数组在Java中不是基本类型,但它们也不是对象,因此它们是通过值传递还是通过引用传递?它是否取决于数组所包含的内容,例如引用或基本类型?
当前回答
你的问题建立在一个错误的前提上。
数组在Java中不是基本类型,但它们也不是对象……”
事实上,Java中的所有数组都是objects1。每个Java数组类型都有Java .lang.Object作为它的超类型,并继承Object API中所有方法的实现。
... 那么它们是通过值传递还是通过引用传递呢?它是否取决于数组所包含的内容,例如引用或基本类型?
简单回答: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问题:
Java是“引用传递”还是“值传递”?
历史背景:
短语“引用传递”最初是“引用调用”,它被用来区分FORTRAN的参数传递语义(引用调用)和ALGOL-60的参数传递语义(值调用和名称调用)。
In call-by-value, the argument expression is evaluated to a value, and that value is copied to the called method. In call-by-reference, the argument expression is partially evaluated to an "lvalue" (i.e. the address of a variable or array element) that is passed to the calling method. The calling method can then directly read and update the variable / element. In call-by-name, the actual argument expression is passed to the calling method (!!) which can evaluate it multiple times (!!!). This was complicated to implement, and could be used (abused) to write code that was very difficult to understand. Call-by-name was only ever used in Algol-60 (thankfully!).
更新
实际上,algore -60的名称调用类似于将lambda表达式作为参数传递。问题在于,这些非精确lambda表达式(它们在实现级别被称为“thunks”)可以间接地修改调用过程/函数作用域内变量的状态。这也是他们难以理解的部分原因。(例如,请参阅维基百科上詹森设备的页面。)
1. 在链接的问答(Java中的数组及其在内存中的存储方式)中,没有任何内容声明或暗示数组不是对象。
其他回答
不,那是不对的。数组是Java中的特殊对象。这就像传递其他对象一样,你传递的是引用的值,而不是引用本身。这意味着,在被调用例程中更改数组的引用将不会反映在调用例程中。
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中的所有内容都是通过值传递的。
看看这篇有趣的文章,了解更多信息…
有点像骗人的房产…甚至在Java中引用也是按值传递的,因此对引用本身的更改是在被调用的函数级别上进行的。编译器和/或JVM通常会将值类型转换为引用。
数组实际上是对象,因此传递的是引用(引用本身是按值传递的,不明白吗?)简单的例子:
// 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 8中String.chars()是整数流?
- 无法创建Android虚拟设备
- 在Java中数组是按值传递还是按引用传递?
- 如何在Spring中以编程方式获取当前活动/默认环境概要文件?
- equals vs Arrays。Java中的等号
- 如何计算一个NumPy bool数组中的真实元素的数量
- 如何找到一个值的数组索引?
- 为什么我们通常用|| / |?有什么不同?
- 如何在Android中获得一个RadioGroup的选定索引
- 如何大写一个字的第一个字母在字符串使用Java?
- 禁用IntelliJ星(包)导入?
- Python csv字符串到数组
- 面试问题:检查一个字符串是否是另一个字符串的旋转
- 将文件加载为InputStream的不同方法
- 到底是什么导致了堆栈溢出错误?