Javaで「Integer」オブジェクトに10を掛けるにはどうすればよいですか?
質問
10 を 1 に掛けるにはどうすればよいですか Integer
反対して取り返してください Integer
物体?
これを行う最もきちんとした方法を探しています。
私はおそらく次のようにするでしょう:int の取得元 Integer
オブジェクトを作成し、それを他の int と乗算し、この int 値を持つ別の Integer オブジェクトを作成します。
コードは次のようなものになります...
integerObj = new Integer(integerObj.intValue() * 10);
しかし、作者がこのようにしているコードを見ました。入手 String
から Integer
オブジェクトの最後に「0」を連結して取得します。 Integer
を使用してオブジェクトを戻す Integer.parseInt
コードは次のようなものです:
String s = integerObj + "0";
integerObj = Integer.parseInt(s);
どちらにしてもやるメリットはあるのでしょうか?
そして、この場合、一般的に最も効率的/最も適切な方法は何でしょうか?
解決
Java 5 の場合 オートボクシング, 、次のようにするだけで済みます。
Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a);
他のヒント
文字列のアプローチは面白いですが、ほぼ確実に悪い方法です。
Integer の int 値を取得して新しい値を作成するのは非常に高速ですが、parseInt の呼び出しにはかなりのコストがかかります。
全体として、私はあなたの元のアプローチに同意します(他の人が指摘しているように、Java 5で導入されたオートボクシングがあれば、それほど混乱せずに実行できます)。
2 番目の方法の問題は、Java での文字列の処理方法です。
"0"
コンパイル時に定数 String オブジェクトに変換されます。このコードが呼び出されるたびに、
s
新しい String オブジェクトとして構築され、javac
そのコードをに変換しますString s = new StringBuilder().append(integerObj.toString()).append("0").toString()
(古いバージョンの場合は StringBuffer)。同じものを使っていても、integerObj
, 、つまり、String s1 = integerObj + "0"; String s2 = integerObj + "0";
(s1 == s2)
だろうfalse
, 、 その間s1.equals(s2)
だろうtrue
.Integer.parseInt
内部呼び出しnew Integer()
とにかく、なぜならInteger
は不変です。
ところで、自動ボックス化/ボックス化解除は内部的には最初の方法と同じです。
2 番目のアプローチは避けてください。Java 1.5 を使用している場合、最善の方法はオートボックス化です。最初の例より前のものが最適です。
String メソッドを使用した解決策は、さまざまな理由からあまり適切ではありません。美的な理由もあれば、実用的な理由もあります。
実用的な面では、(最初の例で表現したように) より通常の形式よりも String バージョンによってより多くのオブジェクトが作成されます。
美的観点から言えば、2 番目のバージョンではコードの意図がわかりにくくなっており、それはコードで目的の結果を生成することと同じくらい重要だと思います。
上記のツールキットの答えは正しく、最良の方法ですが、何が起こっているのかを完全に説明していません。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」のメモリ アドレスは変更されていないことがわかります。
(実生活ではこのように反射を使用しないでください!!)