11

我的一位教授给了我们一些考试练习题,其中一个问题类似于以下内容(伪代码):

a.setColor(blue);
b.setColor(red);
a = b;
b.setColor(purple);
b = a;
//what color is a, and what color is b?

这对我来说似乎非常初级,所以我提出了 a 是“红色”,b 是“红色”的答案,但有人告诉我这是不正确的。我已经分解了我的答案,就像我解决数学问题一样:

a = 15;
b = 12;
a = b; //a becomes 12
b = 13;
b = a; //b becomes 12

但我的思考过程是通过 C 的思想,而不是 Java。我认为两者都有一些通用方法,但也许我错了?是我的答案错了还是我的教授错了?我对 Java 很陌生,虽然我掌握了一些 C、Python 和 Web 逻辑(PHP、Ruby)的命令,所以如果这是一件微不足道的事情(确实如此),我深表歉意。

4

6 回答 6

18

假设您已经创建了两个对象,并创建了变量ab引用它们,那么您最初会得到类似的东西。

a -->  [ white ]     b --> [ white ]

你的前两行改变了对象的颜色,给你

a -->  [ blue  ]     b --> [  red  ]

然后,将变量指向a由 引用的对象b,以便它们都引用同一个对象。你现在有

       [ blue  ]     b --> [  red  ] <-- a

然后更改 引用的对象的颜色b

       [ blue  ]     b --> [ purple ] <-- a

最后,该行b=a;什么也不做,因为b已经引用了与 . 相同的对象a

于 2013-10-21T21:23:13.317 回答
6

这是因为在第一个示例中,aandb是对象,所以这就是每个步骤中发生的情况:

a <-- 是一个对象

b <-- 是一个对象

a.setColor(蓝色); <--a变成蓝色

b.setColor(红色); <--b变成红色

a = b; <-- IMPORTANT ::原始a对象已释放并可用于垃圾回收,现在a拥有bobject的引用,这意味着a并且b现在正在引用同一个对象,即b.

b.setColor(紫色); <-- b 现在是紫色的。因为 a 只指向 b,所以 a 也是紫色的

答案:此时两者ab都是紫色的。

于 2013-10-21T21:18:10.547 回答
4

要意识到的重要一点是,在 line 之后a = b,您不再有两个对象。你有两个变量,它们都指向同一个对象。因此,当您更改该对象的颜色时,两个变量都会反映它。这条线b = a实际上没有做任何事情。

于 2013-10-21T21:16:29.790 回答
3

在 Java 中,将任何作为 Object 的变量视为指向该 Object 类型的值的指针通常是正确的。因此,Java中的以下内容:

Color a = new Color(), b = new Color();

a.setColor(blue);
b.setColor(red);
a = b;
b.setColor(purple);
b = a;

应该在 C++ 中或多或少地做与以下相同的事情:

Color *a = new Color();
Color *b = new Color();

a->setColor(blue); // the value a points to is now blue
b->setColor(red); // the value b points to is now red
a = b; // a now points to the same value as b.
b->setColor(purple); // the value BOTH a and b point to is now purple
b = a; // this does nothing since a == b is already true

(请注意,这与参考资料不同 - 根据本文)。

另请注意,对于原语,Java 变量只是值,而不是指针。因此,在原始整数的情况下,它的行为应该或多或少如您在问题中所期望的那样,因为a = b将 的值设置为a等于 的值b

于 2013-10-21T21:17:30.953 回答
2

a并且b是对对象的引用。当您编写时,a=b将 a 分配给先前分配给 的引用b,因此它们现在都引用同一个对象。

因此,假设您有两个对象 O1 和 O2,它们在开始时分别分配给ab

a.setColor(blue);     // the object O1 is set the color blue
b.setColor(red);      // the object O2 is set the color red
a = b;                // a now references O2, and b still references O2.
b.setColor(purple);   // the object O2 is set the color purple.
b = a;                // b is told to reference O2, which it already is.

如果你想通过 C 的思想来思考,你可以看到ab作为指针,它可以在变量之间交换并且可以修改其数据。

对于像在 C 中那样处理的原始值来说,它是不一样的。

于 2013-10-21T21:16:37.267 回答
2

由于其他人都解释了引用和原语之间的区别,我将解释它是如何在表面下工作的。

所以对对象的引用本质上是一个数字。根据 VM,它将是 32 位或 64 位,但它仍然是一个数字。这个数字告诉你对象在内存中。这些数字被称为地址,通常以十六进制格式写成这样0xYYYYYYYY(这是 32 位地址的示例,64 位地址将是 64 位地址的两倍)。

让我们使用上面的示例,使用 32 位 VM

a.setColor(blue); // Let's assume the object pointed to by a is at 0x00000001
b.setColor(red);  // Let's assume the object pointed to by b is at 0x00000010

/* Now the following makes sense, what happens is the value of 
   a (0x00000001) is overwritten with 0x00000010. 
   This is just like you would expect if a and b were ints.
*/
a = b; // Both a and b have the value 0x00000010. They point to the same object

b.setColor(purple); // This changed the object stored at 0x00000010 

b = a; // This says nothing because both a and b already contain the value 0x00000010

这应该说明引用确实像您在第二个示例中显示的数字一样工作。然而,仅在表面之下,就程序员而言,引用的分配不像原语的分配那样工作。

在 Java 中,您永远不需要担心对象的地址等。在像 C 和 C++ 这样支持较低级别访问的语言中,这变得更加明显和重要。

算术?那么你能做算术和其他你可以用数字做的事情吗?较短的答案是否定的,至少在 java 中没有。

然而,在 C 和 C++ 中,对象指针的递增和递减是完全有效的,并且被大量使用,例如遍历数组。

如果这还不够清楚,请随时提出问题。

于 2013-10-21T21:33:21.393 回答