确定。我完全清楚Java中的所有值都是按值传递的。但是这个例子并没有像我预期的那样:
public class Test {
private static void changeInteger(Integer x) {
x = 5;
}
public static void main(String[] args) {
Integer x = 0;
changeInteger(x);
System.out.println(x);
}
}
因为我将包装类传递给changeInteger方法,所以我传递了它的地址,因此,在执行了应该影响我的x变量的函数并将其设置为5.但是eclipse说输出仍然是0。我明白错了?
答案 0 :(得分:6)
考虑这个例子:
class Wrapper {
int n;
public Wrapper(int k) { n = k; }
public String toString() { return ""+n;}
public static Wrapper valueOf(int k) { return new Wrapper(k); }
}
现在让我们使用上面的Integer
类替换代码中的Wrapper
:
private static void changeInteger(Wrapper x) {
x = Wapper.valueOf(5);
}
public static void main(String[] args) {
Wrapper x = Wrapper.valueOf(0);
changeInteger(x);
System.out.println(x);
}
既然你提到你知道按值传递,我希望很明显为什么这段代码会做它的作用。
现在让我们回到您的代码。在引擎盖下,它是完全相同的代码。唯一的区别是你没有调用Wrapper.valueOf
:编译器通过 autoboxing 为你做。一旦你意识到这是正在发生的事情,你应该清楚这个问题。
changeInteger()
的 ByteCode 以显示Integer.valueOf()
被调用:
private static void changeInteger(java.lang.Integer);
Code:
Stack=1, Locals=1, Args_size=1
0: iconst_5
1: invokestatic #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
teger;
.... // some other code
答案 1 :(得分:4)
使用x = 5;
为x
内的changeInteger()
分配新值。您没有更改当前Integer
对象的值。
方法外的x
值不受影响。
答案 2 :(得分:2)
你的问题是Java是按值传递而不是引用,因此方法中的x
与main x
不同。 Integer是一个不可变类的事实,这里不会改变任何东西。
答案 3 :(得分:2)
你对java的自动装箱功能感到困惑。您无法将原始值分配给对象。当您致电x=5
时,它会创建一个包含5个值的新Integer
对象,并指定其对x
的引用。但这仅影响changeIngeger
范围内的参数,原始对象为0,主范围内的x引用未受影响。
答案 4 :(得分:1)
所有Java参数都按值传递。对于所有非基本类型,该值包含对传递的对象的引用。
对于您的代码,Integer对象存储在内存中的A
位置。内存中的另一个位置B
代表main
的变量x
,并存储值A
。
对于changeInteger
来电,会创建一个新位置C
,并将B
中的值(A
)复制到该位置。这是x
函数的本地changeInteger
。
通过分配,您可以创建一个存储在D
的新变量,并将其位置分配给C
。然后你从方法返回。
您可以看到A
和B
未在任何地方进行修改,因此值保持不变。
答案 5 :(得分:0)
保持简单,所有Java Wrapper类都是不可变的。所以你无法看到变化。
如果您想查看更改,只需从方法(不是主)返回并重新分配。