数组在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;
}

如果传递一个非空列表,在方法返回时它将不是空的。

其他回答

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

// 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中定义。

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