Java是按值传递的。这意味着被调用的方法作用于传入的对象的副本,而不是原始对象。
如果方法中没有更改对象,则似乎不需要创建实际副本。因此,实现程序以创建这样一个副本的编译器将非常低效。所有的Java编译器(javac、gcj、ECJ等)真的都这么做了吗?
至少在参数被声明为final
的情况下,不复制是很有意义的。
编辑
好的,所以对象不会被复制。我很困惑,因为String
的特殊之处在于它是复制的(不可变的)。抱歉我的不知情。为了弥补这一点,这里有一个千分之一的例子,说明当一个对象被传递时会发生什么:
import java.lang.System;
class C { int member; }
public class Test {
static void subMethod(C object) { object.member=1; }
public static void main(String[] args) {
C object = new C();
object.member=0;
subMethod(object);
System.out.println(object.member); // prints "1"
}
}
是的,Java总是按值传递。但对于对象,它传递参考值。换句话说,对象不是复制的,而是它的引用。在方法内部更改对象的属性也会在方法外部更改对象。
从这里开始,
但是,对象不是通过引用传递的。正确的语句应该是Object引用是通过值传递的。
主题:编译器只是将引用复制到堆栈中的内存块。
Java中的对象是引用,正是这个引用通过值传递;这意味着Java是通过引用对象来实现实际目的的。
编辑
我对"实际目的"一词的使用似乎引起了很多争议,所以让我澄清一下。我只是想说,当大多数人想到"通过引用传递"时,他们想到的是对传入值的更改在该方法之外持久化,Java就是这样。例如
void someMethod(SomeClass a) {
a.mutateState();
}
SomeClass a = new SomeClass();
someMethod(a); //passes reference to a by value;
a.methodInvolvingSomeState(); //mutations of object state persist to here, as if the previous call were pass-by-reference.
这就是我所说的"出于实际目的";OP的印象是制作了a
的副本,我试图解释这不是真的。我完全知道java总是按值传递,因此明确表示它是按值传递的引用。正如评论中所指出的,在很多情况下,它与实际上是通过引用不同,我无意表明在Java中任何这些都是可能的。