10

質問はこのコードに要約されます:

// setup
String str1 = "some string";
String str2 = new String(str1);
assert str1.equals(str2);
assert str1 != str2;
String str3 = str2.intern();

// question cases
boolean case1 = str1 == "some string";
boolean case2 = str1 == str3;

Java標準はとの値について何らかの保証を与えますか?もちろん、Java仕様の関連部分へのリンクは素晴らしいでしょう。case1case2

はい、SOが見つけたすべての「類似の質問」を調べましたが、この方法で質問に答えたものは見つからなかったため、重複は見つかりませんでした。equalsいいえ、これは、で置き換えることによって文字列比較を「最適化」するという誤った考えに関するものではありません==

4

2 に答える 2

14

これがあなたのJLS見積もり、セクション3.10.5です:

各文字列リテラルは、クラスString(§4.3.3)のインスタンス(§4.3.1、§12.5)への参照(§4.3)です。文字列オブジェクトには定数値があります。文字列リテラル(または、より一般的には、定数式(§15.28)の値である文字列)は、メソッドString.internを使用して、一意のインスタンスを共有するように「インターン」されます。

したがって、コンパイルユニット(§7.3)で構成されるテストプログラムは次のようになります。

package testPackage;
class Test {
        public static void main(String[] args) {
                String hello = "Hello", lo = "lo";
                System.out.print((hello == "Hello") + " ");
                System.out.print((Other.hello == hello) + " ");
                System.out.print((other.Other.hello == hello) + " ");
                System.out.print((hello == ("Hel"+"lo")) + " ");
                System.out.print((hello == ("Hel"+lo)) + " ");
                System.out.println(hello == ("Hel"+lo).intern());
        }
}

class Other { static String hello = "Hello"; }

およびコンパイルユニット:

package other;

public class Other { static String hello = "Hello"; }

出力を生成します:true true true true false true

この例は、6つのポイントを示しています。

同じパッケージ(§7)内の同じクラス(§8)内のリテラル文字列は、同じ文字列オブジェクト(§4.3.1)への参照を表します。

同じパッケージ内の異なるクラス内のリテラル文字列は、同じStringオブジェクトへの参照を表します。

異なるパッケージの異なるクラス内のリテラル文字列は、同様に同じStringオブジェクトへの参照を表します。

定数式(§15.28)によって計算された文字列は、コンパイル時に計算され、リテラルであるかのように扱われます。

実行時に連結によって計算された文字列は新しく作成されるため、区別されます。計算された文字列を明示的にインターンした結果は、同じ内容の既存のリテラル文字列と同じ文字列になります。

インターン用のJavaDocと組み合わせると、両方のケースがtrueを返すと推測するのに十分な情報が得られます。

于 2013-01-23T07:43:51.103 に答える
6

String.internAPIは十分な情報を提供すると思います

最初は空の文字列のプールは、Stringクラスによってプライベートに維持されます。

インターンメソッドが呼び出されたときに、equals(Object)メソッドによって決定されたこのStringオブジェクトに等しい文字列がプールにすでに含まれている場合、プールからの文字列が返されます。それ以外の場合、このStringオブジェクトはプールに追加され、このStringオブジェクトへの参照が返されます。

したがって、任意の2つの文字列sおよびtについて、s.equals(t)が真である場合に限り、s.intern()== t.intern()が真になります。

すべてのリテラル文字列と文字列値の定数式がインターンされます。文字列リテラルは、Java™言語仕様のセクション3.10.5で定義されています。

于 2013-01-23T07:42:11.670 に答える