web-dev-qa-db-ja.com

Javaの一部の文字列で参照比較(==)が機能するのはなぜですか?

文字列を比較する次のコード行があります。 str1はstr2と等しくありません。これは、オブジェクト参照を比較するので理解できます。しかし、なぜs1がs2に等しいのでしょうか。

String s1 = "abc";
String s2 = "abc";

String str1 = new String("abc");
String str2 = new String("abc");

if (s1==s2)
    System.out.println("s1==s2");           
else
    System.out.println("s1!=s2");

if (str1==str2)
    System.out.println("str1==str2");           
else
    System.out.println("str1!=str2");

if (s1==str1)
    System.out.println("str1==s1");         
else
    System.out.println("str1!=s1");

出力:

  s1==s2
  str1!=str2
  str1!=s1 
60
user84592

文字列定数プールは基本的にすべての文字列リテラルをキャッシュするので、それらはその下にある同じオブジェクトです。そのため、s1==s2の出力が表示されます。これは、本質的にVMの最適化であり、リテラルが宣言されるたびに新しい文字列オブジェクトを作成することを回避します。これは非常にすぐに高価になる可能性があります!str1==str2の例では、明示的に= VM新しい文字列オブジェクトを作成するため、なぜそれが偽であるか。

余談ですが、任意の文字列でintern()メソッドを呼び出すと、定数プールに追加されます(そして、プールに追加された文字列が返されます)。必ず定数として使用される文字列を処理していることを確認してください。そうしないと、メモリリークを追跡するのが困難になる可能性があります。

86
Michael Berry

s1とs2は文字列リテラルです。新しい文字列リテラルを作成すると、コンパイラは最初に、それを表すリテラルが文字列プールに存在するかどうかをチェックします。存在する場合、コンパイラはそのリテラルを返します。それ以外の場合、コンパイラは新しいリテラルを作成します。

String s2を作成すると、以前に作成されたとおり、コンパイラーはプールからString s1を返します。これが、s1s2が同じである理由です。この動作はinterningと呼ばれます。

21
Chandra Sekhar

この現象は Stringinterning によるものです。

基本的に、すべての文字列リテラルは「キャッシュ」されて再利用されます。

9
Bohemian

これは、文字列リテラルがインターンされているためです。この問題について、 Javaドキュメント は次のように述べています。

すべてのリテラル文字列と文字列値の定数式がインターンされます

そして、これがs1およびs2は同じです(これらの2つの変数は同じインターンされた文字列を指します)

5
GETah

Javaでは、同じ定数文字列が再利用されます。つまり、_s1_と_s2_は、同じ "abc"オブジェクトと_s1==s2_を指します。ただし、new String("abc")を使用すると、別のオブジェクトが作成されます。つまり、_s1 != str1_です。

3
zsxwing

stringはJavaでは不変なので、すべてのstring literals再利用のためにキャッシュされました。

New()演算子を使用してStringオブジェクトを作成すると、常にヒープメモリに新しいオブジェクトが作成されます。一方、文字列リテラル構文を使用してオブジェクトを作成するとします。 「Java」の場合、文字列プールから既存のオブジェクトを返します(Perm genスペースの文字列オブジェクトのキャッシュで、最近のJavaリリースでヒープ領域に移動されました)。それ以外の場合は、新しい文字列オブジェクトを作成し、将来の再利用のために文字列プールに入れます。

String s1 = new String("Java");
String s2 = new String("Java");
String s3 = "Java";
String s4 = "Java";

enter image description here

このリンクを参照してください

2