“new”关键字是否会更改对象引用的值?

时间:2021-11-04 16:57:10

Let's say that I have a bunch of class instances that serve different purposes, so I want to be able to reference them directly by name:

假设我有一堆用于不同目的的类实例,所以我希望能够直接通过名称引用它们:

SomeObject aardvark = new SomeObject();
SomeObject llama = new SomeObject();
SomeObject tiger = new SomeObject();
SomeObject chicken = new SomeObject();

But then I also want an array of them for easy iteration:

但是我还想要一个数组来轻松迭代:

SomeObject[] animals = {aardvark, llama, tiger, chicken};

My question is this. What happens when I do this:

我的问题是这个。当我这样做时会发生什么:

llama = new SomeObject();

I'll be creating a totally new llama object. How does this affect my animals array? Will it be referencing the NEW llama object, or somehow still referencing a copy of the old one?

我将创建一个全新的美洲驼对象。这对我的动物阵列有何影响?它会引用新的llama对象,还是以某种方式引用旧的llama对象的副本?

I know Java is "pass by value", but I still get confused by stuff like this. When I use the NEW keyword, does the "value" of that object reference change? Thanks!

我知道Java是“通过价值传递”,但我仍然对这样的东西感到困惑。当我使用NEW关键字时,该对象引用的“值”是否会发生变化?谢谢!

9 个解决方案

#1


Your animals array will be unaffected.

您的动物阵列将不受影响。

Maybe this'll make it easier to visualize. Your initial setup looks like this:

也许这会让你更容易想象。您的初始设置如下所示:

chicken ---------------------------> SomeObject
tiger ---------------------> SomeObject  ^
llama -------------> SomeObject  ^       |
aardvark --> SomeObject  ^       |       |
                 ^       |       |       |
                 |       |       |       |
animals -----> {[0],    [1],    [2],    [3]}

When you do this:

当你这样做:

llama = new SomeObject();

you're creating a new "SomeObject", and then changing llama to point at it.

你正在创建一个新的“SomeObject”,然后改变llama指向它。

chicken ---------------------------> SomeObject
tiger ---------------------> SomeObject  ^
                     SomeObject  ^       |
aardvark --> SomeObject  ^       |       |
                 ^       |       |       |
                 |       |       |       |
animals -----> {[0],    [1],    [2],    [3]}

llama -------> SomeObject

The important thing to remember is that (non-primitive) variables and array elements are just references to objects, and whenever you see "x = y;" (even if x is an array subscript) it means "make x refer to what y currently refers to".

要记住的重要一点是(非原始)变量和数组元素只是对象的引用,每当你看到“x = y;”时(即使x是数组下标),它意味着“使x指代当前所指的y”。

#2


Your animals array will keep the reference you put there (the "old" version) when you assign a different reference (e.g. the "new" version) to name llama.

当您将不同的引用(例如“新”版本)分配给名称llama时,您的animals数组将保留您放在那里的引用(“旧”版本)。

In other words, the array contains references to values (objects) and not to the specific expressions you used to build the array (whether those expressions are simple names of variables or more complicated forms).

换句话说,数组包含对值(对象)的引用,而不是对用于构建数组的特定表达式的引用(这些表达式是变量的简单名称还是更复杂的表单)。

#3


When you initialize the array of animals like you did, you are putting a copy of a reference in the array (which IS NOT the same as a copy of the object). It's really that simple and I can't believe no one has used those exact same words...

当你像你一样初始化动物数组时,你将在数组中放置一个引用的副本(它与对象的副本不同)。它真的那么简单,我无法相信没有人使用过那些完全相同的词......

#4


This has nothing to do with pass-by-value or pass-by-reference, nor with new. What you need to understand here is the difference between a variable, an expression and a reference. The key line is this:

这与传值或传递引用无关,也与new无关。你需要理解的是变量,表达式和引用之间的区别。关键是这样的:

SomeObject[] animals = {aardvark, llama, tiger, chicken};

This is syntactical sugar for creating an array and populating it with references. What happens inside the braces is that there's a list of expressions that are evaluated. These expressions are variables you've declared and initialized earlier, but the variables are just names for a memory address containing a object references. The expressions evaluate to the content of the memory addresses (the references) which are put into the array - this implicitly creates copies of the references. The copied references are therefore completely independant of the variables. Maybe it becomes easier to understand when you consider this:

这是用于创建数组并使用引用填充数组的语法糖。大括号内发生的是有一个被评估的表达式列表。这些表达式是您之前声明和初始化的变量,但变量只是包含对象引用的内存地址的名称。表达式计算放入数组的内存地址(引用)的内容 - 这隐式地创建了引用的副本。因此,复制的引用完全独立于变量。当你考虑这个问题时,可能会更容易理解:

