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..
}
你的问题是基于一个错误的前提。
数组在Java中不是基元类型,但它们也不是对象......"
实际上,Java 中的所有数组都是对象1。每个 Java 数组类型都有其超类型,并继承 API 中所有方法的实现。java.lang.Object
Object
...那么它们是按值还是通过引用传递的?它是否取决于数组包含的内容,例如引用或基元类型?
简短的回答:1)通过值,2)它没有区别。
更长的答案:
像所有Java对象一样,数组是按值传递的...但该值是对数组的引用。因此,当您在被调用的方法中将某些内容分配给数组的单元格时,您将分配给调用方看到的同一数组对象。
这不是逐行引用。真正的按引用传递涉及传递变量的地址。使用真正的逐引用传递,被调用的方法可以分配给其局部变量,这会导致调用方中的变量更新。
但不是在Java中。在 Java 中,被调用的方法可以更新数组的内容,并且可以更新其数组引用的副本,但它无法更新调用方的数组引用的调用方中的变量。因此。。。Java提供的不是逐个引用。
下面是一些链接,用于解释按引用传递和按值传递之间的区别。如果你不明白我上面的解释,或者你倾向于不同意这些术语,你应该阅读它们。
- http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/com.ibm.xlcpp8a.doc/language/ref/cplr233.htm
- http://www.cs.fsu.edu/~myers/c++/notes/references.html
相关 SO 问题:
历史背景:
短语“逐个引用传递”最初是“逐个引用调用”,它用于区分FORTRAN(逐个引用调用)的参数传递语义和ALGOL-60的参数传递语义(按值调用和按名称调用)。
在按值调用中,参数表达式被计算为一个值,并将该值复制到被调用的方法。
在按引用调用中,参数表达式被部分计算为传递给调用方法的“lvalue”(即变量或数组元素的地址)。然后,调用方法可以直接读取和更新变量/元素。
在按名称调用中,实际的参数表达式被传递给调用方法(!!),该方法可以多次计算它(!!!)。这很难实现,并且可能被使用(滥用)来编写非常难以理解的代码。按名称调用只在Algol-60中使用过(谢天谢地!
更新
实际上,Algol-60 的按名称调用类似于将 lambda 表达式作为参数传递。问题是这些不完全是lambda表达式(它们在实现级别被称为“thunks”)可以间接修改调用过程/函数中范围内的变量的状态。这是使它们如此难以理解的部分原因。(例如,请参阅Jensen's Device上的维基百科页面。
1. 链接的问答(Java中的数组以及它们如何存储在内存中)中没有任何内容声明或暗示数组不是对象。
-
-
为什么 Array.newInstance(Class<?>, int) 不是通用的? 我的意思是,这有什么好的理由吗?该具有以下签名: 是否有任何充分的理由将返回值类型声明为 ?对我来说,这似乎非常不方便。
-
-
为什么我可以收集任意大数组的并行流,但不能收集顺序流? 在回答时,我遇到了一个奇特的功能。下面的代码按照我的假设工作(现有数组中的前两个值将被覆盖): 我很好奇为什么顺序流不会像并行流那样覆盖数组的元素。我搜索了一下,无法找到
-
Java JNI 调用的开销 首先让我说,这个问题更多的是出于好奇心,而不是真正的必要性。 我很想知道从Java执行JNI调用的开销是多少,比如说,与分配数组并使用for循环复制元素相比。 如果开销很大