web-dev-qa-db-ja.com

なぜ== Integer.valueOf(String)と比較すると、127と128で異なる結果が得られるのですか?

これらのコード行が異なる値を返す理由はわかりません。

System.out.println(Integer.valueOf("127")==Integer.valueOf("127"));
System.out.println(Integer.valueOf("128")==Integer.valueOf("128"));
System.out.println(Integer.parseInt("128")==Integer.valueOf("128"));

出力は次のとおりです。

true
false
true

最初のものがtrueを返し、2番目のものがfalseを返すのはなぜですか? 127128の間に私が知らない何か違うものはありますか? (もちろん、127 <128であることは知っています。)

また、なぜ3番目のものはtrueを返すのですか?

私は答えを読みました この質問の ですが、trueを返す方法と、2行目のコードがfalseを返す理由がまだわかりませんでした。

177
DnR

ここには顕著な違いがあります。

valueOfIntegerオブジェクトを返し、その値は-128〜127の間にキャッシュされます。これが、最初の値がtrue-キャッシュされている-と2番目の値を返す理由ですfalseを返します-128はキャッシュされた値ではないため、2つの別個のIntegerインスタンスを取得しています。

注意することは重要です参照をInteger#valueOfと比較していること、そしてキャッシュがサポートする値よりも大きい値を比較している場合、not解析された値が同等であっても、trueに評価されます(ケースの例:Integer.valueOf(128) == Integer.valueOf(128))。 代わりにequals()を使用する必要があります。

parseIntはプリミティブintを返しています。これが3番目の値がtrueを返す理由です-128 == 128が評価され、もちろんtrueです。

さて、3番目の結果trueがたまたま生成されました:

  • ボックス化解除の変換が発生します 使用している等価演算子と使用しているデータ型に関して-つまり、intInteger。もちろん、右側のIntegerからvalueOfを取得しています。

  • 変換後、2つのプリミティブint値を比較しています。比較は、プリミティブに関して期待どおりに行われるため、128128を比較することになります。

189
Makoto

Integerクラスには静的キャッシュがあり、256個の特別なIntegerオブジェクトを保存します--128〜127の間のすべての値に1つ。これを念頭に置いて、これら3つの違いを考慮してください。

_new Integer(123);
_

これは(明らかに)真新しいIntegerオブジェクトを作成します。

_Integer.parseInt("123");
_

これは、intを解析した後、Stringプリミティブ値を返します。

_Integer.valueOf("123");
_

これは他のものよりも複雑です。 Stringを解析することから始めます。次に、値が-128〜127の場合、対応するオブジェクトを静的キャッシュから返します。値がこの範囲外の場合、new Integer()を呼び出して値を渡し、新しいオブジェクトを取得します。

ここで、質問の3つの式を検討してください。

_Integer.valueOf("127")==Integer.valueOf("127");
_

値が127のIntegerが静的キャッシュから2回取得され、それ自体と比較されるため、これはtrueを返します。含まれるIntegerオブジェクトは1つだけなので、trueを返します。

_Integer.valueOf("128")==Integer.valueOf("128");
_

128は静的キャッシュにないため、これはfalseを返します。そのため、等式の両側に新しいIntegerが作成されます。 2つの異なるIntegerオブジェクトがあり、オブジェクトの_==_は、両側がまったく同じオブジェクトである場合にのみtrueを返すため、これはfalseになります。

_Integer.parseInt("128")==Integer.valueOf("128");
_

これは、左側のプリミティブint値128と、右側の新しく作成されたIntegerオブジェクトを比較しています。ただし、intIntegerと比較することは意味をなさないため、Javaは、実行前にIntegerを自動的にunboxします比較;したがって、intintと比較することになります。プリミティブ128はそれ自体に等しいため、trueを返します。

122

これらのメソッドから値を返すように注意してください。 valueOfメソッドは整数インスタンスを返します:

public static Integer valueOf(int i)

