我想我明白它是传递给方法tricky()
的对象/数据成员的副本,因为只有值才是重要的,而不是实际的对象本身。但是打印语句向我保证,arg1
和arg2
副本确实在方法中切换。我不明白为什么这不会将信息传回原始对象,从而切换它们;看作该方法能够成功访问方法中的arg1.x
和arg1.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);
}
}
答案 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
方法内,arg1
和arg2
分别是pnt1
和pnt2
引用的副本,因此它们指向相同的对象:< / 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
方法内部交换了内存地址arg1
和arg2
所指的内容。
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)
pnt1
和pnt2
未按预期更改,因为tricky
方法内的所有更改都在arg1
和arg2
上执行,这些只是引用。
因此,在tricky
内你可以更改对象的内容(你有对它的引用),但是你不能修改对它的原始引用,因为你只有一个副本它的。所以 Java 是传递值(实际上是传递的值)。