Java-Strings: "String s = neuer String (" albern ");"

85

Ich bin ein C ++ - Typ, der Java lernt. Ich lese Effective Java und etwas hat mich verwirrt. Es heißt, niemals Code wie diesen zu schreiben:

String s = new String("silly");

Weil es unnötige StringObjekte schafft . Aber stattdessen sollte es so geschrieben werden:

String s = "No longer silly";

Ok, gut, soweit ... Angesichts 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? Sollte es nicht sein

    CaseInsensitiveString cis = "Polish";

  2. Wie kann ich mich so CaseInsensitiveStringverhalten, Stringdass die obige Aussage in Ordnung ist (mit und ohne Erweiterung String)? Was ist es an String, das es in Ordnung macht, es einfach so wörtlich zu übergeben? Nach meinem Verständnis gibt es in Java kein "Kopierkonstruktor" -Konzept?

JavaNewbie
quelle
2
String str1 = "foo"; String str2 = "foo"; Sowohl str1 als auch str2 gehören zu demselben String-Objekt, "foo". B'coz für Java verwaltet Strings in StringPool. Wenn also eine neue Variable auf denselben String verweist, wird kein anderer erstellt, sondern dieselbe vorhandene Alerady zugewiesen StringPool. Aber wenn wir das tun: String str1 = neuer String ("foo"); String str2 = neuer String ("foo"); Hier gehören sowohl str1 als auch str2 zu verschiedenen Objekten. B'coz new String () erstellt zwangsweise ein neues String-Objekt.
Akash5288

Antworten:

110

Stringist eine spezielle integrierte Klasse der Sprache. Es ist nur für die StringKlasse , in der Sie vermeiden sollten, zu sagen

String s = new String("Polish");

Weil das Literal "Polish"bereits vom Typ Stringist und Sie ein zusätzliches unnötiges Objekt erstellen. Für jede andere Klasse sagen

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

ist das Richtige (und in diesem Fall nur).

Adam Rosenfield
quelle
8
Ein zweiter Punkt ist, dass der Compiler sich vorstellen kann, internig / propagating-Zeug mit String-Literalen zu erstellen, die mit einem so seltsamen Funktionsaufruf wie "String (Literal)" nicht unbedingt möglich sind
Tetha
4
Da Sie niemals aufrufen sollten new String("foo"), fragen Sie sich möglicherweise, warum der Konstruktor new String(String)vorhanden ist. Die Antwort ist, dass es manchmal eine gute Verwendung dafür gibt: stackoverflow.com/a/390854/1442870
Enwired
Zu Ihrer Information, Tethas Kommentar oben hat das Wort "interning" falsch geschrieben, wie beim String interning .
Basil Bourque
56

Ich glaube, der Hauptvorteil der Verwendung der Literalform (dh "foo" anstelle des neuen Strings ("foo")) besteht darin, dass alle String-Literale von der VM "interniert" werden. Mit anderen Worten, es wird einem Pool hinzugefügt, sodass jeder andere Code, der dieselbe Zeichenfolge erstellt, die gepoolte Zeichenfolge verwendet, anstatt eine neue Instanz zu erstellen.

Zur Veranschaulichung wird der folgende Code für die erste Zeile wahr, für die zweite falsch ausgegeben:

System.out.println("foo" == "foo");
System.out.println(new String("bar") == new String("bar"));
Leigh
quelle
14
In ähnlicher Weise fordert FindBugs Sie daher auf, "new Integer (N)" durch "Integer.valueOf (N)" zu ersetzen - aus diesem Grund.
Paul Tomblin
6
Sie sollten auch "foo" == new String ("foo") hinzufügen. Intern ()
James Schek
4
Eine Korrektur: String-Literale verweisen vom Compiler auf dieselbe Referenz, nicht von der VM. Die VM kann zur Laufzeit String-Objekte internieren, sodass die zweite Zeile möglicherweise true oder false zurückgibt!
Craig P. Motlin
1
@ Motlin: Ich bin nicht sicher, ob das richtig ist. Das Javadoc für die String-Klasse schreibt vor, dass "alle Literal-Strings und konstanten Ausdrücke mit String-Wert interniert werden". Wir können uns also darauf verlassen, dass Literale interniert werden, was bedeutet, dass "foo" == "foo" immer true zurückgeben sollte.
Leigh
3
@Leigh Ja, Literale werden interniert, aber vom Compiler und nicht von der VM. Was Motlin vorhat, ist, dass die VM zusätzlich Zeichenfolgen internieren kann. Ob neue Zeichenfolge ("bar") == neue Zeichenfolge ("bar") -> false ist, hängt von der Implementierung ab.
Aaron Maenpaa
30

