Wie kann eine Zeichenfolge mit "" initialisiert werden?

154

Wenn String eine Klasse wie jede andere ist, wie kann sie mit doppelten Anführungszeichen initialisiert werden?

Splitgames
quelle
25
String ist eine VIP-Klasse. " "ist schon ein String!
Johnchen902
2
Keine besondere Bedeutung. Ich meinte nur sehr wichtig. Das heißt, java.lang.Stringhaben Sie eine spezielle Behandlung der Java-Sprache.
Johnchen902
16
Wer sagt, dass String "eine Klasse wie jede andere" ist? Es ist eine ganz besondere Klasse, wie keine andere. Da Ihre Vermutung falsch ist, ist die Frage nicht wirklich beantwortbar.
Eric Lippert
5
Nur weil die Annahme falsch ist, heißt das nicht, dass die Frage nicht beantwortet werden kann. Und die richtige Antwort hat bereits 197 Stimmen.
Koray Tugay

Antworten:

293

Java String ist etwas Besonderes

Die Entwickler von Java beschlossen, primitive Typen in einer objektorientierten Sprache beizubehalten, anstatt alles zu einem Objekt zu machen, um die Leistung der Sprache zu verbessern. Grundelemente werden im Aufrufstapel gespeichert, die weniger Speicherplatz benötigen und billiger zu manipulieren sind. Andererseits werden Objekte im Programmheap gespeichert, was eine komplexe Speicherverwaltung und mehr Speicherplätze erfordert.

Aus Leistungsgründen ist Javas String so konzipiert, dass er zwischen einem Grundelement und einer Klasse liegt.

Beispielsweise

String s1 = "Hello";              // String literal
String s2 = "Hello";              // String literal
String s3 = s1;                   // same reference
String s4 = new String("Hello");  // String object
String s5 = new String("Hello");  // String object

Geben Sie hier die Bildbeschreibung ein

Hinweis: String-Literale werden in einem gemeinsamen Pool gespeichert. Dies erleichtert die gemeinsame Nutzung des Speichers für Zeichenfolgen mit demselben Inhalt, um Speicherplatz zu sparen. StringObjekte, die über einen neuen Operator zugewiesen wurden, werden im gespeichert heap, und es gibt keine gemeinsame Nutzung des Speichers für denselben Inhalt.

Suresh Atta
quelle
72
Beachten Sie, dass der "gemeinsame Pool" normalerweise Teil des Heaps ist.
Joachim Sauer
3
@ JoachimSauer Ja..mit kleinen Vorteilen :) fügte das in Anmerkung hinzu. Danke fürs Erinnern.
Suresh Atta
2
Ist es also schneller, String s1 = "Hello" zu schreiben? als String s2 = neuer String ("Hallo");?
user2097804
28
Ich würde das in Ihrem Beispiel hinzufügen s1 == s2 == s3 aber s4! = S5
Alfredo Osorio
8
@ AndrewJanke auf dem letzten Hotspot JVM (7), der String-Pool ist nicht in Perm Gen und von Java 8 gibt es keine Perm Gen mehr ...
Assylias
50

Java behandelt String als eine spezielle Klasse, die Sie auf beide Arten initialisieren können

  1. Literal direkt zuweisen

    String a = "adsasdf";
  2. Wie andere Objekte mit neuem Schlüsselwort

    String a = new String("adsasdf");

Sie müssen besonders vorsichtig sein, wenn Sie mit ==Zeichen vergleichen möchten:

String a = "asdf";
String b = "asdf";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True

String a = new String("asdf");
String b = new String("asdf");
System.out.println(a == b);  // False
System.out.println(a.equals(b)); // True

Dies liegt daran, dass im ersten Fall die Objekte a und b in einem so genannten literal poolObjekt gehalten werden und beide auf dasselbe Objekt verweisen, sodass sie in beiden Richtungen gleich sind.

Im zweiten Fall verweisen a und b jedoch auf unterschiedliche Objekte, beispielsweise wenn wir andere Objekte initialisieren. Daher sind sie im Vergleich zum ==Operator ungleich , während ihre Werte gleich sind.

Chetan
quelle
18

String wird im JLS besonders behandelt: Es ist einer der beiden nicht-primitiven Typen, für die Literale existieren (der andere ist Class) * .

Aus dem JLS :