SomeObject[] animals = {aardvark, llama, tiger, new SomeObject()};

Here, the last expression uses new to create an object. The expression evaluates to a reference to the newly created object, which is put into the array as the only reference to that object - there is no variable which refers to it directly!

这里,最后一个表达式使用new来创建一个对象。表达式求值为对新创建的对象的引用,该对象作为对象的唯一引用放入数组中 - 没有直接引用它的变量!

#5


No it won't. It creates a new instance and the value of the expression will be a reference to the created instance. The assignment will just set the variable to the new object. It won't affect any other references to the previous object.

不,不会。它创建一个新实例,表达式的值将是对创建的实例的引用。赋值只是将变量设置为新对象。它不会影响对前一个对象的任何其他引用。

Basically, you could think of it as two separate operations:

基本上,您可以将其视为两个独立的操作:

SomeObject newInstance = new SomeObject();
oldInstance = newInstance; 

oldInstance holds just a reference and the assignment will change just that.

oldInstance只包含一个引用,赋值将改变它。

It's completely unrelated to pass-by-value. You are not passing any object anywhere.

它与传值完全无关。你没有在任何地方传递任何物体。

#6


no, your example is like:

不,你的例子是这样的:

int a = 1;
int b = 2;
int[] ary = { a, b };
a = 2;
// ary[0] still yields 1

#7


Changing llama will not change the array. As you said, Java is "pass-by-value". Think of llama as a little box that says where you can find the llama. When you create the array, the reference inside llama is copied into the array. So when you modify llama later, you won't be messing with the array.

改变美洲驼不会改变阵列。正如你所说,Java是“按值传递”。把骆驼想象成一个小盒子,上面写着你可以找到骆驼的地方。创建数组时,将llama中的引用复制到数组中。因此,当您稍后修改llama时,您将不会弄乱阵列。

#8


The array should remain as it is, since all elements of an array are actually pointers to a point on the heap where the actuall info can be found.

数组应保持原样,因为数组的所有元素实际上都是指向堆上可以找到实际信息的点的指针。

So in your array, there is a reference to some point on the heap. You then create another point on the heap and have a container hold that, but the other one still exists and will point to the old locatoin.

所以在你的数组中,有一个对堆上某个点的引用。然后,您在堆上创建另一个点并拥有一个容器,但另一个仍然存在,并指向旧的locatoin。

So, your array should remain intact. Do note that the only way to contact is via the x'd element of the array in question.

因此,您的阵列应保持不变。请注意,联系的唯一方法是通过相关数组的x'd元素。

#9


When you use a debugger you can see when you have the same object or a new object. It can also help you when when the same object is visable in multiple ways.

使用调试器时,您可以看到何时拥有相同的对象或新对象。当同一个对象以多种方式可见时,它也可以帮助您。

#1


Your animals array will be unaffected.

您的动物阵列将不受影响。

Maybe this'll make it easier to visualize. Your initial setup looks like this:

也许这会让你更容易想象。您的初始设置如下所示:

chicken ---------------------------> SomeObject
tiger ---------------------> SomeObject  ^
llama -------------> SomeObject  ^       |
aardvark --> SomeObject  ^       |       |
                 ^       |       |       |
                 |       |       |       |
animals -----> {[0],    [1],    [2],    [3]}

When you do this:

当你这样做:

llama = new SomeObject();

you're creating a new "SomeObject", and then changing llama to point at it.

你正在创建一个新的“SomeObject”,然后改变llama指向它。

chicken ---------------------------> SomeObject
tiger ---------------------> SomeObject  ^
                     SomeObject  ^       |
aardvark --> SomeObject  ^       |       |
                 ^       |       |       |
                 |       |       |       |
animals -----> {[0],    [1],    [2],    [3]}

llama -------> SomeObject

The important thing to remember is that (non-primitive) variables and array elements are just references to objects, and whenever you see "x = y;" (even if x is an array subscript) it means "make x refer to what y currently refers to".

要记住的重要一点是(非原始)变量和数组元素只是对象的引用,每当你看到“x = y;”时(即使x是数组下标),它意味着“使x指代当前所指的y”。

#2


Your animals array will keep the reference you put there (the "old" version) when you assign a different reference (e.g. the "new" version) to name llama.

当您将不同的引用(例如“新”版本)分配给名称llama时,您的animals数组将保留您放在那里的引用(“旧”版本)。