Strings werden in Java etwas speziell behandelt, sie sind unveränderlich, so dass sie sicher durch Referenzzählung behandelt werden können.

Wenn du schreibst

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 gelesene Objekte "ist dasselbe Objekt" (oder kann jedenfalls nicht sicher sein, ob dies Teil davon ist die tatsächliche Sprachspezifikation oder einfach ein Detail der Compiler-Implementierung - daher ist es möglicherweise nicht sicher, sich darauf zu verlassen).

Wenn du schreibst

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).

Das, was du schreiben willst,

CaseInsensitiveString cis = "Polish";

kann nicht funktionieren, weil Sie denken, dass die Zitate eine Art Kurzschlusskonstruktor für Ihr Objekt sind, obwohl dies tatsächlich nur für einfache alte java.lang.Strings funktioniert.

Steve B.
quelle
+1 für die Erwähnung der Unveränderlichkeit, was für mich der wahre Grund in Java ist, schreibt strA = strBman statt strA = new String(strB). Es hat wirklich nicht viel mit String-Internierung zu tun.
kritzikratzi
Sie werden nicht durch Referenzzählung behandelt. String Pooling wird vom JLS benötigt.
Marquis von Lorne
20
String s1="foo";

Literal wird in Pool gehen und S1 wird verweisen.

String s2="foo";

Dieses Mal wird überprüft, ob das "foo" -Literal bereits in StringPool verfügbar ist oder nicht, da es jetzt existiert, sodass s2 auf dasselbe Literal verweist.

String s3=new String("foo");

Das Literal "foo" wird zuerst in StringPool erstellt, dann über den String-Arg-Konstruktor. Das String-Objekt wird erstellt, dh "foo" im Heap aufgrund der Objekterstellung durch einen neuen Operator, dann verweist s3 darauf.

String s4=new String("foo");

gleich wie s3

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

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

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

Vikas
quelle
1
Verwenden Sie keine Anführungszeichenformatierung für Text, der nicht in Anführungszeichen steht, und keine Codeformatierung für Code.
Marquis von Lorne
12

Strings sind in Java etwas Besonderes - sie sind unveränderlich und Zeichenfolgenkonstanten werden automatisch in StringObjekte umgewandelt.

Es gibt keine Möglichkeit, Ihr SomeStringClass cis = "value"Beispiel auf eine andere Klasse anzuwenden.

Sie können auch nicht erweitern String, da es als deklariert ist final, was bedeutet, dass keine Unterklassifizierung zulässig ist.

Alnitak
quelle
7

Java-Strings sind interessant. Es sieht so aus, als hätten die Antworten einige der interessanten Punkte abgedeckt. Hier sind meine zwei Cent.

Zeichenfolgen sind unveränderlich (Sie können sie nie ändern)

String x = "x";
x = "Y"; 
  • In der ersten Zeile wird eine Variable x erstellt, die den Zeichenfolgenwert "x" enthält. Die JVM prüft in ihrem Pool von Zeichenfolgenwerten, ob "x" vorhanden ist. Wenn dies der Fall ist, zeigt sie die Variable x darauf. Wenn sie nicht vorhanden ist, erstellt sie sie und führt dann die Zuweisung durch
  • In der zweiten Zeile wird der Verweis auf "x" entfernt und geprüft, ob "Y" im Pool der Zeichenfolgenwerte vorhanden ist. Wenn es existiert, wird es zugewiesen, wenn es nicht vorhanden ist, wird es zuerst erstellt und dann zugewiesen. Wenn die Zeichenfolgenwerte verwendet werden oder nicht, wird der Speicherplatz im Pool der Zeichenfolgenwerte zurückgefordert.

Zeichenfolgenvergleiche hängen davon ab, was Sie vergleichen

String a1 = new String("A");

String a2 = new String("A");
  • a1 ist nicht gleich a2
  • a1und a2sind Objektreferenzen
  • Wenn eine Zeichenfolge explizit deklariert wird, werden neue Instanzen erstellt und ihre Referenzen sind nicht identisch.

Ich denke, Sie sind auf dem falschen Weg, wenn Sie versuchen, die kaseinsensitive Klasse zu verwenden. Lass die Saiten in Ruhe. Was Sie wirklich interessiert, ist, wie Sie die Werte anzeigen oder vergleichen. Verwenden Sie eine andere Klasse, um die Zeichenfolge zu formatieren oder Vergleiche anzustellen.