Ein String-Literal ist eine Referenz auf eine Instanz der Klasse `String [...].

* Nun, es gibt auch den "Null-Typ" mit dem "Null-Literal" null, aber die meisten Leute halten den "Null-Typ" nicht für einen richtigen Typ.

Joachim Sauer
quelle
1
Mir war auch nicht bewusst, dass "Null-Typ" ein richtiger Typ in Java ist. Es ist eine sehr hilfreiche Information, Sie sollten die Schriftgröße erhöhen.
Grijesh Chauhan
1
@GrijeshChauhan: Nun, der "Null-Typ" ist nur ein geschickter Wortlaut, damit jeder nullbeliebige Referenztyp-Variable zugewiesen werden kann. Sonst ist es kein interessanter Typ.
Joachim Sauer
15

Es ist eine Funktion der Java-Sprache. String-Literale im Quellcode werden besonders behandelt.

Die Sprachspezifikation hier sagt einfach, dass ein String-Literal vom StringTyp ist

nr
quelle
5

Text in doppelten Anführungszeichen erstellt ein Literalobjekt String.

String myString = "Some text";

Der obige Code erstellt ein StringObjekt in doppelten Anführungszeichen.

tristan2468
quelle
4

Zeichenfolgen werden sehr häufig in einer Programmiersprache verwendet. Da Java objektorientiert ist, ist eine Zeichenfolge ein Objekt. Um den umständlichen neuen String ("someString") zu vermeiden; Anweisung Jedes Mal, wenn Sie ein Zeichenfolgenobjekt benötigen, können Sie mit Java nur ein Zeichenfolgenobjekt mithilfe des Zeichenfolgenliteral erstellen.

Sie sollten jedoch die String-Gleichheit berücksichtigen. Hier ein kurzer JUnit-Test, um zu demonstrieren, was ich meine.

    @Test
    public void stringTest() {
       // a string literal and a string object created 
       // with the same literal are equal
       assertEquals("string", new String("string"));

       // two string literals are the same string object
       assertSame("string", "string"); 

       // a string literal is not the same object instance 
       // as a string object created with the same string literal
       assertFalse("string" == new String("string"));

       // java's String.intern() method gives you the same
       // string object reference for all strings that are equal.
       assertSame("string", new String("string").intern());
    }
René Link
quelle
Wenn Sie nur einen String mit initialisieren könnten, könnten new String(String src)Sie dem Konstruktor nicht einmal ein String-Literal geben. Sie müssten a initialisieren char []und dann den String(char [] src)Konstruktor verwenden, um die Zeichenfolge zu erstellen, oder Sie müssten die Zeichenfolge aus einer Datei lesen.
AJMansfield
Das ist nicht richtig. Ein String-Literal ist nur eine Zeichenfolge in einer Quelldatei, die durch doppelte Anführungszeichen gekennzeichnet ist. Java erstellt mit diesem Literal automatisch eine Instanz einer Zeichenfolge. Daher sind ein Literal- und ein String-Objekt gleich, aber sie sind nicht gleich. Java hätte auch so implementiert werden können, dass Sie einen neuen String ("") verwenden müssen. ein String-Objekt zu instanziieren, aber dies würde unser Leben nur schwieriger machen. Wenn Sie also einen neuen String ("einen String") schreiben, erstellt Java ein String-Objekt für das Literal "ein String" und übergibt dieses String-Objekt an den Construtor des neuen Strings.
René Link
2

Nur um es zu erwähnen. Ein String-Literal ist ein Verweis auf eine Instanz der Klasse String. Sie können Code wie folgt schreiben:

 "abc" .getBytes ();

 "a: b: c" .split (":");

 "愛" .codePointAt (0);
mkdev
quelle
2

- String ist eine Klasse in Java . Sie haben Recht damit, sodass wir immer mit dem newSchlüsselwort initialisieren können .

- Aber wenn wir so etwas machen wie:

String s = "";

Die obige Anweisung wird vom Compiler als spezielles String-Objekt markiert, und dann sieht JVM beim Laden der Klasse (das Laden erfolgt vor der Initialisierung) das sogenannte String-Literal , das in einem String-Literal-Pool gespeichert ist .

- Ein String kann also mit new()und mit der ""Methode erstellt werden. Letzterer stellt jedoch ein String-Literal bereit, das auch dann im Heap verbleibt, wenn kein Verweis auf dieses String-Objekt vorhanden ist, da es einen Verweis aus dem String-Literal-Pool enthält.

Kumar Vivek Mitra
quelle
2

Java führt für uns einen zweistufigen Prozess durch.

String str = "hello";

ist äquivalent zu

char data[] = {'h', 'e', 'l' , 'l', 'o'};
String str = new String(data);

Wie [.NET] [1] hat eine ähnliche Sache.

String(Char[]) constructor

tut

String(char[] value)

Hinzufügen von Referenzen: -

user1769790
quelle
2
Der von Ihnen beschriebene Prozess ist nicht das, was Java tatsächlich tut: Wie andere bereits angegeben haben, "hello"handelt es sich um ein Zeichenfolgenliteral, das vom Compiler in den konstanten Pool gestellt wird (siehe JLS §3.10.5 und JVMS §5.1) .
Siegi
1

Java.lang.Stringist nicht nur eine Klasse. Es ist ein wesentlicher Bestandteil der Kernsprache. Der Compiler hat syntaktischen Zucker dafür. Zum Beispiel ""ist wie eine Abkürzung für new String(""). Wenn geschrieben"" optimiert der Compiler identische Zeichenfolgen für dieselbe Instanz, um Platz zu sparen."a" + 5 == "a5" ==> true

Der Compiler verfügt über syntaktischen Zucker für viele Dinge, einschließlich der Tatsache, dass zwischen Objektversionen und ihren nativen Typen kein Box / Unbox erforderlich ist. Kein übergeordnetes Mittel Objekt, Standardkonstruktor, ...

Sylwester
quelle
5
""ist keine Abkürzung für new String(""). Wenn Sie verwenden "", müssen Sie zunächst im String-Pool der JVM nach Übereinstimmungen suchen. Wenn dies zutrifft, wird dieser String zurückgegeben. Mit verwenden new String("")Sie immer einen neuen String, auch wenn der String selbst bereits im String-Pool vorhanden ist (da er nicht im String-Pool gespeichert wird).
g00glen00b
Ich habe meine Antwort aktualisiert. Nutzen die Leute dies zu ihrem Vorteil, wie die Verwendung von String-Konstanten, die dem Lisp-Symboltyp entsprechen?
Sylwester