29

このインタビューの質問に対する一般的な回答は、コードによって 2 つのオブジェクトが作成されるというものです。しかし、私はそうは思いません。確認のためにいくつかのコードを書きました。

public class StringTest {
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = "a";
        String s3 = new String("a");
        System.out.println("s1: "+s1.hashCode());
        System.out.println("s2: "+s2.hashCode());
        System.out.println("s3: "+s3.hashCode());
    }
}

出力は次のとおりです。

アプリケーション出力

これは、オブジェクトが 1 つだけ作成されたということですか?

再確認: 私の質問は、次のコードによって作成されたオブジェクトの数です。

String s = new String("xyz")

StringTestコードの代わりに。

@Don Branson に触発されて、以下のコードをデバッグしました。

public class test {
    public static void main(String[] args) {
        String s = new String("abc");
    }
}

結果は次のとおりです。

ここに画像の説明を入力してください

s の ID は 84 で、"abc" の ID は 82 です。これはどういう意味ですか?

4

21 に答える 21

24

使用する JVM/JRE によっては、以下のエラーがあります。とにかく、このようなことについて心配しない方が良いです. 訂正/懸念事項については、コメントセクションを参照してください。

まず、この質問は実際にここで対処することについて尋ねます: Is String Literal Pool a collection of references to the String Object, Or a collection of Objects

それで、それはこの問題に関するすべての人のためのガイドです.

...

このコード行を考えると:String s = new String(“xyz”)

これには、次の 2 つの方法があります。

(1) コード行が実行されると何が起こるか? プログラム内でコードが実行される文字通りの瞬間?

Objects(2)ステートメントによって作成された数の正味の効果は何ですか?

答え:

1) これが実行された後、1 つの追加オブジェクトが作成されます。

a) "xyz" StringJVM がclassこのコード行が含まれている をロードすると、 が作成され、インターンされます。

  • "xyz"が他のコードから既にインターン プールにある場合、リテラルは新しいオブジェクトを生成しない可能性がありますString

b) newString sが作成されると、internalはインターンされた文字列char[]のコピーです。"xyz"

c) つまり、行が実行されると、追加のオブジェクトが 1 つだけ作成されます。

実際には"xyz"、クラスがロードされるとすぐに、このコード セクションが実行される前にオブジェクトが作成されます。

...次のシナリオ...

2)コードによって作成された3つのオブジェクトがあります(インターンを含む"a"

String s1 = "a";
String s2 = "a";
String s3 = new String("a");

Stringa) s1 と s2 は参照されているだけで、オブジェクトではなく、メモリ内で同じものを指しています。

b)「a」はインターンされ、複合オブジェクトです。1つchar[]のオブジェクトとStringオブジェクト自体です。メモリ内の 2 つのオブジェクトで構成されます。

c) s3、new String("a")もう 1 つのオブジェクトを生成します。newは "a"String("a")の をコピーせず、char[]内部で参照するだけです。メソッドのシグネチャは次のとおりです。

public String2(String original) {
        this.value = original.value;
        this.hash = original.hash;
}

1人のインターンString ("a")は2人に等しいObjects。そして、1new String("a")はもう 1 つのオブジェクトに相当します。コードの正味の効果は 3 つのオブジェクトです。

于 2013-10-30T02:06:53.317 に答える
8

このために 2 つのオブジェクトが作成されます。

String s = new String("abc");

1 つはヒープにあり、もう 1 つは「文字列定数プール」(SCP) にあります。参照sは常に指し示しs、SCP 領域では GC が許可されていないため、SCP 上のすべてのオブジェクトは JVM のシャットダウン時に自動的に破棄されます。

例えば:

ここでは、ヒープ オブジェクト参照を使用して、対応する SCP オブジェクト参照を intern() の呼び出しによって取得しています。

String s1 = new String("abc");
String s2 = s1.intern(); // SCP object reference
System.out.println(s1==s2); // false
String s3 = "abc";
System.out.println(s2==s3); //True s3 reference to SCP object here
于 2014-12-08T15:22:04.893 に答える
3

