2011-01-20 14 views
3

2つの文字列を比較すると、論理演算子(==)を使用しないでください。比較のためにString.equals(String)を使用する必要があります。しかし、私は、次のコードが最新のJDK(1.6_23)で "Hello Friend"に準拠していることを確認しています。私は周りを探索しようとし、参照を見つけることができませんでした。いつ起きているのですか?それは、あなたが考える他の何かをするためJavaの論理演算子との文字列比較

public class StringComp{ 
public static void main(String args[]){ 
     String s = "hello"; 
     if(s=="hello"){ 
       System.out.println("Hello Friend"); 
     }else{ 
       System.out.println("No Hello"); 
     } 
    } 
} 
+2

http://stackoverflow.com/questions/767372/java-string-equals-versus –

+1

参照http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java (受け入れられた答えはインターンに言及しています) – finnw

+1

私はこれが欺瞞だとは思わない。この質問は「なぜそれは通常動作しないのですか」ではなく「時には機能するのはなぜですか?」と質問しています – finnw

答えて

10

あなたは==を使用しないでください。

この場合、「hello」が保存されます(文字列インターネット上で読み上げる)ので、あなたの攪拌と同じことが「偶然」です。

==は、2つのものが同じ内容であるかどうかをチェックします。同じ内容のものではありません。これは本当に大きな違いです。偶発的な(間違っていても)「偽りの存在」は、この方法を使用する理由ではありません。

文字列比較にequalsを使用するだけです。このサイトから

例: http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/

String a = new String ("a"); 
String b = new String ("a"); 
System.out.println (a == b); 

次のコードは、trueを返す一方でそれは、falseを返します。

String a = new String ("a"); 
String b = new String ("a"); 
System.out.println (a.equals(b)); 
+0

「interning」が追加された場合、それは私が忘れた単語です) – Nanne

2

==オペレータは.equalsの値を比較しながら、両方が同じ文字列オブジェクトへの参照であるかどうかを確認するために使用されます。

2

sは文字列リテラル"hello"を参照しているため、あなたのケースでも動作します(AFAIKはこれまでのJVMでも同様に動作しています)。リテラルで初期化された文字列参照は、別途作成された新しいオブジェクトではなく、リテラル(バックグラウンドではグローバルオブジェクト)を参照します。これについての言葉は、他の人も触れたように、インターンシップです。したがって、例のs"hello"は、同じ物理オブジェクトを参照しています。

String s1 = "hello"; 
String s2 = "hello"; 
String s3 = "hello"; 

これらの文字列のすべてが「==」これらの任意のペア間の比較、またはそれらのいずれかと"hello"戻りtrueの間でこのように、同一の物理オブジェクトを参照して考えてみましょう。

しかし

String s4 = new String ("hello"); 

のでs4 == "hello"利回りfalse、新しいオブジェクトを作成します。

+0

詳細な回答ありがとうございます。 s2 == "hello"はtrueを返します。 s4 == "hello"はfalseを返します。 – Sundeep

+0

@Sundeep、はい、これはタイプミスで、今修正されました:-) –

4

魔法はインターナショナルと呼ばれます。

ジャワインターン文字列リテラルなどがそれが真と評価が高い確率は、次のとおり、

String a = "hello";  // "hello" is assigned *and* interned 
String b = "hello";  // b gets a reference to the interned literal 
if (a == b) 
    System.out.println("internd."); 

String c = "hello" + Math.abs(1.0); // result String is not interned 
String d = "hello" + Math.abs(1.0); // result String is not interned 
System.out.println(c==d);    // prints "false" 

c = c.intern(); 
System.out.println(c==d);    // prints "false" 

d = d.intern(); 
System.out.println(c==d);    // prints "true" 
-1

==は、オブジェクト参照を比較する(等しい)の文字列の値を比較します。

あなたの場合、値「hello」を持つ2つのStringオブジェクトを割り当てて、それらを==と比較します。コンパイラは、同じオブジェクト参照を最適化して使用することを決め、得た結果と同じような真の結果を得ます。ただし、これは保証されている動作ではありません。値の比較にequals()を使用する方がはるかに安全です。

+1

* "コンパイラは最適化を決めるかもしれません" * - これは正確ではありません。文字列リテラルは常にインターナショナルです。 – finnw

0

"JVMがクラスファイルから文字列リテラルをロードして実行するたびに、その文字列が存在するかどうかをチェックします(指定された文字列が存在するかどうかをチェックします) JVMは、このタイプのチェックをStringリテラルに対して内部的に行いますが、Stringオブジェクトに対してはチェックしません(リスト内に存在する場合)。 'new'キーワードを使用して作成します。これにより、JVMはString.intern()メソッドを使用して 'new'キーワードによって作成されたStringオブジェクトに対してこのタイプのチェックを強制的に実行できます。オブジェクトが既に存在する場合はオブジェクト。

結論として、JVMは内部的にStringリテラル用の一意のStringオブジェクトを保持します。プログラマーは文字列リテラルについて気にする必要はありませんが、 'new'キーワードを使って作成されたStringオブジェクトについては気にする必要があります。また、intern()メソッドを使用してヒープメモリ内にStringオブジェクトが重複してJavaパフォーマンスが向上しないようにする必要があります。 。詳細については、次のセクションを参照してください」

参考:PreciseJava.com - Optimization techniques in Strings and StringBuffer (How the JVM works with Strings)

+0

詳細な説明をありがとうございます。 – Sundeep

0

==あなたは、次のコードで出力を観察することによって、それを理解することができ、オブジェクト参照に

を比較:

public class StringComp{ 
    public static void main(String args[]){ 
     String s = new String("hello"); 
     if(s=="hello"){ 
       System.out.println("Hello Friend"); 
     }else{ 
       System.out.println("No Hello"); 
     } 
    } 
} 

このプログラムは印刷するでしょうNo hello

このコードでは、可能なsは新しい文字列オブジェクトを参照し、これは文字列プールから文字列リテラル "hello"を参照します。