In other words, the array contains references to values (objects) and not to the specific expressions you used to build the array (whether those expressions are simple names of variables or more complicated forms).

换句话说,数组包含对值(对象)的引用,而不是对用于构建数组的特定表达式的引用(这些表达式是变量的简单名称还是更复杂的表单)。

#3


When you initialize the array of animals like you did, you are putting a copy of a reference in the array (which IS NOT the same as a copy of the object). It's really that simple and I can't believe no one has used those exact same words...

当你像你一样初始化动物数组时,你将在数组中放置一个引用的副本(它与对象的副本不同)。它真的那么简单,我无法相信没有人使用过那些完全相同的词......

#4


This has nothing to do with pass-by-value or pass-by-reference, nor with new. What you need to understand here is the difference between a variable, an expression and a reference. The key line is this:

这与传值或传递引用无关,也与new无关。你需要理解的是变量,表达式和引用之间的区别。关键是这样的:

SomeObject[] animals = {aardvark, llama, tiger, chicken};

This is syntactical sugar for creating an array and populating it with references. What happens inside the braces is that there's a list of expressions that are evaluated. These expressions are variables you've declared and initialized earlier, but the variables are just names for a memory address containing a object references. The expressions evaluate to the content of the memory addresses (the references) which are put into the array - this implicitly creates copies of the references. The copied references are therefore completely independant of the variables. Maybe it becomes easier to understand when you consider this:

这是用于创建数组并使用引用填充数组的语法糖。大括号内发生的是有一个被评估的表达式列表。这些表达式是您之前声明和初始化的变量,但变量只是包含对象引用的内存地址的名称。表达式计算放入数组的内存地址(引用)的内容 - 这隐式地创建了引用的副本。因此,复制的引用完全独立于变量。当你考虑这个问题时,可能会更容易理解:

SomeObject[] animals = {aardvark, llama, tiger, new SomeObject()};

Here, the last expression uses new to create an object. The expression evaluates to a reference to the newly created object, which is put into the array as the only reference to that object - there is no variable which refers to it directly!

这里,最后一个表达式使用new来创建一个对象。表达式求值为对新创建的对象的引用,该对象作为对象的唯一引用放入数组中 - 没有直接引用它的变量!

#5


No it won't. It creates a new instance and the value of the expression will be a reference to the created instance. The assignment will just set the variable to the new object. It won't affect any other references to the previous object.

不,不会。它创建一个新实例,表达式的值将是对创建的实例的引用。赋值只是将变量设置为新对象。它不会影响对前一个对象的任何其他引用。

Basically, you could think of it as two separate operations:

基本上,您可以将其视为两个独立的操作:

SomeObject newInstance = new SomeObject();
oldInstance = newInstance; 

oldInstance holds just a reference and the assignment will change just that.

oldInstance只包含一个引用,赋值将改变它。

It's completely unrelated to pass-by-value. You are not passing any object anywhere.

它与传值完全无关。你没有在任何地方传递任何物体。

#6


no, your example is like:

不,你的例子是这样的:

int a = 1;
int b = 2;
int[] ary = { a, b };
a = 2;
// ary[0] still yields 1

#7


Changing llama will not change the array. As you said, Java is "pass-by-value". Think of llama as a little box that says where you can find the llama. When you create the array, the reference inside llama is copied into the array. So when you modify llama later, you won't be messing with the array.

改变美洲驼不会改变阵列。正如你所说,Java是“按值传递”。把骆驼想象成一个小盒子,上面写着你可以找到骆驼的地方。创建数组时,将llama中的引用复制到数组中。因此,当您稍后修改llama时,您将不会弄乱阵列。

#8


The array should remain as it is, since all elements of an array are actually pointers to a point on the heap where the actuall info can be found.

数组应保持原样,因为数组的所有元素实际上都是指向堆上可以找到实际信息的点的指针。

So in your array, there is a reference to some point on the heap. You then create another point on the heap and have a container hold that, but the other one still exists and will point to the old locatoin.

所以在你的数组中,有一个对堆上某个点的引用。然后,您在堆上创建另一个点并拥有一个容器,但另一个仍然存在,并指向旧的locatoin。

So, your array should remain intact. Do note that the only way to contact is via the x'd element of the array in question.

因此,您的阵列应保持不变。请注意,联系的唯一方法是通过相关数组的x'd元素。

#9


When you use a debugger you can see when you have the same object or a new object. It can also help you when when the same object is visable in multiple ways.

使用调试器时,您可以看到何时拥有相同的对象或新对象。当同一个对象以多种方式可见时,它也可以帮助您。