数组是通过值传递还是通过Java中的引用传递?
可能重复:
Java是“通过引用”吗?
数组在Java中不是原始types ,但它们也不是对象 ,它们是按值还是按引用传递的? 它取决于数组包含的内容,例如引用或原始types?
从技术上讲,它是按值传递的,但值是对数组的引用。
通过引用的真实传递涉及传递variables的地址,以便可以更新variables。 这不是在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(通过引用和名称)。
-
在按值调用中,参数expression式被计算为一个值,并且该值被复制到被调用的方法中。
-
在调用引用中,参数expression式被部分地评估为传递给调用方法的“左值”(即variables或数组元素的地址)。 调用方法可以直接读取和更新variables/元素。
-
在名称调用中,实际参数expression式被传递给调用方法(!!),可以多次评估(!!!)。 这实施起来很复杂,可以用来(滥用)编写非常难以理解的代码。 在Algol-60中只有名字叫做(谢天谢地!)。
UPDATE
实际上,Algol-60的call-by-name类似于将lambdaexpression式作为parameter passing。 起皱的是,这些非精确的lambdaexpression式(在执行级别被称为“thunk”)可以间接修改调用过程/函数中范围内的variables的状态。 这使他们很难理解。 (例如,请参阅Jensen设备上的Wikipedia页面。)
Everything in Java are passed-by value.
。 在数组的情况下(这不过是一个对象),数组引用是通过值传递。(就像一个对象引用传递的值)。
将数组传递给其他方法时,实际上对该数组的引用被复制。
- 通过该引用对数组内容进行的任何更改都将影响原始数组。
- 但是将引用更改为指向新数组不会改变原始方法中的现有引用。
看到这个post..
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.. }
数组实际上是对象,所以通过引用(引用本身是按值传递的,困惑了吗?)。 快速示例:
// 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中的特殊对象。 所以就像传递其他对象一样,你传递引用的值,而不是引用本身。 意思是说,在调用例程中改变数组的引用不会反映在调用例程中。
Java中的所有东西都是按值传递的。
在数组的情况下,引用被复制到一个新的引用,但是请记住,Java中的所有内容都是按值传递的。
看看这个有趣的文章进一步的信息…
数组的权威性讨论在http://docs.oracle.com/javase/specs/jls/se5.0/html/arrays.html#27803 。 这清楚地表明Java数组是对象。 这些对象的类是在10.8中定义的。
语言规范的第8.4.1节( http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#40420 )描述了参数如何传递给方法。 由于Java语法是从C和C ++派生的,因此行为是相似的。 与C一样,原始types也是按值传递的。当一个对象被传递时,一个对象引用(指针)通过值传递,镜像按值传递指针的C语法。 请参阅4.3.1, http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.3 ,
实际上,这意味着在一个方法中修改一个数组的内容被反映到调用范围内的数组对象中,但是在该方法内重新分配一个新的值对引用没有影响,正是你所期望的指向C或C ++中的一个对象的结构的行为。
至less部分的术语混淆源于C语言普遍使用之前的高级语言的历史。在现有的stream行的高级语言中,尽可能地避免通过地址直接引用内存,被认为是提供一个抽象层的语言的工作。 这使得语言必须明确地支持从子例程(不一定是函数)返回值的机制。 这个机制是指“通过参考”的正式含义。
当C被引入时,它带有一个简化的过程调用的概念,其中所有参数都是只input的,唯一返回给调用者的值是一个函数结果。 然而,通过引用的目的可以通过指针的明确和广泛的使用来实现。 由于它用于相同的目的,所以传递指针作为对值的引用的实践通常被通俗地称为通过引用。 如果一个例程的语义调用parameter passing,那么C的语法要求程序员明确地传递一个指针。 按值传递指针是在C中实现按引用语义传递的devise模式 。
由于C中原始指针的唯一目的往往是创build崩溃的错误,所以后续的开发(尤其是Java)试图返回到更安全的方式来传递参数。 然而,C的主导地位使得开发者有责任模仿熟悉的C编码风格。 结果是引用类似地传递给指针,但实现更多的保护,使他们更安全。 另一种select是像Ada这样的语言的丰富的语法,但是这会呈现不受欢迎的学习曲线的外观,并且减less了Java的可能的采用。
简而言之,在Java中为包括数组在内的对象传递参数的devise本质上是服务于按引用传递的语义意图,但是采用按值传递引用的语法来实现。
一种技巧不变…即使引用是通过Java中的值传递的,因此引用本身的变化被限定在被调用的函数级别。 编译器和/或JVM通常会将值types转换为引用。