等式 Java 数组中的奇怪之处:引用与指针 [英] Weirdness in Equated Java Arrays: References vs. Pointers

查看:21
本文介绍了等式 Java 数组中的奇怪之处:引用与指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在理解下面代码中发生的事情时遇到问题.数组 cd 的行为正是我所期望的.但是ab 是怎么回事?(我也用普通的标量变量尝试了这个,在任何一种情况下都没有发生任何令人惊讶的事情.)

Having a problem understanding what's going on n the code below. The behavior of arrays c and d is what I would expect. But what's going on with a and b? (I also tried this with normal, scalar variables, and nothing surprising happens in either case.)

将输出复制到 RH 注释中.

The output is copied to the RH comments.

import java.util.Arrays;

public class ArraysParadox {

    public static void main(String[] args) {

        int[] c = {1, 2, 3};
        int[] d = {6, 5, 4, 3};

        System.out.print("c:       ");
        System.out.println(Arrays.toString(c)); // c:       [1, 2, 3]

        System.out.print("d:       ");
        System.out.println(Arrays.toString(d)); // d:       [6, 5, 4, 3]

        System.out.println("--- swap ---");
        int[] tmp = c;
        c = d;
        d = tmp;    // <----- Magic?

        System.out.print("c' (=d): ");
        System.out.println(Arrays.toString(c)); // c' (=d): [6, 5, 4, 3]

        System.out.print("d' (=c): ");
        System.out.println(Arrays.toString(d)); // d' (=c): [1, 2, 3]

        System.out.println("--- c = 0 ---");
        Arrays.fill(c, 0);
        System.out.print("c (=0):  ");
        System.out.println(Arrays.toString(c)); // c (=0):  [0, 0, 0, 0]

        System.out.print("d (=c):  ");
        System.out.println(Arrays.toString(d)); // d (=c):  [1, 2, 3]

        System.out.println("--- d = 1 ---");
        Arrays.fill(d, 1);
        System.out.print("c (=d):  ");
        System.out.println(Arrays.toString(c)); // c (=d):  [0, 0, 0, 0]

        System.out.print("d (=1):  ");
        System.out.println(Arrays.toString(d)); // d (=1):  [1, 1, 1]

        System.out.println("================");

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

        System.out.print("a:       ");
        System.out.println(Arrays.toString(a)); // a:       [1, 2, 3]

        System.out.print("b:       ");
        System.out.println(Arrays.toString(b)); // b:       [6, 5, 4, 3]

        a = b;
        System.out.print("a (=b):  ");
        System.out.println(Arrays.toString(a)); // a (=b):  [6, 5, 4, 3]

        System.out.println("--- α = 0 ---");
        Arrays.fill(a, 0);
        System.out.print("a (=0):  ");
        System.out.println(Arrays.toString(a)); // a (=0):  [0, 0, 0, 0]
        System.out.print("b (=a?): ");
        System.out.println(Arrays.toString(b)); // b (=a?): [0, 0, 0, 0]    ???

        System.out.println("--- b = 1 ---");
        Arrays.fill(b, 1);
        System.out.print("b (=1):  ");
        System.out.println(Arrays.toString(b)); // b (=1):  [1, 1, 1, 1]
        System.out.print("a (=b?): ");
        System.out.println(Arrays.toString(a)); // a (=b?): [1, 1, 1, 1]
    }
}

根据这篇文章,cd 的可交换性表示按值传递:Java 是按值传递的,该死!.(我还查看了 java 数组按引用传递不起作用?,但我看不懂提问者的英语,方法调用模糊了示例.)

The swapability of c and d indicates pass-by-value according to this post: Java is Pass-by-Value, Dammit!. (I also looked at java array pass by reference does not work?, but I can't understand the asker's English, and the method call obscures the example.)

请注意,注释掉 d = tmp; 行后,cd 表现出与 a<相同的奇怪行为/code> 和 b.我仍然不知道该怎么做.

Notice that with the line d = tmp; commented out, c and d exhibit the same odd behavior as a and b. Still I don't know what to make of it.

谁能解释一下 ab 的行为如何用传值来解释?

Can anyone explain how a and b's behavior can be explained with pass-by-value?

事实证明,我帖子中的主要问题不是按值传递,而是别名.为了明确传递值和指针之间的区别,我在我的代码中添加了以下方法并用它来(尝试)交换 cd (由上面链接的 JavaDude 文章链接的文章建议).

It turns out the main issue in my post is not pass-by-value, but aliasing. To be clear about the distinction between pass-by-value and pointers, I added the following method to my code and used it to (try to) swap c and d (suggested by an article linked by JavaDude's article linked above).

static <T> void swap (T c, T d) {
    T tmp = c;
    c = d;
    d = tmp;
}

结果是 cd 返回原样.如果 Java(如 C)将指向 cd 的指针传递给方法,这将有效,但它只是传递它们的值,而保持原始变量不变.

The result is that c and d come back unchanged. This would have worked if Java (like C) passed along pointers to c and d to the method, but instead it simply passes their values, leaving the original variables unchanged.

a = b 更改为 a = b.clone();a = Arrays.copyOf(b, b.length); 给出了我期望的行为.此代码也有效:

Changing a = b to a = b.clone(); or to a = Arrays.copyOf(b, b.length); gives the behavior I was expecting. This code also works:

    int[] tmp = new int[b.length];
    System.arraycopy( b, 0, tmp, 0, b.length );
    a = tmp;

此处描述了相对时间.

推荐答案

这里没有什么奇怪"的地方:数组变量是对实际数组的引用(在其他语言中也称为指针)).当您操作数组变量时,您所做的只是操作指针.

There is nothing "weird" going on here: array variables are references to the actual arrays (also known as pointers in other languages). When you manipulate array variables, all you do is manipulating pointers.

当你将一个数组变量赋值给另一个变量时,你会为你赋值的变量所指向的数组创建一个别名,并使之前被赋值的变量所指向的数组成为垃圾收藏.因为赋值 a = b 使 a 成为 b 的别名,所以用数据填充 b 的作用与用数据填充a:一旦赋值完成,ab 只是同一事物的两个不同名称.

When you assign an array variable to another one, you create an alias to the array pointed to by the variable you assign, and make the array previously pointed to by the variable being assigned eligible for garbage collection. Because the assignment a = b makes a an alias of b, filling b with data acts exactly the same as filling a with data: once the assignment is complete, a and b are merely two different names for the same thing.

按值传递而言,您的示例中没有任何内容:按值传递的概念仅适用于将对象作为参数传递给调用的方法时.在您的示例中,变量 abcd 不是方法参数,它们是局部变量.您确实通过引用方法 toStringfill 来传递它们(或者更准确地说,您通过值将对象的引用传递给 toStringfill,因为在 Java 中一切都是按值传递的),这就是为什么 fill 对数组所做的修改在方法返回时可见.

As far as pass by value is concerned, none of it is going on in your example: the concept of passing by value applies only when you pass objects as parameters to the methods that you call. In your example, variables a, b, c, and d are not method parameters, they are local variables. You do pass them by reference to methods toString and fill (or more precisely, you pass by value the references to your objects to toString and fill, because in Java everything is passed by value), that is why modifications to your arrays done by fill are visible upon the return from the method.

这篇关于等式 Java 数组中的奇怪之处:引用与指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