上記のツールキットの回答は正しく、最良の方法ですが、何が起こっているのかを完全に説明するものではありません。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」のメモリ アドレスは変更されていないことがわかります。
(実生活でこのように反射を使用しないでください!!)