2012-11-18 67 views
2

我正在學習Java中的類和構造函數。我在示例程序中搞亂了代碼,似乎無法弄清楚究竟發生了什麼。Java中的構造函數中的最終參數

此代碼不會編譯這對我來說很有意義:

class Line { 
Point start; 
Point end; 

Line(final Point start, final Point end) { 

    this.start = new Point(start); 
    this.end = new Point(end); 
    start = new Point(0.4, 0.4); 

}... 

我試圖通過調用Point對象的構造函數分配原來的起點對象引用到另一點的對象。最後的關鍵字與此衝突。

然而,當我刪除從點開始參數final關鍵字...

class Line { 
Point start; 
Point end; 

Line(Point start, final Point end) { 

    this.start = new Point(start); 
    this.end = new Point(end); 
    start = new Point(0.4, 0.4); 

} 

它似乎並沒有真正改變參考,傳遞到線構造的Point對象似乎仍然指向原始對象,並且由Line構造函數的代碼保持不變。那麼是什麼給了?這與這個事實有什麼關係,即所謂的「開始」是在Line構造函數的本地範圍內?

+0

您的構造函數中沒有修飾符。 –

回答

0

它似乎並沒有真正改變參考

你不能改變你用它來調用該方法本身內部的方法的參數的參考。參數(它是對象的引用)的值被複制到方法參數中,因此您有第二次引用同一個對象。在該方法內部,只能修改第二個參考,不能更改原始參考。你唯一能做的就是修改被引用的對象。

5

Java不使用傳遞引用,它總是使用傳值。 實際上,Java中的引用類型只是指針,並不像C#中的引用那樣共享相同的含義。

所以,當你在構造函數中做這樣的說法:

start = new Point(0.4, 0.4); 

原來Point傳遞參數沒有改變。 但是,局部變量(意爲參數)將指向由座標:0,4, 0,4定義的新的Point

爲了更好地理解,閱讀這篇文章:Java is Pass-by-Value, Dammit!

+0

從我正在閱讀的書 - 「當您將對象作爲參數傳遞給方法時,應用的機制稱爲傳遞引用,因爲變量中包含的引用的副本被傳輸到方法,不是該對象本身的副本。「 –

+0

@ user1817031在Java世界中,「引用」這個詞是一個很大的用詞不當。使用術語「參考」是因爲變量不包含實例,而是「指向」它。爲什麼Java創建者不這樣稱呼這個「指針」?因爲,指針的內存可以被操縱,特別是在C中(例如調用這個「取消引用」)。在Java中,「指針」(引用...)不應該看到它分配的內存操縱。你自己說過:「因爲變量中包含的引用的COPY被傳遞給方法」=>所以按值傳遞;「 – Mik378

0

該變量爲局部的構造。因此,爲它分配一個新的引用在構造函數外是沒有意義的,因爲它不在構造函數之外。

實現這種效果的一種方法是將其包裝在另一個對象中。並通過引用可變包裝器。

0

當你做「start = new Point(0.4,0.4);」時,你引用了構造函數接收到的開始。由於構造函數將其定義爲final,因此爲變量賦一個新值是非法的。

詳細情況是,即使您不使用final並在構造函數中更改該值,java仍然使用傳值方法,原始值的值(您作爲參數傳遞給方法)仍然是一樣的。

0

當您通過「this」修改「開始」時。初始化後從「Line(Point start,final Point end){」你不會替換堆棧上的「start」指向的實際對象,而是將新的Point對象分配給堆上的獨立區域上的「start = new Point從現有的和修改現有的指針「開始」(STACK標量類型)指向新分配。

構造函數是一個特殊用途的方法(函數),它是在Java堆對象分配後由java的new運算符調用的。所以當一個方法被調用時,堆棧被分配,任何標量類型(在java中它是基本類型,如int,double,char ...)和REFERENCE在方法中都被分配在堆棧上(而不是堆) 當你編寫語句作爲「最終對象o =新對象()」,你已經在內存中分配了兩件東西。
首先,java堆上的「new Object()」。 (HEAP)
其次,指向上面的堆棧中的「Object o」。 (STACK)
就你而言,你只是試圖覆蓋「標量類型的最終對象o」,它只能在jvm內存(STACK)上讀取。

class Line { 
Point start; 
Point end; 

// On the first line "Line(Point start, Point end) {", 
// two references and two actual Objects that references point to 
// are already allocated in memory. 
// So you've allocated four things. 
Line(Point start, final Point end) { // "start" initialized on stack as final 
    this.start = new Point(start); // tried to modify final variable on stack. 
    this.end = new Point(end); 
    start = new Point(0.4, 0.4); 

}