88 Stimmen

Java-Zeichenketten: "String s = new String("silly");"

Ich bin ein C++-Typ, der Java lernt. Ich lese gerade Effektives Java und etwas hat mich verwirrt. Da steht, dass man niemals Code wie diesen schreiben soll:

String s = new String("silly");

Weil es unnötig ist String Objekte. Stattdessen sollte es aber so geschrieben werden:

String s = "No longer silly";

So weit, so gut... Aber in Anbetracht dieser 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("Polish");
String s = "polish";
  1. Warum ist die erste Aussage in Ordnung? Müsste es nicht heißen

    CaseInsensitiveString cis = "Polish";

  2. Wie kann ich die CaseInsensitiveString sich verhalten wie String daher ist die obige Aussage in Ordnung (mit und ohne Erweiterung String )? Was hat es mit String auf sich, dass es in Ordnung ist, ihm einfach ein Literal wie dieses zu übergeben? Soweit ich weiß, gibt es in Java kein Konzept des "Kopierkonstruktors"?

115voto

Adam Rosenfield Punkte 373807

String ist eine spezielle eingebaute Klasse der Sprache. Sie ist für die String Klasse nur in denen Sie nicht sagen sollten

String s = new String("Polish");

Weil die wörtliche "Polish" ist bereits vom Typ String und Sie erstellen ein zusätzliches unnötiges Objekt. Für jede andere Klasse kann man sagen

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

ist die richtige (und in diesem Fall einzige) Maßnahme.

58voto

Leigh Punkte 4198

Ich glaube, der Hauptvorteil der Verwendung der Literalform (d.h. "foo" statt new String("foo")) ist, dass alle String-Literale von der VM "interniert" werden. Mit anderen Worten, sie werden zu einem Pool hinzugefügt, so dass jeder andere Code, der dieselbe Zeichenkette erstellt, den gepoolten String verwendet, anstatt eine neue Instanz zu erstellen.

Zur Veranschaulichung: Der folgende Code gibt für die erste Zeile true aus, für die zweite jedoch false:

System.out.println("foo" == "foo");
System.out.println(new String("bar") == new String("bar"));

30voto

Steve B. Punkte 52372

Strings sind ein bisschen speziell in Java behandelt, sie sind unveränderlich, so ist es sicher für sie durch Referenzzählung behandelt werden.

Wenn Sie schreiben

String s = "Polish";
String t = "Polish";

dann beziehen sich s und t tatsächlich auf dasselbe Objekt, und s==t gibt true zurück, denn "==" für Objekte bedeutet "ist dasselbe Objekt" (oder kann es zumindest, ich bin mir nicht sicher, ob dies Teil der eigentlichen Sprachspezifikation oder einfach ein Detail der Compiler-Implementierung ist - vielleicht ist es also nicht sicher, sich darauf zu verlassen).

Wenn Sie schreiben

String s = new String("Polish");
String t = new String("Polish");

dann s!=t (weil Sie explizit eine neue Zeichenfolge erstellt haben), obwohl s.equals(t) true zurückgibt (weil string dieses Verhalten zu equals hinzufügt).

Die Sache, die Sie schreiben wollen,

CaseInsensitiveString cis = "Polish";

kann nicht funktionieren, weil Sie denken, dass die Anführungszeichen eine Art Kurzschluss-Konstruktor für Ihr Objekt sind, während dies in Wirklichkeit nur für einfache alte java.lang.Strings funktioniert.

20voto

Vikas Punkte 460
String s1="foo";

wird buchstäblich in den Pool gehen und s1 wird verweisen.

String s2="foo";

Diesmal wird geprüft, ob das "foo"-Literal bereits im StringPool vorhanden ist oder nicht, da es jetzt existiert, so dass s2 auf dasselbe Literal verweisen wird.

String s3=new String("foo");

"foo" Literal wird in StringPool ersten dann durch String arg Konstruktor String-Objekt wird erstellt werden, dh "foo" in den Heap durch Objekt Erstellung durch neue Operator dann s3 wird es beziehen.

String s4=new String("foo");

wie bei s3

also System.out.println(s1==s2);// **true** due to literal comparison.

y System.out.println(s3==s4);// **false** due to object

Vergleich (s3 und s4 werden an verschiedenen Stellen im Heap angelegt)

12voto

Alnitak Punkte 324207

String s sind in Java etwas Besonderes - sie sind unveränderbar, und String-Konstanten werden automatisch in String Objekte.

Es gibt keine Möglichkeit für Ihre SomeStringClass cis = "value" Beispiel auf jede andere Klasse anwenden.

Sie können auch nicht die String weil es als final was bedeutet, dass keine Unterklassenbildung erlaubt ist.

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