webentwicklung-frage-antwort-db.com.de

String s = neuer String ("xyz"). Wie viele Objekte wurden nach der Ausführung dieser Codezeile erstellt?

Die allgemein akzeptierte Antwort auf diese Interviewfrage lautet, dass durch den Code zwei Objekte erstellt werden. Aber ich denke nicht so. Ich habe etwas Code zur Bestätigung geschrieben.

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());
    }
}

Die Ausgabe ist:

Application output

Bedeutet dies, dass nur ein Objekt erstellt wurde?

Erneut bestätigen: Meine Frage ist, wie viele Objekte mit folgendem Code erstellt wurden:

String s = new String("xyz")

Anstelle des StringTest-Codes.

Inspiriert von @Don Branson debugierte ich den folgenden Code:

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

Und das Ergebnis ist:

Enter image description here

Die ID von s ist 84 und die ID von "Abc" ist 82. Was genau bedeutet das?

22
smileVann

Es folgen Fehler, die von der verwendeten JVM/JRE abhängen. ES IS BESSER, DASS DIESE AUF KEINEN FALL Sorgen zu machen. SIEHE ANMERKUNGEN ABSCHNITT FÜR KORREKTUREN/KONZERNE.

Zunächst stellt sich diese Frage wirklich zu dem hier behandelten Thema: Ist String Literal Pool eine Sammlung von Verweisen auf das String-Objekt oder eine Sammlung von Objekten

Das ist also ein Leitfaden für alle in dieser Angelegenheit.

...

In dieser Codezeile: String s = new String(“xyz”)

Es gibt zwei Möglichkeiten, dies zu betrachten:

(1) Was passiert, wenn die Codezeile ausgeführt wird - der buchstäbliche Moment, in dem sie im Programm ausgeführt wird?

(2) Was ist der Nettoeffekt daraus, wie viele Objects von der Anweisung erstellt werden?

Antworten:

1) Nach diesem ausgeführt wird ein weiteres Objekt erstellt.

a) Die "xyz"String wird erstellt und interniert, wenn die JVM die class lädt, in der diese Codezeile enthalten ist.

  • Wenn sich "xyz" bereits aus einem anderen Code im internen Pool befindet, erzeugt das Literal möglicherweise kein neues String-Objekt.

b) Wenn ein neuer String s erstellt wird, ist der interne char[] eine Kopie des internen "xyz"-Strings.

c) Das heißt, wenn die Zeile ausführt, wird nur ein zusätzliches Objekt erstellt. 

Tatsache ist, dass das "xyz"-Objekt erstellt wurde, sobald die Klasse geladen wurde und bevor dieser Codeabschnitt ausgeführt wurde.

... nächstes Szenario ...

2) Es gibt drei Objekte, die durch den Code erstellt werden (einschließlich der internierte "a").

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

a) s1 und s2 werden nur referenziert, keine Objekte, und sie zeigen auf dieselbe String im Speicher.

b) Das "a" ist intern und ist ein zusammengesetztes Objekt: ein char[]-Objekt und das String-Objekt selbst. Es besteht aus zwei Objekten im Speicher.

c) s3, new String("a") erzeugt ein weiteres Objekt. Die neue String("a") kopiert nicht den char[] von "a", sondern referenziert ihn nur intern. Hier ist die Methodensignatur:

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

Eine internierte String("a") entspricht 2 Objects. Und ein new String("a") entspricht einem weiteren Objekt. Der Nettoeffekt aus Code besteht aus drei Objekten.

19
The Coordinator

Dafür werden zwei Objekte angelegt:

String s = new String("abc");

Einer im Heap und der andere im "String Constant Pool" (SCP). Die Referenz s zeigt immer auf s, und GC ist im SCP-Bereich nicht zulässig. Daher werden alle Objekte in SCP beim Herunterfahren der JVM automatisch gelöscht.

Zum Beispiel:

Unter Verwendung einer Heap-Objektreferenz erhalten wir die entsprechende SCP-Objektreferenz durch Aufruf von 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
8
user2663609

Es gibt zwei Möglichkeiten, String-Objekte in Java zu erstellen:

  1. Verwenden des neuen Operators, d.h.

    String s1 = new String("abc");
    
  2. Verwenden eines Zeichenkettenliteral, d. H.

    String s2 = "abc";
    

