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

什么是解释?


当前回答

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


让我们用一个例子来解释这一点:

public class Main {

     public static void main(String[] args) {
          Foo f = new Foo("f");
          changeReference(f); // It won't change the reference!
          modifyReference(f); // It will modify the object that the reference variable "f" refers to!
     }

     public static void changeReference(Foo a) {
          Foo b = new Foo("b");
          a = b;
     }

     public static void modifyReference(Foo c) {
          c.setAttribute("c");
     }

}

我将在步骤中解释这一点:

宣布一个参考名为Foo类型,并将其分配给一个新的Foo类型对象与属性“f”。Foo f =新Foo(“f”);从方法侧,一个Foo类型的参考名称A被宣布,它最初被分配为零。

我希望你现在明白如何通过对象作为论点在Java工作:)

其他回答

一个简单的测试,以检查一个语言是否支持通过参考,只是写一个传统的交换。

一个传统的交换方法或函数采取两个论点,并交换它们,以便转换到函数的变量在函数之外发生变化。

(非Java) 基本交换功能结构

swap(Type arg1, Type arg2) {
    Type temp = arg1;
    arg1 = arg2;
    arg2 = temp;
}

如果你能在你的语言中写出这样的方法/函数,那么

Type var1 = ...;
Type var2 = ...;
swap(var1,var2);

事实上,它交换了 var1 和 var2 变量的值,语言支持 pass-by-reference. 但 Java 不允许这样的东西,因为它支持只通过值,而不是指标或参考。

对于简单性和言语性 其通过值参考:

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
}

与某些其他语言不同,Java不允许您在 pass-by-value 和 pass-by-reference 之间选择。

所有论点都以价值为准。

一个方法通话可以通过两个类型的 valuesto 一个方法

原始值的副本(例如,类型值 int 和双值)对物体的参考副本。

当一个方法改变原始类型参数时,参数的变化不会影响呼叫方法的原始论点值。

如果你修改一个参考类型参数以便它指向另一个对象,只有参数指向新对象 - 呼叫器的变量中存储的参数仍然指向原始对象。

参考: JavaTM 如何编程(早期对象),第十版

Java 是由價值通過的。

在某种程度上,我从来没有透露过原始数据类型和对象的值/参考。因此,我用下列代码来测试我的满意度和清晰度;可能有助于寻求类似清晰度的人:

class Test    {

public static void main (String[] args) throws java.lang.Exception
{
    // Primitive type
    System.out.println("Primitve:");
    int a = 5;
    primitiveFunc(a);
    System.out.println("Three: " + a);    //5

    //Object
    System.out.println("Object:");
    DummyObject dummyObject = new DummyObject();
    System.out.println("One: " + dummyObject.getObj());    //555
    objectFunc(dummyObject);
    System.out.println("Four: " + dummyObject.getObj());    //666 (555 if line in method uncommented.)

}

private static void primitiveFunc(int b)    {
    System.out.println("One: " + b);    //5
    b = 10;
    System.out.println("Two:" + b);    //10
}

private static void objectFunc(DummyObject b)   {
    System.out.println("Two: " + b.getObj());    //555
    //b = new DummyObject();
    b.setObj(666);
    System.out.println("Three:" + b.getObj());    //666
}

}

class DummyObject   {
    private int obj = 555;
    public int getObj() { return obj; }
    public void setObj(int num) { obj = num; }
}

如果行 b = 新 DummyObject() 没有评论,随后进行的修改是在一个新的对象,一个新的实例上进行的。 因此,它不反映在方法被召回的地方。 但是,否则,变化是反映的,因为修改只是在对象的“参考”上进行的,即 - b 点到相同的 dummyObject。

在这个条纹中的答案之一(https://stackoverflow.com/a/12429953/4233180)的描述可以帮助获得更深入的理解。

有这么多长的答案,让我给你一个简单的答案:

Java 总是按值传达一切,也就是说,参考也按值传达。

简而言之,您无法改变任何参数的值,但您可以通过对象参考的方法或属性更改。