Java で文字列オブジェクトを作成するには、次の 2 つの方法があります。

  1. new 演算子を使用する、つまり

    String s1 = new String("abc");
    
  2. 文字列リテラルの使用、つまり

    String s2 = "abc";
    

現在、文字列の割り当ては時間とメモリの両方でコストがかかるため、JVM (Java 仮想マシン) がいくつかのタスクを実行します。どんなタスク?

演算子を使用しているときはいつでもnewオブジェクトが作成され、JVM は文字列プールを検索しません。オブジェクトを作成するだけですが、文字列オブジェクトを作成するために文字列リテラルを使用している場合、JVM は文字列プールを検索するタスクを実行します。

つまり、あなたが書くとき

String s2 = "abc";

JVM は文字列プールを調べて、「abc」が既に存在するかどうかを確認します。存在する場合は、既存の文字列「abc」への参照が返され、新しいオブジェクトは作成されず、存在しない場合はオブジェクトが作成されます。

だからあなたの場合(a)

String s1 = new String("abc");
  • が使用されているためnew、オブジェクトが作成されます

(ロ)

String s2 = "abc";
  • 文字列リテラルを使用してオブジェクトが作成され、「abc」が文字列プールにないため、オブジェクトが作成されます。

(c)

String s2 = "abc";
  • 再び文字列リテラルを使用すると、「abc」は文字列プールにあるため、オブジェクトは作成されません。

次のコードを使用して確認することもできます。

class String_Check
{
    public static void main(String[] n)
    {
        String s1 = new String("abc");
        String s2 = "abc";
        String s3 = "abc";
        if (s1==s2)
            System.out.println("s1==s2");
        if(s1==s3)
            System.out.println("s1==s3");
        if(s2==s3)
            System.out.println("s2==s3");
    }
}

これが役立つことを願っています...==オブジェクトが等しいかどうかを確認するためequals(Object)に使用され、コンテンツが等しいかどうかを確認するためにメソッドが使用されることに注意してください。

于 2015-04-16T12:33:13.013 に答える
1

コンパイラの能力に応じて、2 つまたは 3 つのオブジェクトが作成されます。

それにもかかわらず、あなたのテストはがらくたhashCodeです。同一性を確認したい場合は、または単に比較を使用する必要があります。StringStringSystem.identityHashCode==

コンパイラとランタイムは、可能な限り文字列の作成を最適化できます (強制ではありません)。そのため、3 つの文字列に対して 1 つのリテラルを使用して、リテラル文字列を最適化します。とにかく、newオペレーターは新しいオブジェクト (つまり、新しく割り当てられたオブジェクト)を返さなければなりません。代わりに静的メソッドを使用すると、実行時の文字列の最適化が可能です。しかし、キャッシングが現在の JRE によって実際に適用されているかどうかはわかりません (単に新しい を割り当てるよりも、ハッシュ テーブルをチェックする方がコストがかかるかもしれません) 。String.valueOfString

于 2013-10-30T01:58:25.747 に答える
1
        String s1="Pune";
        String s2="Mumbai";
        String s3="Pune";
        String s4=new String("Mumbai");
        System.out.println("S1 :"+s1.hashCode());  //S1 :2499228
        System.out.println("S2 :"+s2.hashCode());  //S2 :-1979126203
        System.out.println("S3 :"+s3.hashCode());  //S3 :2499228
        System.out.println("S4 :"+s4.hashCode());  //S4 :-1979126203
        System.out.println(s2==s4);     // false

上記のプログラムでわかるように、s2 と s4 についてそれぞれ同様のハッシュコードを取得していますが、== 演算子を使用して false を取得しています。== 演算子は参照比較に使用されます。

「String s4=new String("Mumbai")」で 2 つのオブジェクトが作成されました。1 つはヒープ メモリに、もう 1 つはスタック メモリにあります。したがって、s2 は、スタック メモリではなく、ヒープ メモリに作成された s4 と比較されます。

于 2016-10-18T15:12:49.263 に答える
0

