我知道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);
}
为什么?
答案 0 :(得分:14)
在第二种方法中,您尝试交换引用,这些引用无效,因为引用本身是按值传递的。
第一种方法正常工作,因为它更改了数组引用的对象(可变),它不会更改引用本身。
查看this blog post,了解有关传值和传递参考之间差异的详细信息。
答案 1 :(得分:7)
您的第一个示例是传输数组中的值。
您尝试交换引用的第二个(数组是Java中的对象)。引用是本地副本(按值传递),并且对calee上下文没有影响。
(问题#56.903关于按值调用; Stackexchange应该打开PassByValue.com; - )
答案 2 :(得分: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);
}
答案 3 :(得分:1)
第一次交换您更改了数组的数据。 (由arr引用:引用)所以它被修改
第二次交换,您更改了arr,arr2,两个局部变量。因此,当您退出该方法时,两个新变量将被销毁
答案 4 :(得分:1)