2

我想我理解它是传递给方法的对象/数据成员的副本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);  

}
}
4

5 回答 5

5

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

希望这可以解决问题。

于 2012-07-24T02:59:53.397 回答
3

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

但是Java总是按值传递。

于 2012-07-24T03:01:33.500 回答
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";
    }

}

输出:狗狗

现在方法引用正在发布到堆中的另一个对象。

于 2013-01-02T11:34:09.820 回答
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

这是一个带有一些额外背景的相关线程。

于 2012-07-24T03:10:17.043 回答
0

我曾经使用“图形方法”来解释这一点,所以我希望它有所帮助。在main,在调用tricky方法之前,您有:

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

内部tricky方法,arg1和分别是和引用arg2的副本,因此它们指向相同的对象:pnt1pnt2

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

然后,您将“指向”对temp第一个 Point(100;100) 对象的引用。之后,您arg1指向指向arg2-Point(0,0)- 的同一对象,并arg2指向已由 指向的同一对象temp,即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方法内部的所有更改都是在arg1和上执行的arg2,它们只是引用的副本。

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

于 2012-07-24T04:06:01.360 回答