-2

文字列は2つの方法で初期化できます。

String s="ABCD";

また

String s=new String("ABCD");

これら2つは同じですか、それとも異なりますか?再び私はそれに気づきました

String s="ABCD";
String z="ABCD";
boolean b=s.equals(z);

結果は本当ですが

String s=new String("ABCD");
String z=new String("ABCD");
boolean b=s.equals(z);

結果はfalseになります。なぜこれが起こるのか誰かが私に説明できますか?

4

6 に答える 6

10

あなたのすべての例は、2番目のものtrueも含めて結果でなければなりません

なんで?このクラスには、 2つの文字列が同じであるかどうかを文字ごとにチェックStringするオーバーライドされたメソッドがあります。equals一方、Operator ==は、2つの文字列参照が同じオブジェクトを指しているかどうかをチェックします。

したがって、たとえば:

String a = new String("asd"); //new object, will add to pool though
String b = new String("asd"); //new object
String c = "asd"; //will use the pool
boolean b1 = (a == b); //false, different objects (same contents though)
boolean b2 = (a.equals(b)); //true, same contents
boolean b3 = (a == c); //false, different objects
boolean b3 = (a.equals(c)); //true, same contents

注目すべき点は、Javaが文字列をプールすることです。コード内のどこかで文字列リテラルを使用すると、JVMはその値をプールし、コード内の別の場所で再び使用すると、JVMはそれを検出し、参照をポイントします。文字列は不変なので、これは完全に安全です。

最後に強調したいのは構成String b = new String("asd");です。この場合、新しいStringオブジェクトが作成されます(演算子のためnew)。「asd」が文字列プールにすでに存在する場合でも、文字列bは新しいオブジェクトを使用して別のメモリ位置を指します。

「asd」がプールに存在しなかった場合、プールされていないb領域を指すだけでなく、万が一の場合に備えて「asd」もプールに追加されます(将来の参照用)。

于 2012-09-22T06:16:45.543 に答える
0

申し訳ありませんが、私は思います。

String s=new String("ABCD");
String z=new String("ABCD");
boolean b=s.equals(z);

真に戻るはずです。もう一度確認してください。

あなたの質問はさまざまな側面で正しいです(==演算子を使用)JavaでStringオブジェクトを作成する方法は2つあります。

  • new演算子を使用します。例えば、

    String str = new String("Hello");

  • 文字列リテラルまたは定数式を使用)。例えば、

    String str="Hello"; (string literal) or
    String str="Hel" + "lo"; (string constant expression).

文字列リテラル
文字列の割り当ては、すべてのオブジェクトの割り当てと同様に、時間とメモリの両方でコストがかかることがわかります。JVMは、文字列リテラルをインスタンス化するときにいくつかのトリックを実行して、パフォーマンスを向上させ、メモリのオーバーヘッドを削減します。JVMで作成されるStringオブジェクトの数を減らすために、Stringクラスは文字列のプールを保持します。コードが文字列リテラルを作成するたびに、JVMは最初に文字列リテラルプールをチェックします。文字列がすでにプールに存在する場合、プールされたインスタンスへの参照が返されます。文字列がプールに存在しない場合、新しいStringオブジェクトがインスタンス化され、プールに配置されます。文字列は不変であり、データの破損を恐れずに共有できるため、Javaはこの最適化を行うことができます。

だからあなたの質問から

String s="ABCD";
String z="ABCD";
boolean b=s==z; 

true両方のオブジェクトが同じ参照を持っているので、戻る必要があります。

しかしの場合

String s=new String("ABCD");
String z=new String("ABCD");
boolean b = s==z;

false両方のオブジェクトが異なるため、戻ります

于 2012-09-22T06:25:12.680 に答える
0

String.classのソースコード、特にequalsおよびinternメソッドを読んで分析する必要があり、さらにjavaのメモリ構造を調査する必要があることをお勧めします。

String#equals

/**
 * Compares this string to the specified object.  The result is {@code
 * true} if and only if the argument is not {@code null} and is a {@code
 * String} object that represents the same sequence of characters as this
 * object.
 *
 * @param  anObject
 *         The object to compare this {@code String} against
 *
 * @return  {@code true} if the given object represents a {@code String}
 *          equivalent to this string, {@code false} otherwise
 *
 * @see  #compareTo(String)
 * @see  #equalsIgnoreCase(String)
 */
public boolean equals(Object anObject) {
if (this == anObject) {
    return true;
}
if (anObject instanceof String) {
    String anotherString = (String)anObject;
    int n = count;
    if (n == anotherString.count) {
    char v1[] = value;
    char v2[] = anotherString.value;
    int i = offset;
    int j = anotherString.offset;
    while (n-- != 0) {
        if (v1[i++] != v2[j++])
        return false;
    }
    return true;
    }
}
return false;
}

String#intern

/**
 * Returns a canonical representation for the string object.
 * <p>
 * A pool of strings, initially empty, is maintained privately by the
 * class <code>String</code>.
 * <p>
 * When the intern method is invoked, if the pool already contains a
 * string equal to this <code>String</code> object as determined by
 * the {@link #equals(Object)} method, then the string from the pool is
 * returned. Otherwise, this <code>String</code> object is added to the
 * pool and a reference to this <code>String</code> object is returned.
 * <p>
 * It follows that for any two strings <code>s</code> and <code>t</code>,
 * <code>s.intern()&nbsp;==&nbsp;t.intern()</code> is <code>true</code>
 * if and only if <code>s.equals(t)</code> is <code>true</code>.
 * <p>
 * All literal strings and string-valued constant expressions are
 * interned. String literals are defined in &sect;3.10.5 of the
 * <a href="http://java.sun.com/docs/books/jls/html/">Java Language
 * Specification</a>
 *
 * @return  a string that has the same contents as this string, but is
 *          guaranteed to be from a pool of unique strings.
 */
public native String intern();

メモリ構造

http://www.yourkit.com/docs/kb/sizes.jsp

于 2012-09-22T06:48:31.043 に答える
-1

以下のステートメントを呼び出すとき

String s="ABCD";
String z="ABCD";

次に、文字列プールでチェックされ、プールにすでに存在する場合は、アドレスが変数を参照します。
しかし、newキーワードを呼び出すと、新しいメモリを作成するように明示的に言います。

于 2012-09-22T06:12:08.767 に答える
-3

これについてはよくわかりませんが、2番目の例で突っ込みます

String s=new String("ABCD");
String z=new String("ABCD");

それはオブジェクトのように宣言されているので、同等性をチェックしようとすると、必ずuが得られfalseます(オブジェクトはオブジェクトと等しくなりません)

于 2012-09-22T06:14:10.037 に答える
-4
String s="ABCD";
String z="ABCD";

メモリプール内の同じ文字列を参照してください。しかし

String s=new String("ABCD");
String z=new String("ABCD");

文字列用に個別のメモリスペースを生成します。したがって、出力はそのようなものです。これはあなたの最初の質問にも答えます。

于 2012-09-22T06:08:10.030 に答える