Java数组打印修改值

Java数组打印修改值,java,arrays,Java,Arrays,为什么数组的输出会给出b的修改值 public static void main(String[] args) { int i=0; int a[] = {1,2,3,4}; int b[] = {5,6,7,8}; a=b; b[2] = 9; while(i<4) { System.out.println(a[i]); i++; } } publicstaticvoidmain(字符串[

为什么数组的输出会给出b的修改值

public static void main(String[] args)
{
    int i=0;
    int a[] = {1,2,3,4};

    int b[] = {5,6,7,8};
    a=b;
    b[2] = 9;
    while(i<4)
    {
        System.out.println(a[i]);
        i++;
    }
}
publicstaticvoidmain(字符串[]args)
{
int i=0;
int a[]={1,2,3,4};
int b[]={5,6,7,8};
a=b;
b[2]=9;
而(i是因为ab具有相同的参考值,并且基本上是相同的数据


当您写入
a=b;
时,然后
a
b
指向同一数组,即
{5,6,7,8};


然后,不管您是通过
a
还是
b
更新它,它都会对同一数组进行更改。

当您进行数组声明时,只有大括号中的内容实际存储在内存中。 (实际上,存储了更多的信息,但就问题的范围而言,您可以假装这只是大括号中的内容)

变量“a”和“b”只是指向内存中大括号中值位置的引用

所以当你说 a=b 现在,您的数组引用“a”不再使用存储值指向其原始位置,而是指向“b”也指向的位置和存储值。

a=b
这是一个浅拷贝,因为a和b具有相同的引用,数组“a”的任何更改都将更改数组“b”

如果要复制值(深度复制)


for(int i=0;i在Java中,字节数组是一种特殊类型的对象。在这种情况下,您使用的是类型为
i[
的整数数组。在Java中,对象实例总是被引用,而不是按值保存。如果打印出来,您可以很好地看到发生了什么:

int[] a = { 1, 2, 3, 4 };
int[] b = { 5, 6, 7, 8 };

System.out.printf("Before: a=%s b=%s%n", a, b);

a = b;

System.out.printf("After: a=%s b=%s%n", a, b);

b[2] = 9;

System.out.println(Arrays.toString(a));
将打印:

Before: a=[I@15db9742 b=[I@6d06d69c
After: a=[I@6d06d69c b=[I@6d06d69c
[5, 6, 9, 8]
Before: a=[I@15db9742 b=[I@6d06d69c
After: a=[I@7852e922 b=[I@6d06d69c
[5, 6, 7, 8]
如您所见,它将引用打印为类型
I[
,然后是一个
@
,然后是引用。首先,引用指向两个不同的对象实例,但在
a=b
之后,
a
b
都引用了首先分配给
b
的对象实例。这意味着
a
b
的任何更改都将在同一个obj上进行当然,如果您打印出
a
b
的值也不重要

如果要确保
a
b
更改时不会更改,则需要克隆对象。阵列实现接口时支持克隆:

int[] a = { 1, 2, 3, 4 };
int[] b = { 5, 6, 7, 8 };

System.out.printf("Before: a=%s b=%s%n", a, b);

a = b.clone();

System.out.printf("After: a=%s b=%s%n", a, b);

b[2] = 9;

System.out.println(Arrays.toString(a));
将打印:

Before: a=[I@15db9742 b=[I@6d06d69c
After: a=[I@6d06d69c b=[I@6d06d69c
[5, 6, 9, 8]
Before: a=[I@15db9742 b=[I@6d06d69c
After: a=[I@7852e922 b=[I@6d06d69c
[5, 6, 7, 8]
如您所见,
a
现在指向一个全新的数组实例,其原始值首先由
b
引用


请注意,打印对象引用适用于数组,因为数组不实现
toString
,当需要
字符串时,会自动调用该字符串。在这种情况下,它使用
对象#toString
打印引用,如图所示


如果实现了
toString
,则无法打印出对对象实例的引用。相反,您可以使用
System.identityHashCode(变量)
指示引用是否相等。或者,如果(a==b),则只需使用
当然可以测试引用相等性。

与您的问题无关,但您不应该像在
循环中那样使用harcoded值,而更喜欢使用
b.length
。至于代码样式:始终保持一致。不要使用
a=b
(不带空格)和
b[2]=9
(带空格)。通常,我们会尝试使用更多的空格来增强可读性。如果您不想键入
while(i<4)之类的内容
那么您就可以在开发环境中始终使用漂亮的打印机或格式化程序。@gcourtet这也是我注意到的第一件事。硬编码值非常危险,将来可能会产生隐藏的错误,特别是在以后修改代码和更改长度的情况下。另外,因为Java中的数组是一个对象,与那些原语不同数据类型。当使用赋值运算符=,您将b的对象引用赋值给athanks@MaartenBodewes时,我们将实践这一点。在我看来,传递值与这个问题关系不大;没有调用任何方法。我指定的这篇文章是关于变量和数据在Java中如何工作的一般性文章。如果您理解这些原则,它就是eas我想正确的措辞应该是“因为数组(数组是对象)被两个引用引用”;否则我完全同意,这是正确的答案,尽管是重复的…正如你所看到的,我去掉了你的while循环。如果你仔细观察,你也会发现我使用了
int[]a
,而不是等效的
int[]
。通常前者作为
int[]
明确指出
a
的类型
inta[]
应被视为Java中C语法的遗留。