Java Pass By Value和reference

时间:2015-09-01 06:04:22

标签: java pass-by-reference pass-by-value

我有以下代码。但是,我无法理解它在传递价值和参考方面的行为。

class Dog{
    String name;
    int x=100;

    Dog(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }
}
class Demo{
    public static void main( String[] args ){
        Dog aDog = new Dog("Tom");
        foo(aDog);

        if (aDog.getName().equals("Tom")) { //true
            System.out.println( "Java passes by value."+ aDog.getName());
            System.out.println( aDog.x);

        } else if (aDog.getName().equals("Taz")) {
            System.out.println( "Java passes by reference." );
        }
    }

    public static void foo(Dog d) {
        ++d.x;
        d = new Dog("Taz");
        ++d.x;
    }
}

这将提供输出

  

Java按值传递.Tom

     

101

为什么输出101?我期待输出102

4 个答案:

答案 0 :(得分:4)

你要两次递增x,但在不同的狗身上。看看这段代码:

public static void foo(Dog d) {
    ++d.x;
    d = new Dog("Taz");
    ++d.x;
}

最初,d指的是名称为Tomx=100的狗。这不是原始对象的副本 - 它是对同一对象的引用。 Java按值传递引用,这与通过值传递对象或通过引用传递对象的不同。重要的是要了解aDogmain的值不是Dog对象 - 它是对Dog对象的引用。该引用的值按值传递到foo方法...因此d的初始值与aDog的值相同。对d变量本身(而不是其值所引用的对象)的进一步更改 not 更改aDog变量。

所以,看看foo的其余部分:

  • ++d.x之后,d指的是名为Tom的狗,x=101
  • d = new Dog("Taz")之后,d指的是名为Taz的狗,x=100
  • ++d.x之后,d指的是名为Taz的狗,x=101

调用代码只知道名为Tom的狗,所以打印出Tom 101。

答案 1 :(得分:3)

你在给予方法的狗(“汤姆”)上增加x一次。

然后你创建一个名为Taz的 new 狗。

然后为第二只狗增加x。它不会影响原来的,两只狗都会在101.

至于为什么调用方法仍然引用“Tom”,即使您将局部变量更改为指向“Taz”:这是因为局部变量就是:它所使用的位置的本地变量。调用者不关心你以后用它做什么,它自己的变量仍然指向“Tom”。

因为Java不支持pass-by-reference或“out parameters”,所以被调用的函数无法改变调用函数中变量的值。

但请注意,对象不存储在变量中。只存在指向它们的指针。实际的对象实例本身位于共享位置(程序堆内存)。所以被调用的方法确实可以更改对象。但是它不能将不同的对象分配给调用函数。

外卖:制作局部变量final,尤其是方法参数。然后你不能为两个不同的东西重用相同的变量,而且代码变得不那么混乱了。

答案 2 :(得分:2)

Java总是按值传递

主要():

Dog aDog = new Dog("Tom"); // {name="Tom", x=100}

FOO():

++d.x;                     // {name="Tom", x=101}
d = new Dog("Taz");        // {name="Taz", x=100}
++d.x;                     // {name="Taz", x=101}

但是,您可以获得全新副本,但需要将其返回。

在main()中:更新此行

foo(aDog);

aDog = foo(aDog);

还将foo()更新为:

public static Dog foo(Dog d) {
  ...
  return d;
}

答案 3 :(得分:-1)

当您使用new这样的关键字d = new Dog("Taz");时 您创建了一个新的Dog,新的Dog名为Taz并且x=101,因此您不会增加d.x 2同一只狗的时间