无法对Point类型的非静态方法进行静态引用

时间:2013-10-28 08:30:39

标签: java

以下代码成功编译。但我刚刚在其实现中的方法moveP的名称之前添加了static一词。在此之前,我收到错误“无法对非静态字段moveP(PointForPassReferenceTypeParameterByValue)进行静态引用” 我的问题是为什么?我传递的对象是静态的?我的意思是静态参考在这里意味着什么? 如果我用p.moveP(p)替换调用moveP(p)怎么办?

package passbyvaluepracticetest;

public class PassReferenceTypeParamenterByValue {
    public static void main (String []args){
        PointForPassReferenceTypeParametersByValue p = new PointForPassReferenceTypeParametersByValue(2, 3);
        System.out.println("The new X and Y postions of the point P after it has been moved by the method p.moveP() are X: " + moveP(p).xPosition + "and Y: " + moveP(p).yPosition + ".");
    }

    public static PointForPassReferenceTypeParametersByValue moveP(PointForPassReferenceTypeParametersByValue del_p){
        del_p.xPosition=10;
        del_p.yPosition=20;
        del_p = new PointForPassReferenceTypeParametersByValue(del_p.xPosition, del_p.yPosition);
        return del_p;
    }
}

public class PointForPassReferenceTypeParametersByValue {
    int xPosition;
    int yPosition;
    PointForPassReferenceTypeParametersByValue(int x, int y){
        xPosition=x;
        yPosition=y;
    }

}

1 个答案:

答案 0 :(得分:1)

我跳了你一个答案,这需要一些时间,所以继续检查一个小时左右(或检查我所做的所有保存,因为格式和让我疯狂的东西..)

首先,您的代码不会按照发布方式进行编译。小心告诉社区它运行但它实际上没有。这与其他帖子的复制相结合,使你的问题变得迟钝。

以下是代码的第一个版本,只需稍加更改即可运行:

    public class PassReferenceTypeParamenterByValue {

        public static void main (String []args){
            PointForPassReferenceTypeParametersByValue p = new PointForPassReferenceTypeParametersByValue(2, 3);
            System.out.println("The new X and Y postions of the point P after it has been moved by the method p.moveP() are X: " + moveP(p).xPosition + " and Y: " + moveP(p).yPosition + ".");
        }

        public static PointForPassReferenceTypeParametersByValue moveP(PointForPassReferenceTypeParametersByValue del_p){
            del_p.xPosition=10;
            del_p.yPosition=20;
            del_p = new PointForPassReferenceTypeParametersByValue(del_p.xPosition, del_p.yPosition);
            return del_p;
        }
    }

    /* Make sure to understand the difference class types
     * 
     * With "pulbic class...." you create a Top-Level class ("normal" java class) which has to reside in its own .java file 
     * So if you want to create a "public class MyClass" it MUST reside in a file MyClass.java. 
     * 
     * If you however want to define multiple classes whithin the same .java file what you need is a so called nested top level 
     * class. It is basicially the same like a top-level class except it is not stored within a own .java file with the same name 
     */
    class PointForPassReferenceTypeParametersByValue {
        int xPosition;
        int yPosition;
        PointForPassReferenceTypeParametersByValue(int x, int y){
            xPosition=x;
            yPosition=y;
        }

    }

关于可读性的代码的第一个改进可能是将类和方法重命名为字符长度,因此没有人必须按时间顺序滚动。

现在第二个问题是您尝试存档的内容。我假设您只是尝试获得一个代码,其中有一个带有x / y位置的Point和一个可以修改这些坐标的方法。通过以上代码能够运行现在你得到了。

