上面的工具包的答案是正確的,也是最好的方法,但它並沒有給出正在發生的事情的完整解釋。 假設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
你可以看到, 「我」的內存地址沒有改變,即使我們使用反射改變了它的值。
(請不要在實際生活中使用這種反射方式!)
我還建議你檢查一下使用Integer是否真的需要。 Joshua指出在有效Java中使用原語要快很多倍。所以,如果可以的話,堅持** int **。 – 2008-09-05 15:54:56
使用Integer實際上是一個設計約束。這個想法是我得到一個Integer對象,我必須更新它。所以,不能取消:) – Jagmal 2008-09-05 17:40:24