为什么从基元创建数组会复制它们?

时间:2016-01-21 07:10:44

标签: java arrays

在程序中

public static void main(String[] args){
    int x = 1;
    int y = 2;
    int[] z = new int[]{x, y};
    z[0] = 3;
    System.out.println(x); //prints 1
}

我预计会打印3张。但是1是。为什么?我认为Java只复制引用,即当我们将refrence传递给方法时,该方法将使用对同一对象的另一个引用。它就像C ++指针和原始类型。

所以我试着咨询MDN's documentation并没有找到任何有用的信息。也许我对Java中的原始类型有一些误解。你能澄清一下吗?

4 个答案:

答案 0 :(得分:11)

  

为什么从基元创建数组会复制它们?

完全相同的原因:

int a = 5;
int b = a;

...将a的值复制到b,而不在ab之间创建任何类型的链接:被复制,而不是对变量的某种引用。

重新评论:

  

但是当我们操作引用类型时,引用副本,不是吗?

是的,确实如此,就像在int情景中复制数字一样。

无论b = aa是原始类型变量还是引用类型变量,

b(或您的数组初始值设定项)都完全相同a中的复制b,然后ab之间没有正在进行的链接。

唯一的区别是,当你处理引用类型时,变量中的值不是实际值,它是实际内容的引用。因此,将该引用从一个变量复制到另一个变量只会使这两个变量引用相同的内容,就像我上面的代码使ab都具有值5一样。

考虑一下:让我们创建一个列表:

List<String> a = new ArrayList<String>();

这在内存中给了我们这样的东西:

              +----------+
a(55465)----->| the list |
              +----------+

变量a包含一个值,该值是对象的引用。我已将上面的值描述为55465,但我们实际上从未在Java代码中看到原始值(并且随着垃圾收集的完成而改变)。它只是一个值,就像任何其他值一样,它告诉JVM在内存中找到对象的位置。您可以将其视为包含内存地址的long(这不是它的真实含义,但它在概念上有效)。

现在我们这样做:

List<String> b = a;

现在我们在记忆中有这样的东西:


a(55465)--+
          |    +----------+
          +--->| the list |
          |    +----------+
b(55465)--+

ab都包含引用该列表的

您可以看到它的完全相同:

int a = 5

给我们

a(5)

然后

int b = a;

给我们

a(5)
b(5)

在变量之间复制,传递给函数等。与引用类型的唯一区别在于该值的用途,解释方式。

  

如果是这样,我会说java在复制基元值和引用类型引用的意义上是通过值传递的。正确?

没有。 “按值传递”和“按引用传递”在计算中具有特定含义:它涉及对变量的引用,而不是对象。这是传递参考的样子:

// NOT JAVA; Java doesn't have this
void foo(int &a) { // Fake pass-by-reference thing
    a = 3;
}

int a = 5;
foo(&a); // Fake pass-by-reference operator
System.out.println(a); // 3

传递引用与对象引用无关。他们唯一的共同点是“参考”这个词。 Java是一种纯粹的传值语言。

答案 1 :(得分:0)

Java是通过值传递而不是引用。如果您分配给数组零,那么它不会分配给x

答案 2 :(得分:-1)

你错了:

int x = 1;
int y = 2;
int[] z = new int[]{x, y};
z[0] = 3;
System.out.println(x); //prints 1 // You are printing x (where x = 1)

在此打印xx = 1

如果您打印z[0]而不是x,则会打印3

答案 3 :(得分:-1)

z[0] = 3将数组的值分配给int x