将一个原始变量分配给另一个原始变量与另一个原始变量分配
我想了解原始和对象引用变量的行为方式有何不同。 我使用了Kathy Sierra的OCA / OCP Java SE7中的以下代码作为示例:
public class VariableTesting { public static void main(String[] args) { int a = 10; System.out.println("a= " + a); int b = a; b = 30; System.out.println("a= " + a + " after change it to b and b is " + b); Dimension a1 = new Dimension(5, 10); System.out.println("a1.height = " + a1.height); Dimension b1 = a1; b1.height = 30; System.out.println("a1.height= " + a1.height + " after change to b1"); } }
在上面的代码中,我得到a = 10;
的值a = 10;
在改变b
的值之前和之后。
原始变量大小写的输出是:
a = 10 a = 10 after change it to b and b is 30
但是,在对象引用变量中,一旦我更改了b1.height = 30;
的值,我就得到一个不同的值b1.height = 30;
参考变量大小写的输出是:
a1.height = 10 a1.height = 30 after change to b1
书中提到,在这两种情况下都会复制位模式并放置新的副本。 如果这是真的,那么为什么我们会得到不同的行为呢?
这是引用和基元之间的基础差异。 在这两种情况下,您都获得了实际值 ,但只有在对象的情况下,您才有可能影响其他任何用法的结果。
让我们来看看代码吧。
int a = 10; int b = a;
这两个声明如下:
- 将值10分配给名为
a
的int标识符。 - 将a的值分配给名为
b
的int标识符。
到现在为止还挺好。 我们没有说过a
被b
引用; 我们只是在接受价值观。
如果我们宣布:
b = 30;
我们说取值30并将其分配给标识符b
。
那时我们什么都不做; 它已包含值10
。 这就是a
和b
不同的原因。
现在,当我们到达目标时,表面上的事情并没有真正改变……
Dimension a1 = new Dimension(5, 10); Dimension b1 = a1;
我们将其翻译为:
- 将具有(int)参数5和10的新Dimension的实例化值分配给
Dimension
标识符a1
。 - 将
a1
的值分配给Dimension
标识符b1
。
我们仍然在这里分配值 ,因为Java是按值传递的 。 这里的踢球者是在Java中,对象的值仍然是对该对象的引用。
通过上面的例子, a1
和b1
指向同一个实例 。
现在,当我们说明这一点时:
b1.height = 30;
我们实际上在说:
- 将值30分配给通过值
b1
解除引用的字段height
。
我们仍然在这里提到b1
的值,它与a1
。 这就是你看到差异的原因; 因为a1
和b1
引用相同的值(它是相同的引用),所以通过标识符b1
进行的任何更改都通过a1
反映出来。
只有一个例子
当你说
Dimension b1= a1; // <-- assigns reference of a1 to b1.
您将a1
引用的引用地址分配给 b1
。 因此,当您通过b1
修改height
字段时,您还修改了a1
。
b1.height=30; // <-- a1.height = 30
创建另一个实例
如果你想让b1
成为一个独特的referene,那么你使用new
。
Dimension b1= new Dimension(a1.width, a1.height); // <-- creates a new Dimension
Dimension a1= new Dimension(5,10); System.out.println("a1.height = "+ a1.height);
//复制参考a1 —> b1
尺寸b1 = a1; // 第1行
b1.height=30; // line 2 System.out.println("a1.height= "+ a1.height +" after change to b1")// line 3
在line1执行之后,变量b1保存变量a1中保存的引用的副本 。 VM中仍然只有一个Dimention对象的副本,但现在有两个对该对象的引用副本 。
由于变量a1和b1保持对同一对象的引用,因此可以使用任一变量对对象进行更改,并且这些更改也可以通过其他变量可见。
因此,当第2行和第3行执行时,您得到以下输出:
更改为b1后a1.height = 30
此行为不是特定于对象; 数组也会发生同样的事情,如下面的代码所示:
char[] greet = { 'h','e','l','l','o' }; // greet holds an array reference char[] cuss = greet; // cuss holds the same reference cuss[4] = '!'; // Use reference to change an element System.out.println(greet); // Prints "hell!"