2013-03-06 16 views
5

次のコードでobjオブジェクトとobj2オブジェクトの作成方法の違いを理解できません。特に、プリミティブがどのようにオブジェクトにキャストされるのかはわかりません。他のいくつかの質問を見ると、これは不可能だと思った。しかし、以下のプログラムはコンパイルして正常に動作します。最初のケースでは、出力はfalseであり、2番目のケースではtrueです。== Javaのオブジェクトの演算子

public class Test { 

    public static void main(String args[]){ 

     Integer num = new Integer(3) ; 
     Object obj = num; 
     Integer[] integerArr = {1, 2, 3, 4}; 
     Object[] objArr = integerArr; 
     boolean contains = false; 

     for (int i = 0; i < objArr.length; i++){ 
      if (objArr[i] == obj){ 
       contains = true; 
       break; 
      } 
     } 

     System.out.println(contains); 

     int num2 = 3 ; 
     Object obj2 = num2; 
     Integer[] integerArr2 = {1, 2, 3, 4}; 
     Object[] objArr2 = integerArr2; 
     boolean contains2 = false; 

     for (int i = 0; i < objArr2.length; i++){ 
      if (objArr2[i] == obj2){ 
       contains2 = true; 
       break; 
      } 
     } 

     System.out.println(contains2); 
    } 

} 
+4

あなたは幸いです。 'Integer'オブジェクトは小さな値のためにキャッシュされます。 – Mysticial

+0

@神秘的な:ありがとう –

+1

複製、複製、複製..今すぐそれらを見つける。 –

答えて

3

あなたは、後者の場合には、コンパイラはキャッシュを使用して、あなたのための変換を行いながら、新しいIntegerオブジェクトを作成する最初のケースでjava.lang.Integer

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); 
} 

からこの方法を理解する必要があります。ここで

/** 
* Cache to support the object identity semantics of autoboxing for values between 
* -128 and 127 (inclusive) as required by JLS. 
* 
* The cache is initialized on first usage. The size of the cache 
* may be controlled by the -XX:AutoBoxCacheMax=<size> option. 
* During VM initialization, java.lang.Integer.IntegerCache.high property 
* may be set and saved in the private system properties in the 
* sun.misc.VM class. 
*/ 

それはIntegerコンストラクタまたはInteger.valueOf呼び出して終了方法を参照するには、関連するバイトコードです:第2のケースで

0: new #2; //class java/lang/Integer 
3: dup 
4: iconst_3 
5: invokespecial #3; //Method java/lang/Integer."<init>":(I)V 
8: astore_1 
9: aload_1 
10: astore_2 
11: iconst_4 
12: anewarray #2; //class java/lang/Integer 
15: dup 
16: iconst_0 
17: iconst_1 
18: invokestatiC#4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
21: aastore 
... 
90: iconst_3 
91: istore 6 
93: iload 6 
95: invokestatiC#4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
98: astore 7 
100: iconst_4 
101: anewarray #2; //class java/lang/Integer 
104: dup 
105: iconst_0 
106: iconst_1 
107: invokestatiC#4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
110: aastore 
111: dup 
... 
+0

@ Mysticialのコメントを明確にしてくれてありがとう。これは私が探していたものです。 –

4

同一ためのオブジェクト・テストの間に==演算子(2つのオブジェクトが正確に同じである場合)、等価(2つのオブジェクトが同じ値を有するか否か)のための方法equals()テスト一方。

ほとんどの場合、平等に関心があります。偶然にも、Integerオブジェクトがキャッシュされているため(通常は-127〜127の範囲で設定可能ですが)、実際にはという質問で入力した例はですが、より大きな数字を使用してIDをテストした場合はかなり可能ですテストが失敗することを示します。

例えば、これはtrueと評価されます:この一方

Integer a = 127; 
Integer b = 127; 
a == b // true 

falseと評価されます!

Integer a = 128; 
Integer b = 128; 
a == b // false 

ボトムライン:それは安全で再生すると、常にオブジェクト間の平等をテストするためequals()を使用しています。

+1

ありがとうございました。私はequalsメソッドについて知っていますが、私はそれを使用していますが、上記のいずれかのケースで==が動作していた理由について興味がありました。 –

0

を、あなたはプリミティブintを比較していますオブジェクトInteger配列。 JVMは、オブジェクトIntegerを「アンラッピング」し、プリミティブと比較します。したがって、その場合は等価マッチを取得します。

最初のケースでは、常にオブジェクトを別のオブジェクトと比較しています。この例では、これらは決して等しくありません。

1

== object1とobject2が参照型である場合、==はobject1とobject2が両方とも同じオブジェクトへの参照であるかどうかをチェックします。

と等しい object1を使用する場合。

使用String.equals(他の文字列)関数文字列を比較する、しない==演算子:等しい(オブジェクト2)それは、オブジェクト

例の実際の値を比較します。

この関数は文字列の実際の内容をチェックし、==演算子はオブジェクトへの参照が等しいかどうかをチェックします。