有人可以解释一下这个程序是如何执行的吗?
这是代码,其输出我似乎无法得到它:
class Box {
int size;
Box (int s) {
size = s;
}
}
public class Laser {
public static void main(String[] args) {
Box b1 = new Box(5);
Box[] ba = go(b1, new Box(6));
ba[0] = b1;
for(Box b : ba)
System.out.println(b.size + " ");
}
static Box[] go (Box b1, Box b2) {
b1.size = 4;
Box[] ma = {b2, b1};
return ma;
}
}
我运行时的实际输出是4,4。但根据我的理解,这应该是5,4。 任何人都可以帮助了解这是如何执行的?
答案 0 :(得分:3)
我已为您添加了评论;
The important TWIST that you missed here is;
Box[] ma = {b2, b1};
不是{b1,b2}
。返回时内存位置互换。
public static void main(String[] args) {
Box b1 = new Box(5); // b1 == location A
Box[] ba = go(b1, new Box(6)); // ba == location B which stores Location A, D
// PLEASE NOTE HERE
// After the function go() is executed;
// ba[] will have {D, A}
// So ba[0] will have object b1 which is at location A.
ba[0] = b1; // location B will now store A and A
for(Box b : ba)
System.out.println(b.size + " "); // Output: 4 and 4
}
static Box[] go (Box b1, Box b2) { // go(location A, location D )
b1.size = 4; // A's object.size = 4
Box[] ma = {b2, b1}; // position is interchanged here (D and A)
return ma; // return the location of ma
}
希望这会有所帮助。
如果您有任何疑问,请告诉我。一切都是在java中传递的。内存地址按值传递。
答案 1 :(得分:0)
当您将对象作为参数传递时,实际上是将的引用副本传递给它。也就是说,如果修改方法内的参数对象,该对象将在该方法返回时保留这些修改,这就是b1
在size = 4
返回后保留go
赋值的原因。
答案 2 :(得分:0)
Java总是在方法调用中传递对象的引用。当您致电go
时,第一个参数(b1
)是对您b1
中相同的Box
main
的引用。然后,您可以修改该size
现在为4
的对象。
答案 3 :(得分:0)
传递给go
的值是对象的引用。如果您来自C,您可以将参数视为具有指针类型,例如
Box** go (Box *b1, Box *b2) {
b1->size = 4;
/* allocate an array of Box*, set it up, return it */
}
(对不起,如果我的C语法错误。)指针(引用)本身是按值传递的,这意味着如果你在里面说“go”(在C程序中):
b1 = &some_other_box;
它不会影响调用端的任何变量,它在Java中的工作方式相同。这使得它与PHP或Pascal中的var
参数略有不同。
答案 4 :(得分:0)
Java在方法调用中传递对象的引用副本。
您无法通过分配对象来更改对象。
public static void main(String[] args) {
Box b1 = new Box(5);
Change(b1);
System.out.println(b1.size + " ");
static void Change(Box b1) {
b1 = new Box(6);
}
这将始终返回5,因为函数Change
仅将副本覆盖到引用的对象。
但是你可以像这样影响对象的属性:
public static void main(String[] args) {
Box b1 = new Box(5);
Change(b1);
System.out.println(b1.size + " ");
static void Change(Box b1) {
b1.size = 6;
}
这将返回6(对象的引用保持不变)。
答案 5 :(得分:0)
如果原始帖子中的'go'函数在C中(并且b1和b2是C指针),它可以执行以下两项操作(调用者将看到):
在Java中,我们可以做1但不是2,因为go无法访问原始的b1和b2。 (它可以访问b1和b2的副本。在子程序开始时,副本b1指向与原始b1相同的对象,依此类推。)
说Java是逐个调用DOES错过的东西,即函数执行1的能力,即改变b1和b2引用的堆中对象的属性。 [这是声明中发生的事情,b1.size = 4;,这导致了原始海报的混乱。]
'go'中的b1与'main'中的b1位置不同。但是,当函数开始时,'go'中的b1引用与'main'中的b1相同的对象,并且当'main'中的b1用作引用时,将看到使用'go'中的b1对对象所做的任何更改。
但是,如果'go'中的b1设置为另一个Box,'main'中的b1将不会看到这个;它仍会看到前一个Box。
答案 6 :(得分:-1)
在Java中,对象通过引用传递,基元通过值传递。
public class Laser {
public static void main(String[] args) {
//Create a Box of size 5.
Box b1 = new Box(5);
//Create an array of Box objects, which are the results of the go method
Box[] ba = go(b1, new Box(6));
// ba now looks like {new Box(6), b1 /*b1 is size 4 now*/}
// assign reference to b1 at index 0 in ba.
ba[0] = b1;
// array now looks like {b1, b1}
for(Box b : ba)
System.out.println(b.size + " ");
}
static Box[] go (Box b1, Box b2) {
//set the size of the first box to 4
b1.size = 4;
//create an array of boxes, with b2 in index 0 and b1 in index 1
Box[] ma = {b2, b1};
return ma;
}
}