dh

TextUtility.compare(string 1, string 2) 
TextUtility.compareIgnoreCase(string 1, string 2)
TextUtility.camelHump(string 1)

Da Sie die Klasse bilden, können Sie die Vergleiche so machen, wie Sie es möchten - vergleichen Sie die Textwerte.

mson
quelle
Der Compiler erstellt den Zeichenfolgenpool, nicht die JVM. Variablen enthalten keine Objekte, sie verweisen auf sie. Der String-Pool-Speicherplatz für String-Literale wird niemals zurückgefordert.
Marquis von Lorne
6

Das kannst du nicht. Dinge in doppelten Anführungszeichen in Java werden vom Compiler speziell als Strings erkannt, und leider können Sie dies nicht überschreiben (oder erweitern java.lang.String- es ist deklariert final).

Dan Vinton
quelle
Finale ist hier ein roter Hering. Selbst wenn String nicht endgültig wäre, würde ihm die Erweiterung von String in diesem Fall nicht helfen.
Darron
1
Ich denke du meinst zum Glück, dass du das nicht überschreiben kannst. :)
Craig P. Motlin
@ Motlin: Ha! Sie können gut richtig sein. Ich glaube, ich habe irgendwo gelesen, dass Java entwickelt wurde, um zu verhindern, dass jemand jemals etwas Dummes tut, indem es absichtlich etwas Interessantes wie dieses ausschließt ...
Dan Vinton
6

Die beste Möglichkeit, Ihre Frage zu beantworten, besteht darin, sich mit dem "String-Konstantenpool" vertraut zu machen. In Java sind String-Objekte unveränderlich (dh ihre Werte können nach ihrer Initialisierung nicht mehr geändert werden). Wenn Sie also ein String-Objekt bearbeiten, erstellen Sie ein neues bearbeitetes String-Objekt, wobei das alte Objekt nur in einem speziellen Speicherbereich schwebt, der als "String" bezeichnet wird konstanter Pool ". Erstellen eines neuen String-Objekts durch

String s = "Hello";

erstellt nur ein Zeichenfolgenobjekt im Pool und die Referenz s verweist darauf, jedoch mit

String s = new String("Hello");

Sie erstellen zwei Zeichenfolgenobjekte: eines im Pool und das andere im Heap. Die Referenz bezieht sich auf das Objekt im Heap.

Surender Thakran
quelle
4

- Wie kann ich CaseInsensitiveString wie String verhalten, damit die obige Anweisung in Ordnung ist (mit und ohne Erweiterung des Strings)? Was ist es an String, das es in Ordnung macht, es einfach so wörtlich weitergeben zu können? Nach meinem Verständnis gibt es in Java kein "Kopierkonstruktor" -Konzept, oder?

Vom ersten Punkt an wurde genug gesagt. "Polnisch" ist ein Zeichenfolgenliteral und kann nicht der CaseInsentiviveString-Klasse zugewiesen werden.

Nun zum zweiten Punkt

Obwohl Sie keine neuen Literale erstellen können, können Sie dem ersten Punkt dieses Buches für einen "ähnlichen" Ansatz folgen, sodass die folgenden Aussagen zutreffen:

    // Lets test the insensitiveness
    CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
    CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");

    assert cis5 == cis6;
    assert cis5.equals(cis6);

Hier ist der Code.

C:\oreyes\samples\java\insensitive>type CaseInsensitiveString.java
import java.util.Map;
import java.util.HashMap;

public final class CaseInsensitiveString  {


    private static final Map<String,CaseInsensitiveString> innerPool 
                                = new HashMap<String,CaseInsensitiveString>();

    private final String s;


    // Effective Java Item 1: Consider providing static factory methods instead of constructors
    public static CaseInsensitiveString valueOf( String s ) {

        if ( s == null ) {
            return null;
        }
        String value = s.toLowerCase();

        if ( !CaseInsensitiveString.innerPool.containsKey( value ) ) {
             CaseInsensitiveString.innerPool.put( value , new CaseInsensitiveString( value ) );
         }

         return CaseInsensitiveString.innerPool.get( value );   
    }

    // Class constructor: This creates a new instance each time it is invoked.
    public CaseInsensitiveString(String s){
        if (s == null) {
            throw new NullPointerException();
         }         
         this.s = s.toLowerCase();
    }

