我很困惑为什么以下程序的输出显示100和500? 谁能解释这是怎么发生的?
public class ArraysInJava
{
public static void main(String[] args)
{
int[] a = new int[3];
a[1] = 50;
Object o = a;
int[] b = (int[])o;
b[1] = 100;
System.out.println(a[1]);
((int[])o)[1] = 500;
System.out.println(a[1]);
}
}
答案 0 :(得分:4)
让我们一行一行地做...
public class ArraysInJava
{
public static void main(String[] args)
{
int[] a = new int[3]; // a = {0, 0, 0} as default value for int elements is 0
a[1] = 50; // a = {0, 50, 0}
Object o = a; // o = a = {0, 50, 0} - casting affects the variable type, the referenced object remains the same (recall that objects are saved by reference)
int[] b = (int[])o; // b = o = a = {0, 50, 0}
b[1] = 100; // b = o = a = {0, 100, 0}
System.out.println(a[1]); // Prints 100
((int[])o)[1] = 500; // b = o = a = {0, 500, 0}
System.out.println(a[1]); // Prints 500
}
}
所有的转换都不会做任何事情,因为它只会影响您在编译时可以执行的操作。例如,您不能编写o[1]
,因为它在编译时不是数组。
Carlos Heuberger确实在评论中提出了一个重要观点。我认为缺少的部分是关于数据类型的。
主要有两种数据类型:原始数据类型和非原始数据类型。
原始数据类型包括byte
,short
,long
,float
,double
,char
,boolean
。当您将这些数据类型的变量传递给方法或分配给另一个变量时,就是在传递 value 。
int a = 15;
int b = a; // b now holds 15
非原始数据类型(可以称为对象类型)是上述所有类型之外的所有其他类型。这包括数组(也包括基本类型的数组),枚举,类,接口和String
。
当您将这些数据类型的变量传递给方法或将其分配给另一个变量时,您正在传递对象的 reference 。
int[] a = {1, 2};
Object b = a; // "b" now holds the reference (memory address) of the "a"
int[] c = b; // "c" now also points to the exact same array
b = null; // "b" holds no memory reference now, "a" and "c" continues to hold reference of the same array
答案 1 :(得分:1)
如果您调试代码,则可以找到以下操作:
首先a = [0,0,0]
a = [0,50,0]
o = [0,50,0]
b = [0,50,0]
b = [0,100,0]-> o = [0,100,0]-> a = [0,100,0]
打印出a [1] = 100
o [1] = 500-> o = [0,500,0]-> b = [0,500,0]-> a = [0,500,0]
打印出a [1] = 500
这是如何更改a [1]的值。
基本上,有一个数组a一直在改变。
答案 2 :(得分:1)
绘制内存模型并跟踪每个引用,如果您理解这点,则请参阅代码中的注释,以免混淆。 a, b, and o
是引用
a[1]------> 50
a[1]------> 50 <------------o[1]
a[1], b[1]------->50 <---------------o[1]
a[1], b[1] -------->100 <-----------o[1] (but the value 50 is overwritten with 100)
a[1], b[1] -------->500<-----------o[1] (but the value 100 is overwritten with 500)
int[] a = new int[3];
a[1] = 50; // a------> 50,
Object o = a; // a------> 50 <------------o
int[] b = (int[])o; // a, b------->50 <---------------o
b[1] = 100; //a, b -------->100 <-----------o(but the value 50 is overwritten with 100)
System.out.println(a[1]); // so prints 100
((int[])o)[1] = 500; //a, b -------->500<-----------o(but the value 100 is overwritten with 500)
System.out.println(a[1]); // hence prints 500
答案 3 :(得分:0)
您实际上引用的是相同的内存地址(指针),因此,当您更改值时,内存地址中的内容也会更改。
答案 4 :(得分:0)
基本上,变量o
,b
,a
都是对同一数组的引用。
因此,无论您使用这些引用中的哪一个来修改数组的第二个元素,数组的第一个元素都会更改。
首先,您使用a[1]=50
将其更改为50
然后使用b[1]=100
将其更改为100
然后使用(int[] o)[1]=500
答案 5 :(得分:0)
在这里,您创建了一个数组对象a
,并在位置1处初始化了50。
Object o
是a
的引用变量,表示两者都保存着保存值和位置。之后,您创建了b
的另一个参考变量o
,这里b
是o
的参考变量,o
是a
的参考变量,因此b也是参考变量a
。
如果尝试通过任何引用变量更新值,则所有引用将拥有相同的值(意味着,所有引用的值都将更改)。在此示例中,您执行相同的操作。
a
在1处的值由参考变量b
,->第9行更新了
a
在1处的值由参考变量o
,->第11行更新了
答案 6 :(得分:0)
Array是Java中的一个对象。当您对对象使用“ =”赋值运算符时,它实际上指向内存中的同一对象,而不会创建新的对象。像
int[] a = new int[3];
a[1] = 50;
Object o = a; // now o and a will point to same object in memory
//Any changes done in either a or o will reflect in both
int[] b = (int[])o; // now a,b and o pointing to same array in memory
b[1] = 100;
System.out.println(a[1]);
((int[])o)[1] = 500;
System.out.println(a[1]);
因此,内存中只有一个阵列。 a,b和o指向同一数组,因此使用引用变量a,b或o中的任何一个对数组所做的任何更改都将完成同一数组。