我认为关键的误解体现在:
我认为我声明x
,然后y
指代x
。
Java 中的变量包含对对象(和原语,但这在这里并不重要)的引用。唯一可以被变量引用的是对象。变量不是对象,因此没有任何东西可以引用它们。让我们更仔细地考虑这两个代码示例。
在第一种情况下,有两个变量和一个数组:
public static void main(String[] args) {
String[] x = {"A"};
String[] y = x;
x[0] = "B";
System.out.print(x[0] + " " + y[0]);
}
考虑哪些事物是实际值,哪些事物只是引用实际值的引用、指针或句柄(各种)名称,这可能会有所帮助。x
和y
都是变量,这些变量的值是对对象的引用(在这种情况下,是字符串数组)。在这种情况下,的特定值与x
的值相同y
,它是对具有一个元素的数组的引用,即 String "A"
。x[0]
通过检索变量x
具有引用的数组并获取其第一个元素来评估表达式。y[0]
通过检索变量y
具有引用的数组并获取其第一个元素来评估表达式。因为x
和y
持有对同一个数组的引用,数组的第一个元素与自身相同。打印输出为B B
.
在第二种情况下,有两个变量,没有数组。
public static void main(String[] args) {
String x = "A";
String y = x;
x = "B";
System.out.print(x + " " + y);
}
该变量x
包含对字符串的引用"A"
。第一个赋值,String y = x;
保持y
对相同字符串的引用,"A"
。此时,如果您可以修改有关字符串的任何内容(但在 Java 中不能,因为字符串是不可变的),您可以使用x
or来完成y
,并且您会在其中看到结果,因为这两个变量都有引用单个对象。但是,第二个赋值x = "B";
使 a 的值成为x
对不同字符串的引用"B"
。它不会改变 的值y
,它仍然是对字符串的引用"A"
。所以,表达式x
被评估,因为x
持有对字符串的引用"B"
,结果为"B"
. 对表达式y
求值,因为y
持有对字符串 的引用"A"
,所以结果是"A"
。打印输出为B A
.
也许关键点是变量和对象是完全不同的。对象存在,期间。变量保存对对象的引用。当你做类似的事情时
x.doSomething();
您正在检索 的值x
,它是一个对象,然后调用该对象的doSomething()
方法。您可以检索变量引用的对象,并且可以使变量引用不同的对象(通过赋值)。这些是您可以对变量执行的唯一操作。你能做的任何其他事情,都是在对一个对象做。这在以下情况下尤其重要:
String[] x = {"A"}; ; there's an array {"Α"} and the variable `x` _refers_ to it
String[] y = x; ; retrieve the array to which `x` refers, and make `y` refer to it, too
x[0] = "B"; ; retrieve the array to which `x` refers (and to which `y` also refers)
; and make "B" its first element.
String x = "A"; ; there's a string "A", and the variable `x` _refers to it
String y = x; ; retrieve the string to which `x` refers, and may `y` refer to it, too
x = "B"; ; make `x` refer to the string "Β" (has no effect on what `y` refers to)