88 Stimmen

Java-Zeichenfolgen: "String s = new String("albern");"

Ich bin ein C++-Typ, der Java lernt. Ich lese Effective Java und etwas hat mich verwirrt. Es sagt, man solle niemals Code wie diesen schreiben:

String s = new String("silly");

Da es unnötige String-Objekte erstellt. Stattdessen sollte es so geschrieben werden:

String s = "Nicht mehr albern";

Ok bis hierher ... Aber, gegeben diese Klasse:

public final class CaseInsensitiveString {
    private String s;
    public CaseInsensitiveString(String s) {
        if (s == null) {
            throw new NullPointerException();
        }
        this.s = s;
    }
    :
    :
}

CaseInsensitiveString cis = new CaseInsensitiveString("Polnisch");
String s = "polnisch";
  1. Warum ist die erste Aussage in Ordnung? Sollte es nicht sein

    CaseInsensitiveString cis = "Polnisch";

  2. Wie mache ich CaseInsensitiveString so, dass es sich wie String verhält, damit die obige Aussage in Ordnung ist (mit und ohne Erweiterung von String)? Was macht String zu etwas, das es erlaubt, einfach einen Literal zu übergeben? Nach meinem Verständnis gibt es kein Konzept des "Kopierkonstruktors" in Java?

2 Stimmen

String str1 = "foo"; String str2 = "foo"; Beide str1 und str2 gehören zum selben String-Objekt, "foo", da Java Strings im StringPool verwaltet, sodass eine neue Variable auf denselben String verweist und nicht einen anderen erstellt, sondern den bereits im StringPool vorhandenen zuweist. Aber wenn wir dies tun: String str1 = new String("foo"); String str2 = new String("foo"); Hier gehören sowohl str1 als auch str2 zu verschiedenen Objekten, da new String() zwangsläufig ein neues String-Objekt erstellt.

3voto

fastcodejava Punkte 37539

CaseInsensitiveString ist kein String, obwohl es einen String enthält. Ein String literal, z.B. "Beispiel", kann nur einem String zugewiesen werden.

2voto

javaguy Punkte 4206

Nur weil du das Wort String in deiner Klasse hast, bedeutet das nicht, dass du alle speziellen Funktionen der integrierten String-Klasse bekommst.

2voto

Wenn sie sagen, dass du schreiben sollst

String s = "Spinnert";

anstelle von

String s = new String("Spinnert");

dann meinen sie das beim Erstellen eines String-Objekts, da beide der obigen Aussagen ein String-Objekt erstellen, aber die new String() Version zwei String-Objekte erstellt: eins im Heap und das andere im String-Konstanten-Pool. Daher wird mehr Speicher verwendet.

Aber wenn du schreibst

CaseInsensitiveString cis = new CaseInsensitiveString("Polieren");

dann erstellst du keinen String, stattdessen erstellst du ein Objekt der Klasse CaseInsensitiveString. Daher musst du den new-Operator verwenden.

2voto

Herms Punkte 35605

CaseInsensitiveString und String sind verschiedene Objekte. Du kannst nicht machen:

CaseInsensitiveString cis = "Polish";

weil "Polish" ein String ist, kein CaseInsensitiveString. Wenn String CaseInsensitiveString erweitern würde, wäre das in Ordnung, aber offensichtlich tut er das nicht.

Und mach dir keine Sorgen über die Konstruktion hier, du wirst keine unnötigen Objekte erstellen. Wenn du den Code des Konstruktors anschaust, speichert er nur eine Referenz auf den übergebenen String. Es wird nichts zusätzliches erstellt.

In dem Fall String s = new String("foobar") passiert etwas anderes. Zuerst erstellst du den Literalstring "foobar" und erstellst dann eine Kopie davon, indem du einen neuen String daraus konstruierst. Es ist nicht notwendig, diese Kopie zu erstellen.

0 Stimmen

Selbst wenn Sie String erweitert haben, würde dies nicht funktionieren. Sie müssten String erweitern, um CaseInsensitiveString zu erweitern.

0 Stimmen

In beiden Fällen ist es unmöglich, entweder weil der String bereits vorhanden ist oder weil er als final deklariert wurde.

1voto

dharam Punkte 7584

Wenn ich es richtig verstanden habe, bedeutet deine Frage, warum wir ein Objekt nicht direkt durch Zuweisen eines Wertes erstellen können, lassen wir es nicht auf eine Wrapper-Klasse für die String-Klasse in Java beschränken.

Um das zu beantworten, würde ich einfach sagen, dass reine objektorientierte Programmiersprachen einige Konstrukte haben und es besagt, dass alle Literale, wenn sie alleine geschrieben werden, direkt in ein Objekt des angegebenen Typs umgewandelt werden können.

Das bedeutet genau, dass, wenn der Interpreter die 3 sieht, wird sie in ein Integer-Objekt umgewandelt, weil Integer der für solche Literale definierte Typ ist.

Wenn der Interpreter etwas in einfachen Anführungszeichen wie 'a' sieht, wird direkt ein Objekt vom Typ Zeichen erstellt, ohne dass Sie es angeben müssen, da die Sprache das Standardobjekt vom Typ Zeichen definiert.

Ebenso wird, wenn der Interpreter etwas in "" sieht, dies als Objekt seines Standardtyps, d.h. String, betrachtet. Dies ist etwas nativer Code, der im Hintergrund arbeitet.

Dank des MIT-Videovorlesungskurses 6.00, wo ich den Hinweis für diese Antwort erhalten habe.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X