java - 将数组传递给方法与将原始数据类型传递给方法不一致

标签 java arrays pointers pass-by-reference pass-by-value

understand将数组传递给方法仍然是按值传递,但是传递的“值”是数组的引用。这意味着更改数组的内容将导致内容在较早的帧中更新(如果是递归算法),或者当它返回到主方法时。

import java.util.Arrays;

public class SameArrayPassedOn{
    public static void main(String[] args) {
        int[] a = {1,1,1};

        print(a);
        fun(a,0);
        print(a);
    }

    static void fun(int[] b, int count)
    {
        if(count == 1)
            return;

        b[0] = b[1] = b[2] = 2; 
        fun(b,1);
    }

    static void print(int[] a)
    {
        for(int x : a)
            System.out.print(x + " ");
        System.out.println("");
    }
}

Output 111 222

但是,如果您创建一个新数组,例如在下面的代码中,由于引用已更改,因此当您返回到 main 方法时,不会反射(reflect)更新。

import java.util.Arrays;

public class NewArrayCreatedAndReferencePassedOn{
    public static void main(String[] args) {
        int[] a = {1,1,1};

        print(a);
        fun(a,0);
        print(a);
    }

    static void fun(int[] b, int count)
    {
        if(count == 1)
            return;

        int[] newb = {2,2,2};
        fun(newb,1);
    }

    static void print(int[] a)
    {
        for(int x : a)
            System.out.print(x + " ");
        System.out.println("");
    }
}

Output 111 111

但是,我的问题是,为什么为数组选择这样的设计。为什么不能像原始数据类型(例如整数变量)一样,用一个新的 int 来表示每次在函数内部传递它时都会创建它,尽管我们没有显式创建或声明一个新的 int。例如,

import java.util.Arrays;

public class SameIntPassedOn_ButNewCopyCreatedEachFrame {
    public static void main(String[] args) {
        int i = 0;

        fun(i);
    }

    static void fun(int b)
    {
        System.out.println(b);

        if(b == 10)
            return;

        b = b+1;
        fun(b);

        System.out.println(b);
    }
}

输出

0 1 2 3 4 5 6 7 8 9 10 10 9 8 7 6 5 4 3 2 1

如果对数组进行同样的操作,我们就可以为递归函数的每个帧拥有不同的数组副本,这将非常方便。

我认为行为上的一致性会很好,因为目前看来,用数组实现相同的行为,就像原始数据类型(例如 int、float 等)所展示的那样,当传递给方法时,必须使用“new”关键字,并在传递给方法之前创建一个新数组。

最佳答案

However, my question is, why such a design was chosen for Arrays.

有几个主要原因。

首先是性能 - 如果每次调用方法时都必须创建数组的新副本,这将导致性能极差,特别是对于递归调用。

Had the same been done for arrays, it would've allowed us to have a different copy of the array for each frame of the recursive function, which would've been very handy.

第二个是,如果您愿意,您已经可以选择传递数组的副本 - 您可以手动创建一个副本并传递它。通过这种方式,程序员拥有最大的控制权 - 他们可以选择让方法调用修改数组,或者他们可以选择传递一个副本,允许每个方法调用其要使用的数组版本。如果我们强制程序员始终使用副本,他们将失去让方法调用修改数组的选择,这在某些情况下非常有用。当前的设计为程序员提供了最多的选择。

Why couldn't it be that, just like for a primitive data type...

最后一个原因是数组不是原始数据类型 - 它是一个对象。做出这个决定很可能是为了使数组与 Java 中其他对象的行为方式尽可能一致。

关于java - 将数组传递给方法与将原始数据类型传递给方法不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38233451/

相关文章:

java - Android 的未知膨胀错误

c - C 中的可变数组大小

php - 你如何在 wordpress 中使用 wp_Query 输出 JSON?

c - 不确定如何正确使用 malloc() 和 free()

C: 格式指定类型 'char *'

java - 为什么 ArrayList<MyClass> 突然改变它的值

java - 使用 StAX 对 XML 文档进行小的修改

php - 从 SQL 数据库表定义各种变量 - 更好的做法?

c - 我是否创建一个临时 c 结构并通过套接字发送它?

java - 在类中实现类