Die Zuweisung von Zeichenfolgen ist sowohl zeit- als auch speicherintensiv, sodass die JVM (Java Virtual Machine) einige Aufgaben ausführt. WELCHE AUFGABEN 

Immer, wenn Sie den Operator new verwenden, wird das Objekt erstellt, und die JVM sucht nicht in den String-Pool. Es wird nur das Objekt erstellt, aber wenn Sie die String-Literale zum Erstellen von String-Objekten verwenden, führt die JVM die Aufgabe aus, im String-Pool zu suchen 

Wenn Sie schreiben

String s2 = "abc";

die JVM sucht in den String-Pool und prüft, ob "abc" bereits existiert oder nicht. Wenn es existiert, wird ein Verweis auf die bereits vorhandene Zeichenfolge "abc" zurückgegeben, und es wird kein neues Objekt erstellt. Wenn es nicht existiert, wird ein Objekt erstellt.

Also in Ihrem Fall (A)

String s1 = new String("abc");
  • Da new verwendet wird, wird das Objekt erstellt

(b)

String s2 = "abc";
  • mit einem String-Literal wird ein Objekt erstellt, und "abc" befindet sich nicht im String-String Daher wird das Objekt erstellt.

(c)

String s2 = "abc";
  • Die Verwendung eines String-Literal und "abc" befindet sich wieder im String-Pool, und Daher wird das Objekt nicht erstellt.

Sie können es auch mit dem folgenden Code auschecken:

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");
    }
}

Ich hoffe, das hilft ... Beachten Sie, dass == verwendet wird, um zu sehen, ob die Objekte gleich sind, und die equals(Object)-Methode verwendet, um zu sehen, ob der Inhalt gleich ist.

4
Musaddique
  1. String s = neuer String ("xyz");

Die obige Zeile erstellt zwei Objekte, eines befindet sich im Heap und eines im String-Konstantenpool.

jetzt, wenn wir das tun

  1. String s = new String("xyz");
  2. String s1 ="xyz";

die obigen beiden Anweisungen erzeugen zwei Objekte. Die erste Zeile String s = new String("xyz"); erstellt zwei Objekte, wie in der ersten Zeile erwähnt, und prüft, wenn String s = "xyz"; Ausgeführt wird, im String-Konstantenpool, ob dasselbe Inhaltsobjekt vorhanden ist oder nicht, seit die erste Zeile erstellt wurde Ein Eintrag im String-Konstantenpool mit "xyz" gibt dieselbe Referenz zurück und erstellt kein anderes Objekt.

Was ist, wenn wir diese vier Zeilen wie unten erwähnt zusammen haben?.

  1. String s2 = new String("xyz");
  2. String s3 ="xyz";
  3. String s4 = new String("xyz");
  4. String s5 ="xyz";

Wenn wir die obige Zeile ausführen, haben wir drei Objekte.

  • Das erste und wie erwähnt wird zwei Objekt eines in Heap und eines in String Constant Poll erstellen.
  • Wenn die zweite Zeile ausgeführt wird, wird der String Constant Poll eingecheckt
    und finde mit "xyz" dasselbe Objekt, also haben wir bis zur zweiten Zeile zwei Objekte.
  • wenn die dritte Zeile ausgeführt wird, wird ein neues Objekt im Heap erstellt, da der Operator new das Objekt im Heap erstellt, bis die dritte Zeile 3 Objekte enthält.
  • Wenn die vierte Zeile ausgeführt wird, wird der String Constant Poll eingecheckt
    und finde mit "xyz" dasselbe Objekt, also haben wir in der vierten Zeile drei Objekte.

Bonus über die intern() Methode

Wenn die Methode intern () für ein String-Objekt aufgerufen wird, wird die in diesem String-Objekt enthaltene Zeichenfolge im Pool angezeigt. Wenn die Zeichenfolge dort gefunden wird, wird die Zeichenfolge aus dem Pool zurückgegeben. Andernfalls wird dieses String-Objekt zum Pool hinzugefügt und ein Verweis auf dieses String-Objekt zurückgegeben.

public class TestString {