new String("<>") が呼び出された後に正確に何が起こるか混乱して、このスレッドを見つけました。ただし、ハッシュコード比較の理解は技術的に正しくありません。

int hashCode() は String クラスでオーバーライドされており、String リテラルの内容に応じて値を返します。

String s1 = new String("こんにちは"); String s2 = new String("Hello");

したがって、s1.hashCode() = s2.hashCode() = anyStringOfContent_"Hello".hashCode()

**/** Cache the hash code for the string */
private int hash; // Default to 0
public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;
        for (int i = 0; i < value.length; i++) {
            **h = 31 * h + val[i];**
        }
        hash = h;
    }
    return h;
}**

なぜこれが行われるのかを説明するために、実際に Kathy Sierra の本を読むことができます。この本には、開発者がこの方法で行った理由がよく説明されています (基本的に、equals() メソッドに true を返すすべてのオブジェクトは同じ hashCode() 値を返す必要があります)。

于 2018-11-15T21:24:59.940 に答える
0

以下のコードを Eclipse のデバッグ モードで実行すると、String クラス コンストラクターでString string = new String("manoj");作成される Internally で作成されるオブジェクトの数がわかります。以下のスクリーンショットに示すように、参照にカーソルを合わせた後、 IDString str = "manoj"を確認してください。スクリーンショット

public static void main(String[] args)
{
    String str = "atul";
    String string = new String("manoj");
    String string2 = "manoj";
    System.out.println(str == string);
}
于 2018-09-18T12:56:17.643 に答える
-1

Eclipseデバッガーで実行しました。そのコンテキストでは、2 つのオブジェクトが作成されます。1 つは ID 17 で、もう 1 つは 22 です。

ここに画像の説明を入力

于 2013-10-30T01:59:28.620 に答える
-3

メソッドを使用して、hashcode()作成された文字列オブジェクトの数を見つけました。このhashcode()メソッドは、参照変数に格納されたデータを 1 つのハッシュ値にダイジェストします。

ケース1:

String s="

Fred";
System.out.println(s.hashCode());

s=s+"47";
System.out.println(s.hashCode());

s=s.substring(2,5);
System.out.println(s.hashCode());

s=s.toUpperCase();
System.out.println(s.hashCode());

s=s.toString();
System.out.println(s.hashCode());

出力は次のとおりです。

Fred--2198155         //1st object ----------------  String s="Fred"

Fred47--2112428622    //2nd object ----------------  s=s+"47"

ed4--100213           //3rd object ----------------  s=s.substring(2,5)

ED4--68469            //4th object ----------------  s=s.toUpperCase()

ED4--68469            //this is retrieved from the string constant pool -------- s=s.toString();

したがって、合計で 4 つのオブジェクトが作成されます。

ケース 2:

String s="FRED";
System.out.println(s.hashCode());

s=s+"47";
System.out.println(s.hashCode());

s=s.substring(2,5);
System.out.println(s.hashCode());

s=s.toUpperCase();
System.out.println(s.hashCode());

s=s.toString();
System.out.println(s.hashCode());

出力は次のとおりです。

FRED--2166379       //1st object ----------------  String s="Fred" 

FRED47--2081891886  //2nd object ----------------  s=s+"47"

ED4--68469          //3rd object ----------------  s=s.substring(2,5)

ED4--68469          //this is retrieved from the string constant pool -------  s=s.toUpperCase()

ED4--68469          //this is retrieved from the string constant pool -------- s=s.toString() 

合計 3 つのオブジェクトが作成されました。

于 2015-11-20T13:08:15.340 に答える
-3

すべてのハッシュ コードが同じだからといって、同じオブジェクトを見ているとは限りません。2 つのオブジェクトが作成されます。これを分解しましょう。

String s = new String(“xyz”);

「new String("xyz")」の部分では、新しい文字列「xyz」にアドレスが返されます。「 String s = 」と言うと、返されたアドレスがこのオブジェクトに割り当てられるため、それらは同じ場所を指しますが、新しい string と string は 2 つの別個のオブジェクトです。

于 2013-10-30T02:01:43.507 に答える