Java中的所有内容都是按值传递的。在数组的情况下(数组本质上是一个对象),数组引用被按值传递(就像对象引用被按值传递一样)。
当您将一个数组传递给其他方法时,实际上是复制对该数组的引用。
请参见此帖子:Java是“按引用传递”还是“按值传递”?
请查看此工作示例:
public static void changeContent(int[] arr) {
// If we change the content of arr.
arr[0] = 10; // Will change the content of array in main()
}
public static void changeRef(int[] arr) {
// If we change the reference
arr = new int[2]; // Will not change the array in main()
arr[0] = 15;
}
public static void main(String[] args) {
int [] arr = new int[2];
arr[0] = 4;
arr[1] = 5;
changeContent(arr);
System.out.println(arr[0]); // Will print 10..
changeRef(arr);
System.out.println(arr[0]); // Will still print 10..
// Change the reference doesn't reflect change here..
}
相关的SO问题:
历史背景:
“传引用调用”一词最初是“按引用调用”,它用于区分FORTRAN(按引用调用)和ALGOL-60(按值调用和按名称调用)的参数传递语义。
在按值调用中,参数表达式被计算为一个值,并将该值复制到被调用的方法中。
在按引用调用中,参数表达式部分被计算为“左值”(即变量或数组元素的地址),并将其传递给调用方法。调用方法可以直接读取和更新变量/元素。
在按名称调用中,实际参数表达式被传递给调用方法(!!),该方法可以多次评估它(!!!)。这很难实现,并且可能被用来编写非常难以理解的代码。按名称调用仅在Algol-60中使用(谢天谢地!)。
更新
实际上,Algol-60的按名称调用类似于将lambda表达式作为参数传递。问题在于这些不完全是lambda表达式(在实现层面上被称为“thunks”)可以间接地修改在调用过程/函数中范围内的变量状态。这就是使它们难以理解的部分之一(例如,请参见维基百科页面Jensen's Device)。1. 链接的问答中(Java中的数组及其在内存中的存储),没有任何说明或暗示数组不是对象。
数组实际上是对象,因此传递的是引用(引用本身是按值传递的,感到困惑了吗?)。这里有一个快速的例子:
// assuming you allocated the list
public void addItem(Integer[] list, int item) {
list[1] = item;
}
您将会看到在代码调用时列表的变化。然而,您不能更改引用本身,因为它是按值传递的:
// assuming you allocated the list
public void changeArray(Integer[] list) {
list = null;
}
如果你传递一个非空的列表,那么在方法返回时它不会为空。不,那是错误的。在Java中,数组是特殊的对象。因此,传递数组时就像传递其他对象一样,传递的是引用值而不是引用本身。这意味着,在被调用的程序中更改数组的引用不会反映在调用程序中。
#get
、#set
、#iterator
、#size
等方法的开销。你可以理论上将int[]实现为一个对象,使用一块连续的内存等,并编写一个编译器来使用它代替本地数组。它仍然比本地数组慢得多。 - AndrewF实际上,这意味着在方法中修改数组内容会反映在调用作用域中的数组对象中,但在方法内部重新分配新值的引用对调用作用域中的引用没有影响,这正是您期望在C中结构体指针或C ++对象的指针的行为。
至少部分术语混淆源于在C普及之前的高级语言历史。在先前的流行高级语言中,直接通过地址引用内存是尽可能避免的事情,这被认为是语言提供抽象层次的工作。这使得语言必须明确支持从子例程(不一定是函数)返回值的机制。正式提到“按引用传递”时,指的是此机制。
当引入C时,它带有一个简化的过程调用概念,其中所有参数都是仅输入的,而唯一返回给调用者的值是函数结果。但是,通过显式和广泛使用指针,可以实现传递引用的目的。由于它具有相同的目的,因此将指针作为对值的引用传递的做法通常俗称为按引用传递。如果例程的语义要求通过引用传递参数,则C的语法要求程序员明确传递指针。通过值传递指针是在C中实现按引用传递语义的设计模式。
有点像房地产的技巧...即使在Java中,引用也是按值传递的,因此对于引用本身的更改仅限于被调用函数级别。编译器和/或JVM通常会将值类型转换为引用。