Java真的总是复制传递给方法的所有对象吗



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中任何这些都是可能的。

最新更新