输出将如何为“ 100”和“ 500”?

时间:2018-10-04 05:57:16

标签: java

我很困惑为什么以下程序的输出显示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]);
    }
}

7 个答案:

答案 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确实在评论中提出了一个重要观点。我认为缺少的部分是关于数据类型的。

主要有两种数据类型:原始数据类型和非原始数据类型。

原始数据类型包括byteshortlongfloatdoublecharboolean。当您将这些数据类型的变量传递给方法或分配给另一个变量时,就是在传递 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)

如果您调试代码,则可以找到以下操作:

  1. 首先a = [0,0,0]

  2. a = [0,50,0]

  3. o = [0,50,0]

  4. b = [0,50,0]

  5. b = [0,100,0]-> o = [0,100,0]-> a = [0,100,0]

  6. 打印出a [1] = 100

  7. o [1] = 500-> o = [0,500,0]-> b = [0,500,0]-> a = [0,500,0]

  8. 打印出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)

基本上,变量oba都是对同一数组的引用。 因此,无论您使用这些引用中的哪一个来修改数组的第二个元素,数组的第一个元素都会更改。

首先,您使用a[1]=50将其更改为50 然后使用b[1]=100将其更改为100 然后使用(int[] o)[1]=500

将其更改为500

答案 5 :(得分:0)

在这里,您创建了一个数组对象a,并在位置1处初始化了50。 Object oa的引用变量,表示两者都保存着保存值和位置。之后,您创建了b的另一个参考变量o,这里bo的参考变量,oa的参考变量,因此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中的任何一个对数组所做的任何更改都将完成同一数组。