    public boolean equals( Object other ) {
         if ( other instanceof CaseInsensitiveString ) {
              CaseInsensitiveString otherInstance = ( CaseInsensitiveString ) other;
             return this.s.equals( otherInstance.s );
         }

         return false;
    }


    public int hashCode(){
         return this.s.hashCode();
    }

// Teste die Klasse mit dem Schlüsselwort "assert"

    public static void main( String [] args ) {

        // Creating two different objects as in new String("Polish") == new String("Polish") is false
        CaseInsensitiveString cis1 = new CaseInsensitiveString("Polish");
        CaseInsensitiveString cis2 = new CaseInsensitiveString("Polish");

        // references cis1 and cis2 points to differents objects.
        // so the following is true
        assert cis1 !=  cis2;      // Yes they're different
        assert cis1.equals(cis2);  // Yes they're equals thanks to the equals method

        // Now let's try the valueOf idiom
        CaseInsensitiveString cis3 = CaseInsensitiveString.valueOf("Polish");
        CaseInsensitiveString cis4 = CaseInsensitiveString.valueOf("Polish");

        // References cis3 and cis4 points to same  object.
        // so the following is true
        assert cis3 == cis4;      // Yes they point to the same object
        assert cis3.equals(cis4); // and still equals.

        // Lets test the insensitiveness
        CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
        CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");

        assert cis5 == cis6;
        assert cis5.equals(cis6);

        // Futhermore
        CaseInsensitiveString cis7 = CaseInsensitiveString.valueOf("SomethinG");
        CaseInsensitiveString cis8 = CaseInsensitiveString.valueOf("someThing");

        assert cis8 == cis5 && cis7 == cis6;
        assert cis7.equals(cis5) && cis6.equals(cis8);
    }

}

C:\oreyes\samples\java\insensitive>javac CaseInsensitiveString.java


C:\oreyes\samples\java\insensitive>java -ea CaseInsensitiveString

C:\oreyes\samples\java\insensitive>

Erstellen Sie also einen internen Pool von CaseInsensitiveString-Objekten und geben Sie von dort aus die entsprechende Instanz zurück.

Auf diese Weise gibt der Operator "==" true für zwei Objektreferenzen zurück, die denselben Wert darstellen .

Dies ist nützlich, wenn ähnliche Objekte sehr häufig verwendet werden und das Erstellen von Kosten teuer ist.

In der Dokumentation zur Zeichenfolgenklasse wird angegeben, dass die Klasse einen internen Pool verwendet

Die Klasse ist nicht vollständig. Einige interessante Probleme treten auf, wenn wir versuchen, den Inhalt des Objekts bei der Implementierung der CharSequence-Schnittstelle zu durchlaufen. Dieser Code ist jedoch gut genug, um zu zeigen, wie dieses Element im Buch angewendet werden kann.

Es ist wichtig zu beachten, dass bei Verwendung des internalPool- Objekts die Referenzen nicht freigegeben werden und somit kein Müllsammelobjekt ist. Dies kann zu einem Problem werden, wenn viele Objekte erstellt werden.

Es funktioniert für die String-Klasse, da es intensiv genutzt wird und der Pool nur aus "internierten" Objekten besteht.

Es funktioniert auch gut für die Boolesche Klasse, da es nur zwei mögliche Werte gibt.

Und schließlich ist dies auch der Grund, warum valueOf (int) in der Klasse Integer auf -128 bis 127 int-Werte beschränkt ist.

OscarRyz
quelle
3

In Ihrem ersten Beispiel erstellen Sie einen String "albern" und übergeben ihn dann als Parameter an den Kopierkonstruktor eines anderen Strings, wodurch ein zweiter String erstellt wird, der mit dem ersten identisch ist. Da Java-Strings unveränderlich sind (was häufig Menschen sticht, die an C-Strings gewöhnt sind), ist dies eine unnötige Verschwendung von Ressourcen. Sie sollten stattdessen das zweite Beispiel verwenden, da mehrere unnötige Schritte übersprungen werden.

Das String-Literal ist jedoch kein CaseInsensitiveString, sodass Sie in Ihrem letzten Beispiel nicht das tun können, was Sie wollen. Darüber hinaus gibt es keine Möglichkeit, einen Casting-Operator wie in C ++ zu überladen, sodass buchstäblich keine Möglichkeit besteht, das zu tun, was Sie möchten. Sie müssen es stattdessen als Parameter an den Konstruktor Ihrer Klasse übergeben. Natürlich würde ich wahrscheinlich nur String.toLowerCase () verwenden und damit fertig sein.