parseIntメソッドは整数値(プリミティブ型)を返します。

public static int parseInt(String s) throws NumberFormatException

比較の説明:

メモリを節約するために、ラッパーオブジェクトの2つのインスタンスは、プリミティブ値が同じ場合は常に==になります。

  • ブール
  • バイト
  • \ u0000から\ u007fまでの文字(7fは10進数で127)
  • -128〜127の短整数

==を使用してプリミティブをラッパーと比較すると、ラッパーはアンラップされ、比較はプリミティブからプリミティブになります。

あなたの状況(上記のルールによる):

Integer.valueOf("127")==Integer.valueOf("127")

この式は、-128〜127の整数値を含むため、trueを返すため、同じオブジェクトへの参照を比較します。

Integer.valueOf("128")==Integer.valueOf("128")

この式は、異なるオブジェクトへの参照を比較します。これらのオブジェクトには<-128、127>にない整数値が含まれているため、falseが返されます。

Integer.parseInt("128")==Integer.valueOf("128")

この式は、プリミティブ値(左側)とオブジェクトへの参照(右側)を比較するため、右側はアンラップされ、プリミティブ型は左側と比較されるため、trueが返されます。

13
piobab

256の整数のうち-128〜127の間の整​​数オブジェクトキャッシュ

オブジェクト参照を==または!=と比較しないでください。代わりに.equals(..)を使用するか、より良い方法-整数ではなくプリミティブintを使用してください。

parseInt:文字列引数を符号付き10進整数として解析します。文字列の文字はすべて10進数でなければなりませんが、最初の文字は負の値を示すためにASCIIマイナス記号 '-'( '\ u002D')である場合があります。結果の整数値引数と基数10がparseInt(Java.lang.String、int)メソッドの引数として指定された場合とまったく同じように返されます。

valueOf 2番目の引数で指定された基数で解析された場合、指定されたStringから抽出された値を保持するIntegerオブジェクトを返します。最初の引数は、引数がparseInt(Java.lang.String、int)メソッドに渡された場合とまったく同じように、2番目の引数で指定された基数の符号付き整数を表すと解釈されます。結果は、文字列で指定された整数値を表すIntegerオブジェクトです。

に相当

_new Integer(Integer.parseInt(s, radix))
_

radix-sの解釈に使用される基数

そのため、その間の整数がInteger.valueOf()に等しい場合

-128〜127は、条件でtrueを返します。

_lesser than_ -128および_greater than_ 127の場合、falseが得られます

6
Nambi

指定された回答を補完するために、次の点にも注意してください。

public class Test { 
    public static void main(String... args) { 
        Integer a = new Integer(129);
        Integer b = new Integer(129);
        System.out.println(a == b);
    }
}

このコードは以下も出力します:false

ユーザー Jay は受け入れられた回答のコメントを要求しているため、オブジェクトで演算子==を使用する場合は注意が必要です。ここでは、両方の参照が同じかどうかを確認しています。 、これらはまったく同じ値を表しますが、異なるオブジェクトであるためです。オブジェクトを比較するには、代わりにequalsメソッドを使用する必要があります。

Integer a = new Integer(128);
Integer b = new Integer(128);
System.out.println(a.equals(b));

これは印刷されます:true

しかし、最初の行がtrueを印刷した理由を尋ねることができます。 Integer.valueOfメソッドのソースコードを確認すると、次のことがわかります。

public static Integer valueOf(String s) throws NumberFormatException {
    return Integer.valueOf(parseInt(s, 10));
}

public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

ParamがIntegerCache.low(デフォルトは-128)とIntegerCache.high(実行時に最小値127で計算)の間の整数である場合、事前に割り当てられた(キャッシュされた)オブジェクトが返されます。したがって、127をパラメーターとして使用すると、同じキャッシュオブジェクトへの2つの参照が取得され、参照の比較でtrueが取得されます。

6
higuaro