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

时间:2016-07-06 20:43:32

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

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

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("");
    }
}
  

输出111 222

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

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("");
    }
}
  

输出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

如果对数组做了同样的事情,它将允许我们为递归函数的每一帧提供不同的数组副本,这将非常方便。

我认为在行为上保持一致是很好的,因为目前看起来好像是用Arrays实现相同的行为,就像原始数据类型(如int,float等)所表现的那样,传递给方法时,必须使用' new '关键字,并在传递给方法之前创建一个新数组。

3 个答案:

答案 0 :(得分:3)

  

但是,我的问题是,为什么选择这样的设计用于阵列。

有几个主要原因。

第一个是性能 - 如果每次调用一个方法时都必须创建一个新的数组副本,这会导致性能极差,尤其是对于递归调用。

  

如果对数组做了同样的事情,它会让我们拥有一个   递归函数的每个帧的数组的不同副本,   哪个会非常方便。

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

  

为什么不能这样,就像原始数据类型......

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

答案 1 :(得分:0)

答案是所有对象,实际上所有方法参数都是按值传递的。你的评估"对阵列做了同样的事情"是错误的,因为对数组做了同样的事情。与所有对象引用一样,数组按值传递。发送给方法的原始值的副本与调用者传递的值相同。发送给方法的数组指针的副本与调用者传递的值相同。发送给方法的任何对象指针的副本与调用者传递的值相同。 它指向同一个对象,因为指针是按值复制的。

为什么,你问?因为它很简单,它有效,而且确实没有任何缺点。

答案 2 :(得分:-1)

Array是一个包含一组对象的容器(数据结构)。

这些物体可能很大或很小。并且数组可以包含许多对象

想象每个数组引用我们做完全复制

语言将非常缓慢且效率低下

因此,主要原因是效率