假设我有一堆用于不同目的的类实例,所以我希望能够直接通过名称引用它们:
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关键字时,该对象引用的“值”是否会发生变化?谢谢!
答案 0 :(得分:7)
您的动物阵列将不受影响。
也许这会让你更容易想象。您的初始设置如下 这样:
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指代当前指的是”。
答案 1 :(得分:2)
当您为名称animals
分配不同的引用(例如“新”版本)时,您的llama
数组会保留您放置的引用(“旧”版本)。
换句话说,数组包含对值(对象)的引用,而不是对用于构建数组的特定表达式的引用(这些表达式是变量的简单名称还是更复杂的表单)。
答案 2 :(得分:1)
当你像你一样初始化动物数组时,你将在数组中放置一个引用的副本(它与对象的副本不同)。这真的很简单,我无法相信没有人使用过那些完全相同的词......
答案 3 :(得分:1)
这与传值或传递引用无关,也与new
无关。你需要理解的是变量,表达式和引用之间的区别。关键是:
SomeObject[] animals = {aardvark, llama, tiger, chicken};
这是用于创建数组并使用引用填充数组的语法糖。大括号内部发生的是有一个被评估的表达式列表。这些表达式是您之前声明和初始化的变量,但变量只是包含对象引用的内存地址的名称。表达式计算放入数组的内存地址(引用)的内容 - 这隐式地创建了引用的副本。因此,复制的引用完全独立于变量。当你考虑这个问题时,可能会更容易理解:
SomeObject[] animals = {aardvark, llama, tiger, new SomeObject()};
这里,最后一个表达式使用new
来创建一个对象。表达式求值为对新创建的对象的引用,该对象作为 only 对该对象的引用放入数组中 - 是没有变量,它直接引用它!
答案 4 :(得分:0)
不,不会。它创建一个新实例,表达式的值将是对创建的实例的引用。赋值只是将变量设置为新对象。它不会影响对前一个对象的任何其他引用。
基本上,您可以将其视为两个独立的操作:
SomeObject newInstance = new SomeObject();
oldInstance = newInstance;
oldInstance
只包含一个引用,而赋值只会改变它。
它与传值完全无关。你没有在任何地方传递任何物体。
答案 5 :(得分:0)
int a = 1;
int b = 2;
int[] ary = { a, b };
a = 2;
// ary[0] still yields 1
答案 6 :(得分:0)
更改llama
不会更改数组。正如你所说,Java是“按值传递”。把llama
想象成一个小盒子,上面写着你可以找到骆驼的地方。创建数组时,llama
中的引用将复制到数组中。因此,当您稍后修改llama
时,您将不会弄乱阵列。
答案 7 :(得分:0)
数组应该保持不变,因为数组的所有元素实际上都是指向堆上可以找到实际信息的点的指针。
所以在你的数组中,有一个对堆上某个点的引用。然后你在堆上创建另一个点,并有一个容器保持,但另一个仍然存在,并指向旧的locatoin。
因此,您的阵列应该保持不变。请注意,联系的唯一方法是通过相关数组的x'd元素。
答案 8 :(得分:0)
使用调试器时,您可以看到何时拥有相同的对象或新对象。当同一个对象以多种方式可见时,它也可以帮助您。