2

Java 7 と C#(.net 3.5) で同じ (..similar?) コードを書いたところ、紛らわしい出力が得られました。この動作を理解するのを手伝ってください:

ジャワ:

public class strTest {
    public static void main(String [] s) {      
        String s1 = "abc";
        String s2 = new String(new char[] {'a', 'b', 'c'});
        System.out.println(s1 == s2);                      // false
        System.out.println(((Object)s1) == ((Object)s2));  // false
        System.out.println(s1.equals(s2));                 // true
    }
}

出力: false false true

C#:

namespace ConsoleApplication1
{
    class Program2
    {
        static void Main(string[] args)
        {
            String s1 = "abc";
            String s2 = new String(new Char[] {'a', 'b', 'c'});
            Console.WriteLine(s1 == s2);                     // true
            Console.WriteLine(((Object)s1) == ((Object)s2)); // false
            Console.WriteLine(s1.Equals(s2));                // true
        }
    }
}

出力:真偽真

文字列の不変性や文字列プールなどの概念は認識していますが、細かい部分が欠けていると思います。

Java: s1 によって参照されるものを使用できたのに、なぜ s2 の新しい String オブジェクトを作成したのですか? それは String プールが達成すべきことではありませんか?

4

4 に答える 4

15

あなたの質問には2つの側面があります.オブジェクトがいつ作成されるか、そして==比較がどのように機能するかです:

オブジェクトの作成

インターン (「プーリング」) に関しては、定数のみが自動的にインターンされます。Intern/を使用して他の文字列をインターンできますが、常に新しい文字列を作成するintern文字列コンストラクターを呼び出すだけです。(まあ、.NET での 1 つの奇妙なコーナー ケースを除いては、今のところ無視できます。)

したがって、コードではs1s2常に異なるオブジェクトを参照してください。

比較

違いの原因は、 の使用です==。C# はユーザー定義の演算子のオーバーロードをサポートし、次のStringようにオーバーロードします。

public static bool operator ==(string x, string y)

参照ではなく文字列の内容を比較します。stringしたがって、 typeのオペランドが 2 つあるx == y場合、 は恒等比較ではなく等値比較を行うことになります。そのため、C# 出力の最初の行はTrue.

Javaにはこの動作がありませんfalse

オペランドの型が の場合Object、C# と Java の両方で参照の等価性が使用されます。そのため、どちらの場合も 2 行目が false になります。

于 2012-06-21T07:22:01.293 に答える
2

C# が s1==s2 と言う理由を尋ねていると思いますか? 文字列比較では、大文字と小文字を区別して 2 つの文字列の内容が比較されます。両方の文字列の内容が同じであるため、それらの比較は true を返します。

Java では、2 つの変数が同じ文字列を参照しているかどうかを判断するために、文字列参照のみが比較されます。それらの内容は比較されません。

プーリングに関しては、Java と C# の両方がリテラルに対してプーリング (C# ではインターン) を使用します。プログラムで作成された文字列は、プールされたインスタンスが既に存在する場合でも、両方の言語で新しいインスタンスになります。値が同じであっても、インターンされた文字列が生成された文字列とは異なるインスタンスである、あなたのような例については、 String.Internのドキュメントを確認してください。

于 2012-06-21T07:22:25.670 に答える
1

文字列プーリングは、リテラルでのみ使用されます。String s1 = "abc"; と言う場合 文字列 s2 = "abc"; オブジェクトが 1 つだけ作成されます。

于 2012-06-21T07:23:59.483 に答える
0

Java 言語仕様では、'new' キーワードを使用すると、実際の新しいオブジェクトが作成され、チートや内部キャッシュ コピーが返されないことが要求されます。

クラス インスタンス作成式 (§15.9) の評価によってクラスがインスタンス化されると、新しいクラス インスタンスが明示的に作成されます。

インターンはリテラルとして表現された文字列に適用されますが、新しいキーワードを明示的に使用すると、言語は実際に新しい別のオブジェクトを作成する必要があります。

于 2012-06-21T07:25:55.240 に答える