数组在Java中不是基本类型,但它们也不是对象,因此它们是通过值传递还是通过引用传递?它是否取决于数组所包含的内容,例如引用或基本类型?


当前回答

关于数组的详细讨论在http://docs.oracle.com/javase/specs/jls/se5.0/html/arrays.html#27803。这表明Java数组是对象。这些对象的类在10.8中定义。

语言规范http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#40420的8.4.1节描述了如何将参数传递给方法。由于Java语法源自C和c++,因此行为是相似的。与C语言一样,基本类型是按值传递的。当传递一个对象时,对象引用(指针)是按值传递的,这与C语言按值传递指针的语法是一致的。见4.3.1,http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.3,

实际上,这意味着在方法中修改数组的内容会反映在调用作用域中的数组对象中,但在方法中为引用重新分配新值不会对调用作用域中的引用产生影响,这正是C中指向结构的指针或c++中的对象的指针所期望的行为。

At least part of the confusion in terminology stems from the history of high level languages prior to the common use of C. In prior, popular, high level languages, directly referencing memory by address was something to be avoided to the extent possible, and it was considered the job of the language to provide a layer of abstraction. This made it necessary for the language to explicitly support a mechanism for returning values from subroutines (not necessarily functions). This mechanism is what is formally meant when referring to 'pass by reference'.

When C was introduced, it came with a stripped down notion of procedure calling, where all arguments are input-only, and the only value returned to the caller is a function result. However, the purpose of passing references could be achieved through the explicit and broad use of pointers. Since it serves the same purpose, the practice of passing a pointer as a reference to a value is often colloquially referred to a passing by reference. If the semantics of a routine call for a parameter to be passed by reference, the syntax of C requires the programmer to explicitly pass a pointer. Passing a pointer by value is the design pattern for implementing pass by reference semantics in C.

Since it can often seem like the sole purpose of raw pointers in C is to create crashing bugs, subsequent developments, especially Java, have sought to return to safer means to pass parameters. However, the dominance of C made it incumbent on the developers to mimic the familiar style of C coding. The result is references that are passed similarly to pointers, but are implemented with more protections to make them safer. An alternative would have been the rich syntax of a language like Ada, but this would have presented the appearance of an unwelcome learning curve, and lessened the likely adoption of 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..
}

数组实际上是对象,因此传递的是引用(引用本身是按值传递的,不明白吗?)简单的例子:

// 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中引用也是按值传递的,因此对引用本身的更改是在被调用的函数级别上进行的。编译器和/或JVM通常会将值类型转换为引用。

关于数组的详细讨论在http://docs.oracle.com/javase/specs/jls/se5.0/html/arrays.html#27803。这表明Java数组是对象。这些对象的类在10.8中定义。

语言规范http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#40420的8.4.1节描述了如何将参数传递给方法。由于Java语法源自C和c++,因此行为是相似的。与C语言一样,基本类型是按值传递的。当传递一个对象时,对象引用(指针)是按值传递的,这与C语言按值传递指针的语法是一致的。见4.3.1,http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.3,

实际上,这意味着在方法中修改数组的内容会反映在调用作用域中的数组对象中,但在方法中为引用重新分配新值不会对调用作用域中的引用产生影响,这正是C中指向结构的指针或c++中的对象的指针所期望的行为。

At least part of the confusion in terminology stems from the history of high level languages prior to the common use of C. In prior, popular, high level languages, directly referencing memory by address was something to be avoided to the extent possible, and it was considered the job of the language to provide a layer of abstraction. This made it necessary for the language to explicitly support a mechanism for returning values from subroutines (not necessarily functions). This mechanism is what is formally meant when referring to 'pass by reference'.

When C was introduced, it came with a stripped down notion of procedure calling, where all arguments are input-only, and the only value returned to the caller is a function result. However, the purpose of passing references could be achieved through the explicit and broad use of pointers. Since it serves the same purpose, the practice of passing a pointer as a reference to a value is often colloquially referred to a passing by reference. If the semantics of a routine call for a parameter to be passed by reference, the syntax of C requires the programmer to explicitly pass a pointer. Passing a pointer by value is the design pattern for implementing pass by reference semantics in C.

Since it can often seem like the sole purpose of raw pointers in C is to create crashing bugs, subsequent developments, especially Java, have sought to return to safer means to pass parameters. However, the dominance of C made it incumbent on the developers to mimic the familiar style of C coding. The result is references that are passed similarly to pointers, but are implemented with more protections to make them safer. An alternative would have been the rich syntax of a language like Ada, but this would have presented the appearance of an unwelcome learning curve, and lessened the likely adoption of Java.

简而言之,在Java中为对象(包括数组)传递参数的设计本质上是服务于按引用传递的语义意图,但是是用按值传递引用的语法实现的。