    public static void main(String[] args) {
        String s1 = "Test";
        String s2 = "Test";
        String s3 = new String("Test");
        final String s4 = s3.intern();
        System.out.println(s1 == s2);
        System.out.println(s2 == s3);
        System.out.println(s3 == s4);
        System.out.println(s1 == s3);
        System.out.println(s1 == s4);
        System.out.println(s1.equals(s2));
        System.out.println(s2.equals(s3));
        System.out.println(s3.equals(s4));
        System.out.println(s1.equals(s4));
        System.out.println(s1.equals(s3));
    }

}
//Output
true
false
false
false
true
true
true
true
true
true

Sehen Sie die Magie von intern, indem Sie die Methode intern auf ein neues String-Objekt anwenden. intern wird hier angewendet, um zu prüfen, ob "Test" im String-Konstanten-Pool verfügbar ist oder nicht, da "Test" im String-Konstanten-Pool verfügbar ist und dasselbe Objekt zurückgibt, sodass s3 denselben Verweis hat wie s1 Und s2 Und erhalten das gesamte Ergebnis als wahr

public class TestString {

    public static void main(String[] args) {
          String s1 = "Test";
                String s2 = "Test";
                String s3 = new String("Test").intern(); 
                final String s4 = s3.intern();
                System.out.println(s1 == s2);
                System.out.println(s2 == s3);
                System.out.println(s3 == s4);
               System.out.println(s1 == s3);
                System.out.println(s1 == s4);
                System.out.println(s1.equals(s2));
                System.out.println(s2.equals(s3));
                System.out.println(s3.equals(s4));
                System.out.println(s1.equals(s4));
                System.out.println(s1.equals(s3));
    }

}
true
true
true
true
true
true
true
true
true
true
2
Varun

Wenn wir String s = new String("Brajesh"); ausführen, werden zwei Objekte erstellt. Ein Objekt wird im String-Literal-Pool und ein anderes im Heap-Bereich erstellt. Wenn jedoch bereits dasselbe String-Literal-Objekt vorhanden ist, wird nur ein Objekt erstellt 

String s1  ="Brajesh"; 
String s = new String("Brajesh");//it will create only one object in heap area

Abgesehen davon wird im Heap-Bereich ein weiteres Objekt erstellt, bei dem es sich um das Objekt von char [] handelt. Ich habe hier eine Momentaufnahme des Heap-Speichers angehängt  enter image description here

2
Brajesh
public String(String original) {
    int size = original.count;
    char[] originalValue = original.value;
    char[] v;
    if (originalValue.length > size) {
        // The array representing the String is bigger than the new
        // String itself.  Perhaps this constructor is being called
        // in order to trim the baggage, so make a copy of the array.
        int off = original.offset;
        v = Arrays.copyOfRange(originalValue, off, off+size);
    } else {
        // The array representing the String is the same
        // size as the String, so no point in making a copy.
        v = originalValue;
    }
    this.offset = 0;
    this.count = size;
    this.value = v;
}

Wenn wir den Code sehen, können wir sehen, dass er nur ein Zeichen [] erzeugt und jedes Mal kopiert wird, wenn derselbe Inhalt instanziiert wird, und ja, er speichert Daten im String Constant Pool. 1) Nimmt vom SCP String s1 = "a" String s2 = "a"; 2) Erstellt ein neues Objekt String s3 = new String ("a"); Neugier, neues Objekt String s2 = neuer String ("a"); In allen obigen Codes wird das gleiche Zeichen [] kopiert. I: e Zeichen [] Wert Sie können dies hier überprüfen

1
Samrat Roy

Je nachdem, wie intelligent der Compiler ist, werden 2 oder 3 Objekte erstellt.

Trotzdem ist Ihr Test Junk, da hashCode von Strings auf dem Inhalt der String basiert und nicht auf deren Identität. Wenn Sie die Identität prüfen möchten, sollten Sie System.identityHashCode oder nur == Vergleich verwenden.

Der Compiler und die Laufzeitumgebung sind (nicht erzwungen) zulässig, um die Erstellung von Strings zu optimieren, wann immer dies möglich ist. Sie optimieren also Literal-Strings, indem sie für die drei Strings, die Sie haben, ein einzelnes Literal verwenden . Der new-Operator muss ein new -Objekt zurückgeben (dh ein neu zugewiesenes) ..__ Die Stringoptimierung zur Laufzeit ist möglich, wenn stattdessen die statische Methode String.valueOf verwendet wird. Ich weiß jedoch nicht, ob von aktuellen JREs tatsächlich Zwischenspeicherung angewendet wird (möglicherweise ist das Überprüfen einer Hashtabelle teurer als das Zuweisen einer neuen String).