Außerdem sollte Ihr CaseInsensitiveString die CharSequence-Schnittstelle sowie wahrscheinlich die serialisierbaren und vergleichbaren Schnittstellen implementieren. Wenn Sie Comparable implementieren, sollten Sie natürlich auch equals () und hashCode () überschreiben.

James
quelle
3

Nur weil Sie das Wort Stringin Ihrer Klasse haben, bedeutet dies nicht, dass Sie alle Besonderheiten der integrierten StringKlasse erhalten.

javaguy
quelle
3

CaseInsensitiveStringist kein a, Stringobwohl es a enthält String. Ein StringLiteral zB "Beispiel" kann nur einem zugeordnet werden String.

fastcodejava
quelle
2

CaseInsensitiveString und String sind unterschiedliche Objekte. Sie können nicht tun:

CaseInsensitiveString cis = "Polish";

weil "Polish" ein String ist, kein CaseInsensitiveString. Wenn String CaseInsensitiveString String erweitert, sind Sie in Ordnung, aber offensichtlich nicht.

Und mach dir keine Sorgen um die Konstruktion hier, du wirst keine unnötigen Objekte herstellen. Wenn Sie sich den Code des Konstruktors ansehen, wird lediglich ein Verweis auf die übergebene Zeichenfolge gespeichert. Es wird nichts Zusätzliches erstellt.

Im Fall von String s = new String ("foobar") macht es etwas anderes. Sie erstellen zuerst die Literalzeichenfolge "foobar" und dann eine Kopie davon, indem Sie daraus eine neue Zeichenfolge erstellen. Diese Kopie muss nicht erstellt werden.

Herms
quelle
Selbst wenn Sie String erweitern würden, würde dies nicht funktionieren. Sie benötigen String, um CaseInsensitiveString zu erweitern.
Darron
in jedem Fall seines unmöglich, weil entweder String wird in oder weil gebaut seinem endgültigen erklärt
luke
2

wenn sie sagen zu schreiben

String s = "Silly";

anstatt

String s = new String("Silly");

Sie meinen es beim Erstellen eines String-Objekts, da beide obigen Anweisungen ein String-Objekt erstellen, die neue String () -Version jedoch zwei String-Objekte erstellt: eines im Heap und das andere im String-Konstantenpool. Daher wird mehr Speicher verwendet.

Aber wenn du schreibst

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

Sie erstellen keinen String, sondern ein Objekt der Klasse CaseInsensitiveString. Daher müssen Sie den neuen Operator verwenden.


quelle
1

Wenn ich es richtig verstanden habe, bedeutet Ihre Frage, warum wir ein Objekt nicht erstellen können, indem wir ihm direkt einen Wert zuweisen. Wir können es nicht auf eine Wrapper of String-Klasse in Java beschränken.

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

Das bedeutet genau, wenn der Interpreter 3 sieht, wird er in ein Integer-Objekt konvertiert, da 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, Sie müssen es nicht angeben, da die Sprache das Standardobjekt vom Typ Zeichen dafür definiert.

Wenn der Interpreter etwas in "" sieht, wird es als Objekt seines Standardtyps betrachtet, dh als Zeichenfolge. Dies ist ein nativer Code, der im Hintergrund arbeitet.

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

Dharam
quelle
0

In Java erstellt die Syntax "text" eine Instanz der Klasse java.lang.String. Die Zuordnung:

String foo = "text";

ist eine einfache Aufgabe, für die kein Kopierkonstruktor erforderlich ist.

MyString bar = "text";

Ist illegal, was auch immer Sie tun, da die MyString-Klasse weder java.lang.String noch eine Oberklasse von java.lang.String ist.

Darron
quelle
0

Erstens können Sie keine Klasse erstellen, die sich von String aus erstreckt, da String eine letzte Klasse ist. Und Java verwaltet Strings anders als andere Klassen, sodass Sie dies nur mit String tun können

String s = "Polish";

Aber mit Ihrer Klasse müssen Sie den Konstruktor aufrufen. Dieser Code ist also in Ordnung.

Lucas Gabriel Sánchez
quelle
0

Ich möchte nur hinzufügen, dass Java Kopierkonstruktoren hat ...

Nun, das ist ein gewöhnlicher Konstruktor mit einem Objekt vom gleichen Typ wie das Argument.