然而,这里的版本id更喜欢以下语言独立的面向对象编程概念,如封装和东西(这些概念值得阅读,然后将在Java,.NET,C#等工作)。

好吧我们现在所做的就是称为重构,它会引导我们找到一个更容易接受的代码,这通常更好地理解,维护并且在运行时具有更高的性能。

我们一步一步地这样做。第一步是通过创建一个来遵循面向对象编程的基本规则 更好的版本,你以前的实现基本上是一个点。

    public class PassReferenceTypeParamenterByValue {

        public static void main (String []args){
            MyPoint p = new MyPoint(2, 3);
            //We already use the get/ set methods rather to "rape" your new MyPoint object by directly calling its member variables
            System.out.println("The new X and Y postions of the point P after it has been moved by the method p.moveP() are X: " + moveP(p).getXPosition() + " and Y: " + moveP(p).getYPosition() + ".");
        }

        public static MyPoint moveP(MyPoint del_p){
            del_p.setXPosition(10);
            del_p.setYPosition(20);
            del_p = new MyPoint(del_p.getXPosition(), del_p.getYPosition());
            return del_p;
        }
    }


    /* We call this MyPoint just because the sun is shining bright outside here in switzerland (teaching you how to name things properly 
     * exceeds the bounds of my answer right now. 
     */
    class MyPoint {
        /* Encapsulation: You dont want other classes to directly access your class members (variables) so you define those 
         * as private. Thus to allow other classes to access those private members you provide get/set Methods. Go read about
         * the java bean naming convention of bean propertys and the according get/ set methods right now and make sure to always
         * use that naming pattern in the future (since tonns of frameworks youre maybe using in the future will rely on you following 
         * those standards
         */
        private int xPosition;
        private int yPosition;

        MyPoint(int x, int y){
            xPosition=x;
            yPosition=y;
        }

        /* You dont want to have that for any variable in general but for those that should be accessable (indirectly) from 
         * outside your code. 
         */
        public void setXPosition(int xPosition){
            /* Because you now have two variables (read about visibility of different variable types) with the same name you have 
             * to clearify which of both you mean. By adding 'this' you tell the compiler youre talking about the variable of the
             * object rather than the local one of this method. 
             */

            this.xPosition = xPosition;
        }

        public int getXPosition(){
            /* Here you dont need the 'this' because there is no other local variable with the same name, you can however always 
             * make that clearification so "return this.xPosition" is equal in that case. 
             */
            return xPosition;
        }

        //The same for the yPosition value:
        public void setYPosition(int yPosition){
            this.yPosition = yPosition;
        }

        public int getYPosition(){
            //like told above 'return this.yPosition' is equal to 'return yPosition'
            return this.yPosition;
        }

    }

在第二步中,我们要查看修改Point的Method。你想在这里存档两种可能性(好的还有更多,但我会选择两种常规方法),然后制作两种方法:

    public class PassReferenceTypeParamenterByValue {

        public static void main (String []args){
            MyPoint p = new MyPoint(2, 3);

            System.out.println("The new X and Y postions of the point P after it has been moved by the method p.moveP() are X: " + moveThePointYouDeliverMe(p).getXPosition() + " and Y: " + moveThePointYouDeliverMe(p).getYPosition() + ".");

            System.out.println("The new X and Y postions of the new point P after it has been created by the method p.moveP() are X: " + moveThePointYouDeliverMe(p).getXPosition() + " and Y: " + moveThePointYouDeliverMe(p).getYPosition() + ".");

        }

        /* If you just want to move a point and not create a new, independent (of the one delivered) one you 
         * can just use the set-methods of that point, modify its values and return the updated point.
         * This will best match your above System-out which indicates you still have the same Point object you delivered to that method.
         */
        public static MyPoint moveThePointYouDeliverMe(MyPoint del_p){
            del_p.setXPosition(10);
            del_p.setYPosition(20);
            return del_p;
        }

        /* If you dont want to change the object delivered to your method but rather return a new, independent object
         * your previous approach comes in with a little modification so you dont change the state of the delivered object
         */    
        public static MyPoint copyAndMoveThePointDeliveredMe(MyPoint del_p){
            return new MyPoint(10, 20);
        }
    }


    /* We call this MyPoint just because the sun is shining bright outside here in switzerland (teaching you how to name things properly 
     * exceeds the bounds of my answer right now. 
     */
    class MyPoint {
        /* Encapsulation: You dont want other classes to directly access your class members (variables) so you define those 
         * as private. Thus to allow other classes to access those private members you provide get/set Methods. Go read about
         * the java bean naming convention of bean propertys and the according get/ set methods right now and make sure to always
         * use that naming pattern in the future (since tonns of frameworks youre maybe using in the future will rely on you following 
         * those standards
         */
        private int xPosition;
        private int yPosition;

        MyPoint(int x, int y){
            xPosition=x;
            yPosition=y;
        }

        /* You dont want to have that for any variable in general but for those that should be accessable (indirectly) from 
         * outside your code. 
         */
        public void setXPosition(int xPosition){
            /* Because you now have two variables (read about visibility of different variable types) with the same name you have 
             * to clearify which of both you mean. By adding 'this' you tell the compiler youre talking about the variable of the
             * object rather than the local one of this method. 
             */

            this.xPosition = xPosition;
        }

        public int getXPosition(){
            /* Here you dont need the 'this' because there is no other local variable with the same name, you can however always 
             * make that clearification so "return this.xPosition" is equal in that case. 
             */
            return xPosition;
        }

        //The same for the yPosition value:
        public void setYPosition(int yPosition){
            this.yPosition = yPosition;
        }

        public int getYPosition(){
            //like told above 'return this.yPosition' is equal to 'return yPosition'
            return this.yPosition;
        }

    }

现在我们以“通用”方式查看您的代码,因为这样很糟糕。这两种方法只是设置静态值,但是您希望允许其他人(在本例中包括您自己)以更通用的方式使用该MyPoint类。所以我们允许它们告诉我们必须移动点的新坐标。

    public class PassReferenceTypeParamenterByValue {

        public static void main (String []args){

            MyPoint p = new MyPoint(2, 3);

            System.out.println("Created a Point with coordinates X="+p.getXPosition()+" , Y+"+p.getYPosition());

            int newXPos = 20;
            int newYPos = 10;

            System.out.println("Moving the Point to the new coordinates X="+newXPos+" , Y="+newYPos);

            /* Since you already have a reference 'p' to your point and know that your move-method wont change the reference (e.g. create and return a new 
             * Point Object. you can just call this method without storing the same reference:
             */
            moveThePointYouDeliverMe(p, newXPos, newYPos);

            System.out.println("The point was moved! New coordinates: X="+p.getXPosition()+" , Y+"+p.getYPosition());           

        }

        /* We now allow the outerworld to tell  us where to move that point to.
         */
        public static MyPoint moveThePointYouDeliverMe(MyPoint del_p, int newXPosition, int newYPosition){
            del_p.setXPosition(newXPosition);
            del_p.setYPosition(newYPosition);
            return del_p;
        }

        /* We dont need such a method because the outerworld can already create the same result by directly calling 
         * the constructor of MyPoint providing the values of x/y to the constructor
         * 
         * So delte this comment and this method 
         */    
        /*public static MyPoint copyAndMoveThePointDeliveredMe(MyPoint del_p, int newXPosition, int newYPosition){
            return new MyPoint(newXPosition, newYPosition);
        }*/
    }


    /* We call this MyPoint just because the sun is shining bright outside here in switzerland (teaching you how to name things properly 
     * exceeds the bounds of my answer right now. 
     */
    class MyPoint {
        /* Encapsulation: You dont want other classes to directly access your class members (variables) so you define those 
         * as private. Thus to allow other classes to access those private members you provide get/set Methods. Go read about
         * the java bean naming convention of bean propertys and the according get/ set methods right now and make sure to always
         * use that naming pattern in the future (since tonns of frameworks youre maybe using in the future will rely on you following 
         * those standards
         */
        private int xPosition;
        private int yPosition;

        MyPoint(int x, int y){
            xPosition=x;
            yPosition=y;
        }

        /* You dont want to have that for any variable in general but for those that should be accessable (indirectly) from 
         * outside your code. 
         */
        public void setXPosition(int xPosition){
            /* Because you now have two variables (read about visibility of different variable types) with the same name you have 
             * to clearify which of both you mean. By adding 'this' you tell the compiler youre talking about the variable of the
             * object rather than the local one of this method. 
             */

            this.xPosition = xPosition;
        }

        public int getXPosition(){
            /* Here you dont need the 'this' because there is no other local variable with the same name, you can however always 
             * make that clearification so "return this.xPosition" is equal in that case. 
             */
            return xPosition;
        }

        //The same for the yPosition value:
        public void setYPosition(int yPosition){
            this.yPosition = yPosition;
        }

        public int getYPosition(){
            //like told above 'return this.yPosition' is equal to 'return yPosition'
            return this.yPosition;
        }

    }

因为与我们的老板会面,这些老板具有与您一样努力的软件工程相同的知识,而且我必须回到这里工作,这是一个没有评论的最终版本。最后一步使你的观点提供了一种移动自身的方法,而不是拥有允许移动交付点的代码(也就是o.k.):

    public class PassReferenceTypeParamenterByValue {

        public static void main (String []args){

            MyPoint p = new MyPoint(2, 3);

            System.out.println("Created a Point with coordinates X="+p.getXPosition()+" , Y+"+p.getYPosition());

            int newXPos = 20;
            int newYPos = 10;

            System.out.println("Moving the Point to the new coordinates X="+newXPos+" , Y="+newYPos);

            p.moveMe(newXPos, newYPos);

            System.out.println("The point was moved! New coordinates: X="+p.getXPosition()+" , Y+"+p.getYPosition());           

        }
    }

    class MyPoint {

        private int xPosition;
        private int yPosition;

        MyPoint(int x, int y){
            xPosition=x;
            yPosition=y;
        }

        /* Like polite people polite programms ask things to move rather to just move them away not because the result differs 
         * but the way you got to the result :) 
         */
        public void moveMe(int newXPos, int newYPos){
            /*We own those variables, we have the exclusive right to directly modify those values and are the only ones that dont 
             * need to call the set/get Methods for this
             */
            this.xPosition = newXPos;
            this.yPosition = newYPos;
        }

        public void setXPosition(int xPosition){
            this.xPosition = xPosition;
        }

        public int getXPosition(){
            return xPosition;
        }

        public void setYPosition(int yPosition){
            this.yPosition = yPosition;
        }

        public int getYPosition(){
            return this.yPosition;
        }

    }

如果这对你有帮助,我绝对没有想法,如果它确实是我开始学习java的话。在您完全理解静态上下文并正确使用之前,它是一种简单的方法来摆脱静态上下文:

    public class PassReferenceTypeParamenterByValue {

        public static void main (String []args){
            new PassReferenceTypeParamenterByValue().myDynamicMain();       
        }

        public void myDynamicMain(){
            //Look at this as your new main for now until you understand the static parts in the java world.
            System.out.println("From here on i dont have to care about static stuff...");

            //Place your Code here 
        }
    }

顺便说一下,这就是我学习java的方法,并成为一个十分可以接受的软件开发人员,拥有10年以上的java经验(只有可接受的英语技能......没有道理,对不起,我知道它很可怕)。

  • 我有一本589页的书,其标题为“从初学者到专业学习Java”。
  • 在我成为那本书之后的前两年,我不断尝试像你一样的事情,并试图完全理解他们为什么工作或为什么他们不
  • 2年后,我完全阅读了20多本书。

现在是我回去工作的时候了,祝你好运,学习java。