[英]How does JVM handle references to an object that is then set to a new object value using new keyword
[英]Does the “new” keyword change the value of an object reference?
假設我有一堆用於不同目的的類實例,所以我希望能夠直接通過名稱引用它們:
SomeObject aardvark = new SomeObject();
SomeObject llama = new SomeObject();
SomeObject tiger = new SomeObject();
SomeObject chicken = new SomeObject();
但是我還想要一個數組來輕松迭代:
SomeObject[] animals = {aardvark, llama, tiger, chicken};
我的問題是這個。 當我這樣做時會發生什么:
llama = new SomeObject();
我將創建一個全新的美洲駝對象。 這對我的動物陣列有何影響? 它會引用新的llama對象,還是以某種方式引用舊的llama對象的副本?
我知道Java是“通過價值傳遞”,但我仍然對這樣的東西感到困惑。 當我使用NEW關鍵字時,該對象引用的“值”是否會發生變化? 謝謝!
您的動物陣列將不受影響。
也許這會讓你更容易想象。 您的初始設置如下所示:
chicken ---------------------------> SomeObject
tiger ---------------------> SomeObject ^
llama -------------> SomeObject ^ |
aardvark --> SomeObject ^ | |
^ | | |
| | | |
animals -----> {[0], [1], [2], [3]}
當你這樣做:
llama = new SomeObject();
你正在創建一個新的“SomeObject”,然后改變llama指向它。
chicken ---------------------------> SomeObject
tiger ---------------------> SomeObject ^
SomeObject ^ |
aardvark --> SomeObject ^ | |
^ | | |
| | | |
animals -----> {[0], [1], [2], [3]}
llama -------> SomeObject
要記住的重要一點是(非原始)變量和數組元素只是對象的引用,每當你看到“x = y;”時 (即使x是數組下標),它意味着“使x指代當前所指的y”。
當您為llama
命名不同的引用(例如“新”版本)時,您的animals
數組將保留您放在那里的引用(“舊”版本)。
換句話說,數組包含對值(對象)的引用,而不是對用於構建數組的特定表達式的引用(這些表達式是變量的簡單名稱還是更復雜的表單)。
當你像你一樣初始化動物數組時,你將在數組中放置一個引用的副本(它與對象的副本不同)。 它真的那么簡單,我無法相信沒有人使用過那些完全相同的詞......
這與傳值或傳遞引用無關,也與new
無關。 你需要理解的是變量,表達式和引用之間的區別。 關鍵是這樣的:
SomeObject[] animals = {aardvark, llama, tiger, chicken};
這是用於創建數組並使用引用填充數組的語法糖。 大括號內部發生的是有一個被評估的表達式列表。 這些表達式是您之前聲明和初始化的變量,但變量只是包含對象引用的內存地址的名稱。 該表達式的計算結果被放入數組的內存地址(引用)的內容 -這隱含創建引用的副本。 因此,復制的引用完全獨立於變量。 當你考慮這個問題時,可能會更容易理解:
SomeObject[] animals = {aardvark, llama, tiger, new SomeObject()};
這里,最后一個表達式使用new
來創建一個對象。 表達式求值為對新創建的對象的引用,該對象作為對該對象的唯一引用放入數組中 - 沒有直接引用它的變量!
不,不會。 它創建一個新實例,表達式的值將是對創建的實例的引用。 賦值只是將變量設置為新對象。 它不會影響對前一個對象的任何其他引用。
基本上,您可以將其視為兩個獨立的操作:
SomeObject newInstance = new SomeObject();
oldInstance = newInstance;
oldInstance
只包含一個引用,賦值將改變它。
它與傳值完全無關。 你沒有在任何地方傳遞任何物體。
不,你的例子是這樣的:
int a = 1;
int b = 2;
int[] ary = { a, b };
a = 2;
// ary[0] still yields 1
改變llama
不會改變陣列。 正如你所說,Java是“按值傳遞”。 把llama
想象成一個小盒子,上面寫着你可以找到駱駝的地方。 創建數組時,將llama
的引用復制到數組中。 因此,當您稍后修改llama
,您將不會弄亂陣列。
數組應保持原樣,因為數組的所有元素實際上都是指向堆上可以找到實際信息的點的指針。
所以在你的數組中,有一個對堆上某個點的引用。 然后,您在堆上創建另一個點並擁有一個容器,但另一個仍然存在,並指向舊的locatoin。
所以,你的數組應保持不變。 請注意,聯系的唯一方法是通過相關數組的x'd元素。
使用調試器時,您可以看到何時擁有相同的對象或新對象。 當同一個對象以多種方式可見時,它也可以幫助您。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.