PhiLho
quelle
2
Es ist ein Entwurfsmuster, kein Sprachkonstrukt. Mit Java gibt es nur sehr wenige Anwendungen, bei denen ein Kopierkonstruktor interessant wäre, da immer alles "als Referenz" ist und jedes Objekt nur eine Kopie hat. In der Tat würde das Erstellen von Kopien wirklich viele Probleme verursachen.
Bill K
0

In den meisten Versionen des JDK sind die beiden Versionen identisch:

String s = neuer String ("albern");

String s = "Nicht mehr albern";

Da Zeichenfolgen unveränderlich sind, verwaltet der Compiler eine Liste von Zeichenfolgenkonstanten. Wenn Sie versuchen, eine neue zu erstellen, wird zunächst überprüft, ob die Zeichenfolge bereits definiert ist. Wenn dies der Fall ist, wird ein Verweis auf die vorhandene unveränderliche Zeichenfolge zurückgegeben.

Zur Verdeutlichung: Wenn Sie "String s =" sagen, definieren Sie eine neue Variable, die Platz auf dem Stapel einnimmt, passiert genau dasselbe, ob Sie "Nicht mehr albern" oder einen neuen String ("albern") sagen - eine neue Eine konstante Zeichenfolge wird in Ihre Anwendung kompiliert und die Referenz zeigt darauf.

Ich sehe den Unterschied hier nicht. Für Ihre eigene Klasse, die nicht unveränderlich ist, ist dieses Verhalten jedoch irrelevant und Sie müssen Ihren Konstruktor aufrufen.

UPDATE: Ich habe mich geirrt! Aufgrund einer Abwärtsabstimmung und eines beigefügten Kommentars habe ich dies getestet und festgestellt, dass mein Verständnis falsch ist - neue Zeichenfolge ("Silly") erstellt tatsächlich eine neue Zeichenfolge, anstatt die vorhandene wiederzuverwenden. Ich bin mir nicht sicher, warum dies so ist (was ist der Vorteil?), Aber Code spricht lauter als Worte!

Ewan Makepeace
quelle
0

String ist eine der speziellen Klassen, in denen Sie sie ohne den neuen Sring-Teil erstellen können

es ist das gleiche wie

int x = y;

oder

char c;

Tolga E.
quelle
0

Es ist ein Grundgesetz, dass Strings in Java unveränderlich sind und zwischen Groß- und Kleinschreibung unterscheiden.

user1945649
quelle
0
 String str1 = "foo"; 
 String str2 = "foo"; 

Sowohl str1 als auch str2 gehören zum selben String-Objekt "foo". B'coz Java verwaltet Strings in StringPool. Wenn also eine neue Variable auf denselben String verweist, wird keine weitere Variable erstellt, sondern dieselbe in StringPool vorhandene Alerady zugewiesen .

 String str1 = new String("foo"); 
 String str2 = new String("foo");

Hier gehören sowohl str1 als auch str2 zu verschiedenen Objekten. B'coz new String () erstellt zwangsweise ein neues String-Objekt.

Akash5288
quelle
-1

Java erstellt ein String-Objekt für jedes String-Literal, das Sie in Ihrem Code verwenden. Jedes Mal "", wenn es verwendet wird, ist es dasselbe wie ein Anruf new String().

Strings sind komplexe Daten, die sich nur wie primitive Daten "verhalten". String-Literale sind tatsächlich Objekte, obwohl wir so tun, als wären sie primitive Literale wie 6, 6.0, 'c',usw. Das String-Literal "text"gibt also ein neues String-Objekt mit Wert zurück char[] value = {'t','e','x','t}. Deshalb anrufen

new String("text"); 

ist eigentlich ähnlich wie anrufen

new String(new String(new char[]{'t','e','x','t'}));

Hoffentlich können Sie von hier aus sehen, warum Ihr Lehrbuch dies für überflüssig hält.

Als Referenz finden Sie hier die Implementierung von String: http://www.docjar.com/html/api/java/lang/String.java.html

Es macht Spaß zu lesen und könnte zu Einsichten inspirieren. Es ist auch ideal für Anfänger, zu lesen und zu verstehen, da der Code sehr professionellen und konventionskonformen Code zeigt.

Eine weitere gute Referenz ist das Java-Tutorial zu Strings: http://docs.oracle.com/javase/tutorial/java/data/strings.html

Patrick Michaelsen
quelle
Jedes Mal, wenn "" verwendet wird, verweist es auf dieselbe Zeichenfolge im Konstantenpool.
Marquis von Lorne