用Java传递参数

我知道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中的对象)。 引用是本地副本(按值传递),并且对calee上下文没有影响。

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

如果您曾经使用过C或C ++并且知道指针是如何工作的,那么为我提供的整个方案的选择如下:

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

所以基本上是交换function

 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); } 
  • Arrarr2是局部变量,因此在交换方法完成时它们将被销毁。
  • 在外部交换方法中,局部变量的变化不会受到影响。
  • 第一次交换你改变了数组的数据。 (由arr引用:引用)所以它被修改

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