-1

以下代码编译成功。但是我只是在其实现中的方法 moveP 的名称之前添加了静态一词。在此之前,我收到错误“无法对非静态字段 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;
    }

}
4

1 回答 1

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;
        }

    }

关于可读性的代码的第一个改进可能是将您的类和方法重命名为字符长度,因此无需水平滚动。

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

然而,这里有一个版本 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;
        }

    }

在第二步中,我们要查看修改点的方法。您想在此处存档的内容有两种可能性(还有更多,但我选择两个通用的),因此有两种方法:

    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;
        }

    }

因为与我们的老板的无聊会议,他们和你一样拥有相同的软件工程知识,所以我必须回到这里工作,这是一个没有评论的最终版本。最后一步使您的观点提供一种移动自身的方法,而不是让代码允许移动交付的观点(这也可以):

    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”。
  • 在我成为那本书后的头两年里,我不断尝试像你一样做的事情,并试图完全理解它们为什么有效或为什么不有效
  • 两年后,我已经完整地阅读了这本书超过 20 遍。

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

于 2013-10-28T09:20:15.667 回答