【问题标题】:Parameter passing in JavaJava中的参数传递
【发布时间】:2014-08-25 13:27:24
【问题描述】:

我知道 Java 总是按值传递,但我不明白为什么会这样:

public static void swap(int[] arr, int i, int j)
{
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
public static void main(String[] args)
{
    int[] arr = {3, 4, 5, 6};
    swap(arr, 1, 3);
    // arr becomes {3, 6, 5, 4}
}

这不起作用:

public static void swap(int[] arr, int[] arr2)
{
    int[] tmp = arr;
    arr = arr2;
    arr2 = tmp;
}
public static void main(String[] args)
{
   int[] arr = {3, 4, 5, 6};
   int[] arr2 = {1, 2, 5, 6};
   swap(arr, arr2);
}

为什么?

【问题讨论】:

标签: java pass-by-value


【解决方案1】:

在第二种方法中,您尝试交换引用,这将不起作用,因为引用本身是按值传递的。

第一种方法可以正常工作,因为它改变了数组引用的对象(它是可变的),它不会改变引用本身。

查看this blog post,了解有关按值传递和按引用传递之间差异的更多详细信息。

【讨论】:

  • 我还要补充一点,数组在 Java 中是可变的,这就是第一个示例有效的原因。
【解决方案2】:

您的第一个示例是传输数组中的值。

您尝试交换引用的第二次(数组是 Java 中的对象)。引用是本地副本(按值传递),对 calee 上下文没有影响。

(关于按值调用的问题 #56.903;Stackexchange 应该打开 PassByValue.com ;-)

【讨论】:

    【解决方案3】:

    如果您曾经使用过 C 或 C++ 并且知道指针是如何工作的,那么对我来说整个场景的成功之处在于以下语句:

    In Java, everything is passed by value. 
    In case of Objects, the reference (pointer) is passed by value.
    

    所以基本上是交换功能

    public void swap(int[] a, int[] b)
    {
        etc.
    }
    

    只会得到指向a int[] 数组的指针和指向b int[] 数组的指针。 你只是交换两个指针。你不能像那样修改指针的内容。

    基本上C等价于

    void swap(int* a, int* b)
    {
       int* temp = a;
       a = b;
       b = temp;
    }
    
    int main(void)
    {
        int a[] = {5,6,7,8};
        int b[] = {1,2,3,4};
        swap(a,b);
    }
    

    即使在 C 中,也只能这样工作:

    void swap(int** a, int** b)
    {
       int* temp = (*a);
       (*a) = (*b);
       (*b) = temp;
    }
    
    int main(void)
    {
        int a[] = {5,6,7,8};
        int b[] = {1,2,3,4};
        swap(&a, &b);
    }
    

    当然,您不能在 Java 中发送引用的引用。 Java 中不存在这种意义上的指针。

    因此,为了在另一个函数中实际修改对象,您需要一个“Holder”对象,将引用复制到该对象,但其中对要修改的对象的引用实际上是实际的引用对象,如果这有意义的话。

    因此,以下将起作用:

    public class ArrayHolder
    {
        public int[] array;
    
        public ArrayHolder(int[] array)
        {
            this.array = array;
        }
    }
    
    public void swap(ArrayHolder a, ArrayHolder b)
    {
        int[] temp = a.array;
        a.array = b.array;
        b.array = temp;
    }
    
    public static void main(String[] args)
    {
        ArrayHolder aaa = new ArrayHolder(new int[] {5,6,7,8});
        ArrayHolder bbb = new ArrayHolder(new int[] {1,2,3,4});
        swap(aaa,bbb);
    }
    

    【讨论】:

      【解决方案4】:
      • Arrarr2 是局部变量,所以它们会在 swap 方法结束时被销毁。
      • 在swap方法之外,局部变量的改变不会受到影响。

      【讨论】:

        【解决方案5】:
        • 第一次交换你改变了数组的数据。 (由 arr 引用:一个引用)所以它被修改了

        • 第二次swap,你改变arr,arr2,两个局部变量。因此,当您退出该方法时,两个新变量将被销毁

        【讨论】:

          猜你喜欢
          • 2012-12-14
          • 1970-01-01
          • 2012-01-22
          • 2016-11-22
          • 2020-05-15
          • 1970-01-01
          • 2018-07-26
          • 2012-01-07
          • 2019-09-13
          相关资源
          最近更新 更多