上面工具包的答案是正确的,也是最好的方法,但它没有对正在发生的事情给出完整的解释。假设 Java 5 或更高版本:
Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a); // will output 20
您需要知道的是,这与执行以下操作完全相同:
Integer a = new Integer(2); // or even just Integer a = 2;
a = a.intValue() * 10;
System.out.println(a.intValue()); // will output 20
通过对对象“a”执行操作(在本例中为 *=),您不会更改“a”对象内的 int 值,而是实际上将新对象分配给“a”。这是因为“a”被自动拆箱以执行乘法,然后乘法的结果被自动装箱并分配给“a”。
整数是不可变的对象。(所有包装类都是不可变的。)
以这段代码为例:
static void test() {
Integer i = new Integer(10);
System.out.println("StartingMemory: " + System.identityHashCode(i));
changeInteger(i);
System.out.println("Step1: " + i);
changeInteger(++i);
System.out.println("Step2: " + i.intValue());
System.out.println("MiddleMemory: " + System.identityHashCode(i));
}
static void changeInteger(Integer i) {
System.out.println("ChangeStartMemory: " + System.identityHashCode(i));
System.out.println("ChangeStartValue: " + i);
i++;
System.out.println("ChangeEnd: " + i);
System.out.println("ChangeEndMemory: " + System.identityHashCode(i));
}
输出将是:
StartingMemory: 1373539035
ChangeStartMemory: 1373539035
ChangeStartValue: 10
ChangeEnd: 11
ChangeEndMemory: 190331520
Step1: 10
ChangeStartMemory: 190331520
ChangeStartValue: 11
ChangeEnd: 12
ChangeEndMemory: 1298706257
Step2: 11
MiddleMemory: 190331520
你可以看到'i'的内存地址正在改变(你的内存地址会不同)。
现在让我们用反射做一个小测试,将它添加到 test() 方法的末尾:
System.out.println("MiddleMemory: " + System.identityHashCode(i));
try {
final Field f = i.getClass().getDeclaredField("value");
f.setAccessible(true);
f.setInt(i, 15);
System.out.println("Step3: " + i.intValue());
System.out.println("EndingMemory: " + System.identityHashCode(i));
} catch (final Exception e) {
e.printStackTrace();
}
额外的输出将是:
MiddleMemory: 190331520
Step2: 15
MiddleMemory: 190331520
您可以看到“i”的内存地址没有改变,即使我们使用反射改变了它的值。
(不要在现实生活中以这种方式使用反射!!)