2016-05-18 82 views
0

這裏一般是Java和OOP的新手。對象創建流程如何在Java中工作?

我想了解什麼時候可以使用對象的成員。具體來說,爲什麼我不能在類中調用實例變量時將構造函數傳遞給構造函數?下面的代碼示例如下:

public class Point { 

    public String name; 

    { 
     name = "Henry"; 
    } 

    public Point() 
    { 
     this(this.name); // cannot reference this before supertype constructor has been called 
    } 

    public Point(String name) 
    { 
     this.name = name; 
    } 

} 

之前有人問過這樣的問題,但我不知道如何向Google詢問我在這裏解釋的內容。我知道我不能在this(this.name)調用中引用this.name,因爲尚未創建對象引用,但Java如何調用構造函數?

該構造函數將要執行的唯一時間是用new Point()當創建一個對象,而此時的對象引用可用,編譯器不會有什麼可抱怨的。如果有可能將this.name分配給一個變量,然後將其傳遞給this(variable),它會起作用嗎?什麼是巨大的差異?我在這裏完全誤解了一些東西。

這是我如何可視化它,這顯然是不正確的:

Point myPoint = new Point();

myPoint.name現在等於"Henry"

Point()構造函數中,執行this(this.name) // which should be "Henry"

+0

無聊的細節應該主要在https://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html(在你的情況下,如果超類聲明瞭,會發生什麼字段,並希望將其設置在它的構造函數中?這就是爲什麼超級必須運行之前,你可以使用任何東西) – zapl

+0

當你做'新的Point()',那就像'new'是一個方法,返回一個引用'在堆上構建的Point對象(引擎蓋下只是一些內存,它包含所有實例變量/引用/ ... https://dzone.com/articles/java-object-memory)。它不會首先創建一個「對象」。它直接是一個「點」。但是'Point'是一個Object(通過繼承),所以'Object'構造函數將會發現它所期望的。因此,當你「延長」時你不能拿走。 – zapl

回答

1

該構造函數將要執行的唯一時間是使用新的點(),而此時一個對象的引用將可創建對象時,編譯器不會有什麼可抱怨關於。

我想說的是,這裏的關鍵點是對象引用僅適用後的構造函數被調用。因此,在期間引用這個,構造函數的操作沒有任何意義。

還要記住,通過繼承,可以在實例化/創建特定對象之前調用多個構造函數。例如:

public class ParentPoint { 
    public String name = "Parent Point"; 

    public ParentPoint() { 
     // do something 
    } 
} 

public class Point extends ParentPoint { 

    public Point() { 
     super(); 
     // do something else 
    } 

} 

在這種情況下,你有兩個構造函數被調用之前的一點是完全實例化(所以你在OP提到的流動並不總是那麼簡單)。

澤維爾·席爾瓦的答案代碼是一個很好的,並且還具有getter和setter方法將是理想太:

public class Point { 

    public String name = "Henry"; 

    public Point() { 

    } 

    public Point(String name) { 
     this.name = name; //changes current value (Henry) to the one sent as an argument. 
    } 

    public void setName(String newName) { 
     this.name = newName; 
    } 

    public String getName() { 
     return this.name; 
    } 


    public static void main(String[] args) { 
     Point pointA = new Point(); 
     Point pointB = new Point("Other name"); 

     System.out.println(pointA.name); // Henry 
     System.out.println(pointB.name); // Other name 

     pointA.setName("New name"); 
     System.out.println(pointA.getName()); // New name 
    } 
} 

最後一位演示getter和setter,代碼的其餘部分不變。

+0

謝謝,我讀了更多,並理解該對象只有在構造函數執行後才被初始化。我不能在'this()'內引用'this.name',因爲這樣做會試圖在執行超類構造函數之前操作引用。我還發現一個構造函數只能鏈接到另一個構造函數。因此'this(this.name)'被用來代替'super()'期望'Point(String name)'(這是this()'指向的)來執行它,但是被告知要處理在任何構造函數執行'super()'之前調用'this.name'。我有權利嗎? –

+0

延誤的道歉 - 我有點不確定你的評論的某些方面,但是,你說的話似乎是正確的整體。 –

0

你可以完成你的目標是清空this(this.name)構造函數 - 這樣,調用一個空構造函數 - 新的Point() - 讓na我作爲亨利,並使用其他構造函數 - 例如新點(「Bob」) - 會將該名稱(「Bob」)設置爲名稱。

我相信你也可以通過將「this」替換爲「super」來實現。

2

我不知道,因爲它是一個有點混亂,這完全回答你的問題,但我會給我最好的:

爲了創建使用new操作,就像Point point = new Point();一個新的對象。 您的對象可以/應該包含屬性,並且在創建public String name;時啓動了它(儘管您應該搜索此內容是因爲它們不應該公開)。如果您必須爲屬性指定默認值,則必須在聲明後立即執行此操作(例如public String name = "Henry";)。再次,您可能需要搜索Java常量以解決此問題。

此代碼可能會幫助您瞭解(我覺得)你想做的事:。

public class Point { 

    public String name = "Henry"; 

    public Point() { 

    } 

    public Point(String name) { 
     this.name = name; //changes current value (Henry) to the one sent as an argument. 
    } 


    public static void main(String[] args) { 
     Point pointA = new Point(); 
     Point pointB = new Point("Other name"); 

     System.out.println(pointA.name); 
     System.out.println(pointB.name); 
    } 
} 

在這段代碼中,你可以找到一個空對象(new Point();)和一個名爲「其他名稱」(new Point("Other name");)的實例化

如果你運行它,你可以看到兩個實例之間的區別。

希望這可以幫助你!

編輯: P.S.你也可能想搜索一下getter/setters。

+0

這是一個很好的答案,但如果你想採取漫長的路線,你可以簡單地找到關於這個問題的文檔,以獲得更詳細的視圖。 https://docs.oracle.com/javase/tutorial/java/concepts/ –