Java Pass通过价值理解

时间:2012-07-24 02:56:56

标签: java parameter-passing

我想我明白它是传递给方法tricky()的对象/数据成员的副本,因为只有值才是重要的,而不是实际的对象本身。但是打印语句向我保证,arg1arg2副本确实在方法中切换。我不明白为什么这不会将信息传回原始对象,从而切换它们;看作该方法能够成功访问方法中的arg1.xarg1.y数据成员。

// This class demonstrates the way Java passes arguments by first copying an existing
// object/data member. This is called passing by value. the copy then points(refers)
// to the real object

// get the point class from abstract window toolkit
import java.awt.*;

public class passByValue {


static void tricky(Point arg1, Point arg2){

  arg1.x = 100;
  arg1.y = 100;
  System.out.println("Arg1: " + arg1.x + arg1.y);
  System.out.println("Arg2: " + arg2.x + arg2.y);

  Point temp = arg1;
  arg1 = arg2;
  arg2 = temp;
  System.out.println("Arg1: " + arg1.x + arg1.y);
  System.out.println("Arg2: " + arg2.x + arg2.y);
}




public static void main(String [] args){

  Point pnt1 = new Point(0,0);
  Point pnt2 = new Point(0,0);
  System.out.println("X1: " + pnt1.x + " Y1: " +pnt1.y); 
  System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
  System.out.println(" ");
  tricky(pnt1,pnt2);
  System.out.println("X1: " + pnt1.x + " Y1:" + pnt1.y); 
  System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);  

}
}

5 个答案:

答案 0 :(得分:5)

复制对象引用,复制的引用仍指向内存中的同一对象。这就是您可以使用复制的引用更改对象的原因。但是,修改参数引用会修改副本,而不是原始引用。这就是为什么重定向方法中的引用不会重定向传入的引用。

希望这可以解决问题。

答案 1 :(得分:3)

Java确实按值传递,但它传递的是对象引用的值,它给出了引用传递的效果(对于基元,它的行为更像是按值传递)。

但是Java 总是按值传递。

答案 2 :(得分:2)

Java 按值传递,但是当我们传递一个对象引用时,引用值传递给方法,并且从那里方法可以更改对象成员的值。

请看以下代码:

public class Passbyvalue {

    public static void main(String[] args) {
        // TODO code application logic here
        Animal animal=new Animal();
        animal.name="Dog";
        System.out.println(animal.name);
        testIt(animal);
        System.out.println(animal.name);
    }


    public static void testIt(Animal animal){
        animal.name="Cat";
    }

}

输出

犬 猫

这是因为引用(原始和方法)都指向同一个对象。

    __________
   |          |                 
   |          |<------------- Orignal Reference 
   | Object   |   
   |          |<------------- Method Reference
   |          |
   |__________|

如果您想更清楚地看到此效果,请在方法

中创建新对象
public class Passbyvalue {

    public static void main(String[] args) {
        Animal animal=new Animal();
        animal.name="Dog";
        System.out.println(animal.name);
        testIt(animal);
        System.out.println(animal.name);
    }


    public static void testIt(Animal animal){
        animal=new Animal();
        animal.name="Cat";
    }

}

输出: 狗 狗

现在,方法引用将发布到堆中的其他Object。

答案 3 :(得分:1)

最初你新建两个对象,打印出以下内容:

X1: 0 Y1: 0
X2: 0 Y2: 0

当你调用tricky()时,你通过值传递对pnt1和pnt2的引用,并将它们分配给arg1和arg2。所以你要在内存中传递位置。然后打印值:

Arg1: 100100
Arg2: 00
Arg1: 00
Arg2: 100100

使用temp进行交换时,您正在交换地址。所以回到你的主要方法pnt1和pnt2仍然保留原始地址。因此,当你打印时,你得到:

X1: 100 Y1:100
X2: 0 Y2: 0

这是一个相关的thread,有一些额外的背景。

答案 4 :(得分:0)

我曾经使用&#34;图形方法&#34;来解释这个,所以我希望它有所帮助。在main中,在调用tricky方法之前,您有:

pnt1 -> Point(x=0; y=0)
pnt2 -> Point(x=0; y=0)

tricky方法内,arg1arg2分别是pnt1pnt2引用的副本,因此它们指向相同的对象:< / p>

pnt1 -> Point(x=0; y=0) <- arg1
pnt2 -> Point(x=0; y=0) <- arg2

通过arg1引用,您正在修改第一个Point对象:

pnt1 -> Point(x=100; y=100) <- arg1
pnt2 -> Point(x=0; y=0) <- arg2

然后,你是&#34;指着&#34; temp对第一个Point(100; 100)对象的引用。之后,使arg1指向arg2引用的相同对象-Point(0,0) - ,并使arg2指向temp已指向的同一对象。 1}},即Point(100; 100)。因此,在tricky方法内部交换了内存地址arg1arg2所指的内容。

pnt1 -> Point(x=100; y=100) <- arg2 (temp also pointing this object)
pnt2 -> Point(x=0; y=0) <- arg1

但是一旦方法完成,arg1和arg2(和temp)超出了范围(消失),你再次拥有:

pnt1 -> Point(x=0; y=0)
pnt2 -> Point(x=0; y=0)

pnt1pnt2未按预期更改,因为tricky方法内的所有更改都在arg1arg2上执行,这些只是引用。

因此,在tricky内你可以更改对象的内容(你有对它的引用),但是你不能修改对它的原始引用,因为你只有一个副本它的。所以 Java 传递值(实际上是传递的值)。