1
Giulio Franco

Wenn new String () zwei Objekte erstellt (eines im Heap und eines im String-Pool), was ist dann die Verwendung der .intern-Methode?

die intern () -Methode, die für ein String-Objekt aufgerufen wird, sucht nach der Zeichenfolge in diesem String-Objekt im Pool enthalten, wenn die Zeichenfolge gefunden wird dort wird dann die Zeichenfolge aus dem Pool zurückgegeben. Ansonsten ist dies Das String-Objekt wird dem Pool hinzugefügt und ein Verweis auf diesen String Objekt wird zurückgegeben.

0
Rahul

Wenn wir den folgenden Code in Eclipse im Debug-Modus ausführen, erhalten wir eine Vorstellung davon, wie viele Objekte mit String string = new String("manoj"); erstellt werden. Intern wird String str = "manoj" Im String-Klassenkonstruktor erstellt. Überprüfen Sie einfach die ID , nachdem Sie mit der Maus über die Referenz gefahren sind (siehe Abbildung unten). ScreenShot

public static void main(String[] args)
{
    String str = "atul";
    String string = new String("manoj");
    String string2 = "manoj";
    System.out.println(str == string);
}
0
atul_java
        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

Wie wir im obigen Programm sehen können, erhalten wir einen ähnlichen Hashcode für s2 bzw. s4, obwohl wir mit dem Operator == false erhalten. == Operator wird für Referenzvergleich verwendet. 

Unter "String s4 = new String (" Mumbai ")" wurden zwei Objekte erstellt, eines im Heap-Speicher und eines im Stack-Speicher. Daher ist s2 vergleichbar mit s4, das im Heap-Speicher erstellt wird, nicht mit dem Stack-Speicher.

0
Kiran Kawade

Java.lang.String überschreibt die hashCode()-Methode, sodass der Wert von content der Zeichenfolge abhängt. 

Daher sagt Ihnen hashCode() nichts über die Anzahl der Instanzen. Es kann sich um dieselbe Zeichenfolge oder um eine andere Instanz handeln, bei der kein einzelnes Byte gemeinsam genutzt wird. Gleiches über equals(). Dies erklärt Ihre Ausgabe.

Verwenden Sie System.identityHashCode (..) für diese Art von Forschung. 

Und möge die Quelle bei dir sein .

0
h22

@ Giulio, du hast recht. String s3 = neuer String ("abc"); Erstellt zwei Objekte, eines im Heap mit der Referenz s3 und eines im SCP (ohne Referenz). und jetzt String s2 = "abc"; erstellt in SCP kein neues Objekt, da "abc" bereits in SCP vorhanden ist.

    String s1 = "abc";
    String s2 = "abc";
    String s3 = new String("abc");
    String s4 = s3.intern();
    System.out.println("s1: "+System.identityHashCode(s1));
    System.out.println("s2: "+System.identityHashCode(s2));
    System.out.println("s3: "+System.identityHashCode(s3));
    System.out.println("s4: "+System.identityHashCode(s4));

O/P: s1: 366712642, s2: 366712642, s3: 1829164700, s4: 366712642

Da ich nicht zum Kommentieren berechtigt bin, habe ich es hier geschrieben.

0
Siddappa Walake

Verwechselt mit dem, was genau passiert, nachdem der neue String ("<>") aufgerufen wurde, habe ich diesen Thread gefunden. Ihr Verständnis für den Vergleich von Hashcodes ist jedoch technisch nicht korrekt.

int hashCode () wurde in der String-Klasse überschrieben und gibt je nach Inhalt des String-Literal einen Wert zurück.

String s1 = neuer String ("Hello"); String s2 = neuer String ("Hello");

Also 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;
}**

Um nur zu erklären, warum dies getan wird, können Sie tatsächlich das Kathy Sierra-Buch lesen, das eine großartige Erklärung dafür liefert, warum Entwickler auf diese Art und Weise vorgegangen sind (im Allgemeinen sollten alle Objekte, die true für die equals () - Methode zurückgeben, denselben Wert für hashCode () zurückgeben).

0
Priyak Dey