我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。

什么是解释?


当前回答

Java 总是通过值,而不是通过参考。

Pass by reference(也称为 pass by address)是指实际参数地址的副本存储。

public class PassByValue {
    public static void main(String[] args) {
        Test t = new Test();
        t.name = "initialvalue";
        new PassByValue().changeValue(t);
        System.out.println(t.name);
    }
    
    public void changeValue(Test f) {
        f.name = "changevalue";
    }
}

class Test {
    String name;
}

让我们一步一步了解一下:

Test t = new Test();

正如我们都知道,它将创建一个对象,并将参考值返回t 例如,假设t 的值为 0x100234 (我们不知道实际的 JVM 内部值,这只是一个例子) 。

此分類上一篇

new PassByValue().changeValue(t);

通过 t 函数时,它不会直接通过对象测试的实际参考值,但它会创建 t 的副本,然后将其转移到函数。 因为它通过值,它会通过变量的副本而不是实际的参考值。 因为我们说 t 的值是 0x100234, t 和 f 都将具有相同的值,因此它们将指向相同的 ob。

此分類上一篇

public class PassByValue {
    public static void main(String[] args) {
        Test t = new Test();
        t.name = "initialvalue";
        new PassByValue().changeRefence(t);
        System.out.println(t.name);
    }
    
    public void changeRefence(Test f) {
        f = null;
    }
}

class Test {
    String name;
}

这会扔一个NullPointerException吗? 不,因为它只通过一个副本的参考。 在通过参考的情况下,它可能会扔一个NullPointerException,如下所示:

此分類上一篇

希望这能帮助。

其他回答

我觉得关于“pass-by-reference vs pass-by-value”的争论并不太有用。

在我们到达Java实施之前,滑板/滑板上走路:价值观以顺序的方式滑板上走路,就像一家咖啡馆里的滑板一样。 滑板中的记忆(也称为动态记忆)是危险的,不组织的。

好吧! 首先,地方原始人走在地板上,所以这个代码:

int x = 3;
float y = 101.1f;
boolean amIAwesome = true;

此分類上一篇

当你宣布和即时一个对象时,实际对象会走在地板上,什么会走在地板上?对象的地址会走在地板上,C++程序员会称之为指标,但一些Java开发人员反对“指标”这个词。

像这样:

int problems = 99;
String name = "Jay-Z";

此分類上一篇

JButton[] marxBros = new JButton[3];
marxBros[0] = new JButton("Groucho");
marxBros[1] = new JButton("Zeppo");
marxBros[2] = new JButton("Harpo");

此分類上一篇

private static void shout(String name){
    System.out.println("There goes " + name + "!");
}

public static void main(String[] args){
    String hisName = "John J. Jingleheimerschmitz";
    String myName = hisName;
    shout(myName);
}

此分類上一篇

所以,值,参考?你说“土豆”。

不,不是通过参考。

Java 按 Java 语言规格通过值:

当方法或构造器被提及(第15条12),实际论点表达的值启动新创建的参数变量,每一个声明的类型,在执行方法或构造器的身体。

“pass-by-value”和“pass-by-reference”是指变量;“pass-by-value”是指变量的值转移到函数/方法;“pass-by-reference”是指该变量的参考转移到函数;“pass-by-reference”是指变量的值转移到函数;“pass-by-reference”是指变量的值转移到函数。

它如同这样:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    Dog oldDog = aDog;

    // we pass the object to foo
    foo(aDog);
    // aDog variable is still pointing to the "Max" dog when foo(...) returns
    aDog.getName().equals("Max"); // true
    aDog.getName().equals("Fifi"); // false
    aDog == oldDog; // true
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // change d inside of foo() to point to a new Dog instance "Fifi"
    d = new Dog("Fifi");
    d.getName().equals("Fifi"); // true
}

同样:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    Dog oldDog = aDog;

    foo(aDog);
    // when foo(...) returns, the name of the dog has been changed to "Fifi"
    aDog.getName().equals("Fifi"); // true
    // but it is still the same dog:
    aDog == oldDog; // true
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // this changes the name of d to be "Fifi"
    d.setName("Fifi");
}

有关参考通行和值通行的更多信息,请参见以下答案: https://stackoverflow.com/a/430958/6005228. 这更详细地解释了两者背后的语法和历史,并解释了为什么Java和许多其他现代语言似乎在某些情况下都会做两件事。

Java 总是使用 Call by Value. 这意味着该方法获得所有参数值的副本。

考虑下列三种情况:

1、试图改变原始变量

public static void increment(int x) { x++; }

int a = 3;
increment(a);

x 将复制一个值,并将增加 x,一个将保持相同的值

(二)试图改变对象的原始领域

public static void increment(Person p) { p.age++; }

Person pers = new Person(20); // age = 20
increment(pers);

p 将复制个体的参考值,并将增加年龄领域,变量是指相同的对象,所以年龄改变。

(三)试图改变参考变量的参考值

public static void swap(Person p1, Person p2) {
    Person temp = p1;
    p1 = p2;
    p2 = temp;
}

Person pers1 = new Person(10);
Person pers2 = new Person(20);
swap(pers1, pers2);

呼叫交换 p1 后,p2 复制 pers1 和 pers2 的参考值与值交换,因此 pers1 和 pers2 仍然相同。

因此,您只能在将参考值复制到该对象时更改对象的字段。

首先,通过参考与通过价值之间的区别是什么?

关于 pass-by-value 的评论

在 call-by-value 中,论点表达是评估的,结果值与函数中的相应变量有联系......如果函数或程序能够将值分配给其参数,则仅会分配其本地副本。

因此,它分配(或绑定)论点的价值与相应的参数变量。

论点的价值是什么?

Java 语言规格也表示

public void method (String param) {}
...
String variable = new String("ref");
method(variable);
method(variable.toString());
method(new String("ref"));

一切都将一个参考的值绑在一个紧缩例子上,该方法的新创建的参数,参数,这正是通过值的定义所描述的。