2013-10-28 62 views
-1

以下代碼成功編譯。但是我剛剛在方法moveP的名字前添加了static這個詞。在此之前,我得到的錯誤「無法使非靜態字段moveP(PointForPassReferenceTypeParameterByValue)的靜態引用」 我的問題是爲什麼?我傳遞的對象是靜態的?我的意思是靜態參考在這裏意味着什麼? 如果我用p.moveP(p)替換callP moveP(p)會怎麼樣?無法對非靜態類型的方法進行靜態引用Point

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

} 
+2

請閱讀http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html - 並查看右側的所有「相關」問題。 –

+0

請參閱http://stackoverflow.com/questions/3903537/i-want-to-know-the-difference-between-static-method-and-non-static-method – Ashish

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

    } 

第一個改進你的代碼就可讀性可能必須對您的類和方法重命名爲一個sencefull字符長度,所以沒有人需要水平滾動。

現在第二個問題是您嘗試存檔。我假設你只是想獲得一個代碼,你有一個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; 
     } 

    } 

在第二步,我們要看看你的方法,修改一個點。有你想在這裏存檔哪兩個possibilitys(當然還有更多,但我去了兩個普通的)和thatfore使兩種方法:

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

    } 

因爲我們的老闆有軟件工程的知識,同樣像你剛纔endet和我得回到這裏工作的borring會議是沒有意見的最終版本。最後一步使你的觀點提供了一種移動自己的方法,而不是允許移動交付點的代碼(這就是我們所說的)。以及):

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

    } 

我是絕對沒有IDEAR如果這能幫助你,萬一它這裏是我開始學習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的方式,成爲一個完全可以接受的軟件developper在Java10年+經驗(只有英語接受的技巧...沒有實際的,對不起,我知道它很可怕)。

  • 我收到了一本書,有589頁,標題爲「學習Java從初級到專業」。
  • 在頭兩年後,我成了這本書就像你做我試過汽車無事,並試圖完全理解爲什麼他們的工作或他們爲什麼不
  • 2年後,我已經讀過那本書完全地超過20倍。

現在是時候讓我回去工作,並祝你好運和有趣的學習java。

+0

無論您是否評價或接受此答案都不符合我的興趣。但是,一旦你成爲一名優秀的程序員,請記得幫助剛剛開始的程序員;) – JBA

+0

謝謝你的廣泛回答,其中也包括一些指導。我非常感謝。我很感謝你,我會記住你的建議,你現在正在幫助我,並且在我可以幫助他人的時候會幫助我回報:) 我會尋找你建議的書。再次感謝。祈禱。 – user2882662

+0

你能告訴我這本書的作者名字嗎? – user2882662

相關問題