【问题标题】:Does Java really always copy all objects passed to a method? [duplicate]Java 真的总是复制传递给方法的所有对象吗? [复制]
【发布时间】:2016-01-11 14:52:10
【问题描述】:

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 仅是按值传递的?仅适用于原始类型的 AFAIK。
  • @HubertGrzeskowiak Java 总是按值传递。在非原始类型的情况下,它通过值传递引用
  • 如果我们不是在谈论原始数据类型,即对象,JAVA 是通过引用传递的。我不知道你从哪里得到 JAVA 是按值传递的想法......
  • @TT。如果 Java 将在任何时候通过引用传递,那么您可以执行 a = new A() 其中 a 是类 A 的参数,并且这个新引用也会在传递给方法的原始变量中发生变化,因此它's 唯一的按值传递...
  • @Kevin Goodness,什么吹毛求疵。 JAVA 通过值传递对 ... 周围对象的引用。当然,它不会通过引用传递引用,这不是用任何语言完成的。也没有 C++ 中的引用类型。真的,这不是 OP 的重点。他认为对象是按值传递的,但事实并非如此(否则该对象将像在 C++ 中一样被复制)。对象通过引用传递。把它放在不同的地方只会造成混乱。只有我 2c。

标签: java compiler-optimization pass-by-value


【解决方案1】:

是的,Java 始终是按值传递的。但是对于对象,它传递参考值。换句话说,对象没有被复制,但它的引用被复制了。在方法内更改对象的属性也会在方法外更改它。

来自here

但是,对象不是通过引用传递的。正确的说法是对象引用是按值传递的。

主题:编译器只是将引用复制到堆栈中的内存块。

【讨论】:

  • 在我的代码中,外部对象没有改变: static void subMethod(String str) {str="change made from subMethod";} public static void main(String[] args) { String str = new String("原字符串");子方法(str); System.out.println(str); }
  • 1) 字符串是特殊的。 stackoverflow.com/questions/14473488/… 2) 您正在将引用分配给一个新对象。由于 Java 是按值传递的,因此不会影响原始对象。如果你做了类似obj.attribute++; 的事情,那么它会影响原始对象
  • @JonathanEnders 字符串是不可变的,尤其是this answer
  • 无论定义如何,所有不可变对象(Integer、Double、String 等)都可以视为传递值。你传递了这个对象,你可以确定它不会在任何地方被改变。
【解决方案2】:

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 总是 值传递,因此明确指出它是按值传递的引用。正如在 cmets 中所指出的,在很多情况下它与 实际上 传递引用不同,我无意表明其中任何一个是可以在 Java 中使用。

【讨论】:

  • "意味着 Java 是按引用传递" 不!! Java 总是按值传递 - in对象的情况下,它通过值传递引用。
  • @BorisTheSpider 重新阅读我的答案;我特别说过,它是按值传递的引用,并且它是出于实际目的而传递的引用。我非常清楚java总是按值传递:)
  • @jonk “实际目的” 不是。将方法内的引用设置为另一个对象不会更改传递的引用。但是,当 Java 不是按引用调用时,情况就会如此。
  • “pass-by-reference 用于实际目的” pass-by-reference 的一个实际用途(例如在 C++ 中)是编写一个swap 方法。你不能在 Java 中这样做,因为它实际上是按值传递的,因此将其视为“实际上”按引用传递是误导性的。
  • @BoristheSpider 我认为 jonk 更多是指在方法中改变 ab,例如打电话给a.mutateState();。但是,我只是认为试图将其称为“实际上是通过引用传递”只会使简单的规则变得更加困难。
猜你喜欢
  • 2011-12-15
  • 2011-11-21
  • 1970-01-01
  • 1970-01-01
  • 2017-02-22
  • 1970-01-01
  • 2017-09-23
  • 1970-01-01
  • 2016-03-09
相关资源
最近更新 更多