Java-Strings, StringBuilder, StringBuffer

Erfahren Sie heute mehr über Strings in Java. Java-Strings gehören zu den am häufigsten verwendeten und daher werden wir uns ausführlich damit befassen.

Einige der Hauptunterschiede zwischen Java-Strings und anderen Sprachen sind:

  • String ist ein Objekt in Java und Teil des Pakets java.lang.
  • Um Objekte anderer Klassen in Java aufzurufen, müssen wir ein neues Objekt() in Java erstellen und dann auf die darin enthaltenen Methoden zugreifen. Aber in Java können Strings auch erstellt werden, ohne explizit ein neues String()-Objekt dafür zu erstellen.
  • Zeichenfolgen sind veränderlich. Ich werde dies anhand einiger Beispiele verdeutlichen.
  • String-Verkettung mit dem „+“-Operator.
  • Java-Strings-Deklaration:

    String java_str = "JavaStrings";
    String java_str1 = new String("JavaStrings1");
    

    Im ersten Fall erstellt Java intern eine neue Objektinstanz von Strings und speichert dann deren Inhalt „JavaStrings“, während wir im zweiten Fall Strings explizit mit dem Java-Konstruktor erstellen.

    Denken Sie an die Methodenüberladung: Die Java-String-Klasse verfügt über mehr als 10 Konstruktoren, die je nach Bedarf eingesetzt werden können. Schauen wir uns das folgende Programm an, um die Sache etwas interessanter zu machen. Ich habe das Beispielprogramm in mehrere Teile aufgeteilt, um Schlüsselkonzepte hervorzuheben. Schauen wir uns jedes Szenario im Detail an.

    public class JavaString {
    
        /**
        * @param args
        */
         public static void main(String() args) {
            String str1 = "JavaString1";
            String str2 = "JavaString1";
    
            if(str1==str2) {
               System.out.println("They are equal!");
            }
            else {
               System.out.println("No, they are not equal!");
            }
         }
      }
    

    Ausgabe:

    They are equal!
    

    Im ersten Fall wurden zwei unterschiedliche Zeichenfolgen str1 und str2 mithilfe von Zeichenfolgenliteralen (ein häufig verwendeter Name für solche Deklarationen) erstellt. Denken Sie daran, dass die Methode „==“ zwei Objektreferenzen und nicht deren Inhalt vergleicht. Damit sowohl str1 als auch str2 den gleichen Inhalt haben, optimiert Java diese unterschiedlichen Zeichenfolgen intern und speichert sie am selben Speicherort. Java reserviert für diesen Zweck etwas Speicher. Von nun an nennen wir es als Referenz „String-Speicher“. Deshalb erfüllen sie die Gleichheitsbedingung.

    Hinweis: Verwenden Sie zum Vergleichen zweier Zeichenfolgen immer die Methode equal(). Ich habe „==“ nur zur Veranschaulichung verwendet.

     String str3 = new String("JavaString1");
     String str4 = new String("JavaString2");
    <span style="font-size: 12px; line-height: 18px;">   if(str3==str4) {</span>
        System.out.println("They are equal!");
       }
       else {
        System.out.println("No, they are not equal!");
       }
    

    Ausgabe:

    No, they are not equal!
    

    Im zweiten Fall habe ich mit new String() zwei Strings erstellt und sie werden erwartungsgemäß an zwei verschiedenen Orten im Speicher gespeichert, obwohl ihr Inhalt derselbe ist. Dies wird im Heap-Speicher gespeichert, im Vergleich zum ersten Fall, in dem Java es optimiert und in einem String-Speicher speichert. Das ist ein wesentlicher Unterschied. Und da wir zwei verschiedene Objektreferenzen vergleichen, lautet die Ausgabe „Sie sind nicht gleich!“.

    str3 = str4;
        if (str3==str4) {
            System.out.println("They are equal!");
        }
        else {
           System.out.println("No, they are not equal!");
        }
    

    Ausgabe:

    They are equal!
    

    Der dritte Fall kombiniert die Konzepte des ersten und des zweiten Szenarios. Wir verwenden dieselben Strings, die mit new String() erstellt wurden, weisen aber einen String-Verweis einem anderen zu, dh beide verweisen jetzt auf denselben Speicherort. Dies soll veranschaulichen, dass Zeichenfolgen mit demselben Inhalt, die mit new String() erstellt wurden, immer „false“ zurückgeben, es sei denn, Sie weisen explizit eine Zeichenfolgenreferenz einer anderen zu, wie wir es in diesem Fall tun. Das ist der Grund; wir sehen die Ausgabe „Sie sind gleich!“ in diesem Fall.

    String str5 = "JavaString5";
      String str6 = "JavaString6";
    
      if(str5==str6) {
          System.out.println("They are equal!");
      }
      else {
          System.out.println("No, they are not equal!");
      }
    

    Sagen Sie nun die Ausgabe des obigen Programms voraus, bevor Sie die Ausgabe unten überprüfen:

    Hurra! du hast Recht. Die Ausgabe wäre „Nein, sie sind nicht gleich!“. Dies liegt daran, dass zwei Zeichenfolgen an unterschiedlichen Speicherorten (nicht im Heap) gespeichert werden, da sie unterschiedliche Inhalte haben.

    Ausgabe:

    No, they are not equal!
    

    Unveränderliche Zeichenfolgen

    Sie müssen diesen Begriff schon an mehreren Stellen gehört haben, Java-Strings sind unveränderlich. Was könnte also die nächste Frage sein? Schauen wir es uns im Detail an. Einige der Hauptgründe, warum Strings in Java unveränderlich sind, sind Sicherheit, verzögerte Hashcode()-Initialisierung und Thread-Sicherheit. Unveränderlich bedeutet, dass der Zustand eines Objekts nach seiner Erstellung nicht mehr geändert werden kann. Daher können Java-Strings, die einmal erstellt und zugewiesen wurden, später nicht mehr geändert werden. Das mag etwas verwirrend sein, aber bleiben Sie bei mir und ich werde Beispiele liefern, um dies zu veranschaulichen.

    String myStr = new String("StringOld");
    System.out.println( myStr + ":" + myStr.hashCode());
    myStr.replace("Old", "New");
    System.out.println( myStr + ":" + myStr.hashCode());
    

    Oh, warte … aber haben wir myStr nicht auf einen neuen Wert geändert !!!!. Warum wird der neue Wert nicht gedruckt? Das liegt daran, dass Zeichenfolgen unveränderlich sind. Sobald wir also eine String-Referenz erstellt haben, kann ihr Inhalt nicht mehr geändert werden. Was also wirklich passiert, ist, dass Java, wenn wir seinen Wert ändern, intern eine neue String-Instanz erstellt und diesen neuen geänderten Wert speichert, wobei die alte String-Referenz unverändert bleibt. Aus diesem Grund gibt die Ausgabe dieselbe Ausgabe aus, obwohl wir ihren Wert geändert haben.

    String newStr = new String("Stringold");
    System.out.println( newStr + ":" + newStr.hashCode());
    newStr = newStr + "new";
    System.out.println( newStr + ":" + newStr.hashCode());
    

    Ausgabe:

    Stringold: 1814702166
    Stringoldnew: 1038981514
    

    Dann,

    myStr = myStr.replace("Old", "New");
    System.out.println( myStr + ":" + myStr.hashCode());
    

    Wenn wir das getan hätten, wären unterschiedliche Hashcodes die Ausgabe gewesen. Obwohl wir glauben, dass wir dieselben Strings ändern, verbraucht Java intern Speicher für die Erstellung einer neuen String-Referenz und muss eine Garbage Collection für zwei String-Referenzen statt für eine durchführen. Denken Sie also daran, Als Java-Entwickler müssen wir immer StringBuilder/StringBuffer verwenden, wenn wir wissen, dass wir den String-Inhalt ändern werden.

    Ausgabe:

    StringNew: 1814670255
    

    Dieses Beispiel wird Ihnen helfen, Immutable viel besser zu verstehen. Obwohl wir nun denselben String ändern, wird intern von Java eine weitere String-Referenz erstellt, weshalb wir zwei verschiedene Hashcodes ausgedruckt sehen. Aber dann könnte die Frage sein, warum dieselben hashcodes() im vorherigen Beispiel? Das liegt daran, dass wir es nicht myStr zugewiesen haben.

    Vorteile von unveränderlich

  • Wie man sieht, können wir aus Sicherheitsgründen diese unveränderliche Eigenschaft nutzen, wenn wir sicherstellen müssen, dass niemand sonst den ursprünglichen Wert von Strings geändert hat, den er haben sollte.
  • Am Ende verwenden wir viele String-hashcode()-Methoden im Java Collections-Framework wie HashMap. Sie verwenden diese unveränderliche Eigenschaft, um ihre hashcode()-Werte zwischenzuspeichern, anstatt sie jedes Mal abzurufen. Dies liegt daran, dass wir wissen, dass einmal erstellte String-Werte danach nicht mehr geändert werden können.
  • Thread-Sicherheit: Mit dieser unveränderlichen Eigenschaft können wir sicher sein, dass ein bestimmter String-Wert nicht von parallel laufenden Threads geändert werden konnte. Als ob es geändert worden wäre, wird intern von Java eine neue String-Instanz erstellt, und so hilft uns diese Unveränderlichkeit bei der Thread-Sicherheit.
  • StringBuilder und StringBuffer

    Gibt es nicht auch andere Formen veränderlicher String-Objekte? Ja, das gibt es. StringBuilder und StringBuffer sind veränderbare String-Objekte. Wir gehen hier kurz auf sie ein, da sie sehr leicht zu verstehen sind. Abgesehen davon sind sie fast gleich StringBuilder ist nicht synchronisiert und StringBuffer ist synchronisiert und es kommt also auf die Nutzung an. Schauen wir uns ein Beispiel an, um die Unterschiede bei der Verwendung der StringBuffer- und StringBuilder-Klassen zu sehen.

     String str = "";
          int size = 5000;
          // Using StringBuffer class - unsynchronized and so can save overhead
          // while being used in Single Threaded programs
          startTime = System.nanoTime();
          size = 5000;
          StringBuilder sBuildbuf = new StringBuilder(size);
          for (int i = 0; i < size; ++i) {
              sBuildbuf = sBuildbuf.append("ABC");
          }
    
          elapsedTime = System.nanoTime() - startTime;
          System.out.println("Building Stringbuilder " + "Time diff is " +                                         elapsedTime/100000);
    

    Und

     // Using StringBuilder class – synchronized and can be effectively
          // used in multi threaded programs
          startTime = System.nanoTime();
          size = 5000;
          StringBuffer sBuffbuf = new StringBuffer(str);
          for (int i = 0; i < size; ++i) {
               sBuffbuf = sBuffbuf.append("ABC");
          }
          elapsedTime = System.nanoTime() - startTime;
          System.out.println("Building Stringbuffer " + "Time diff is " + elapsedTime/100000);
      }
    

    Ausgabe:

    Building Stringbuilder Time diff is 18
    Building Stringbuffer Time diff is 23
    

    Der Zeitunterschied ist nicht so groß, da StringBuilder und StringBuffer auf ähnliche Weise implementiert wurden, außer dass Java bei der Implementierung von StringBuilder Overhead spart, da es für Single-Thread-Programme optimiert ist.

    String msg = "one" + "two" + "three",
    

    Java kompiliert diese Zeilen intern zu

    String msg = new StringBuffer().append("one").append("two").append("three")                                    .toString();
    

    Wie man sieht, ist es ein Overhead, wenn wir Strings ändern. Daher sollten wir Strings immer vermeiden, wenn wir wissen, dass wir sie häufig ändern werden. Stattdessen sollten wir die Klassen StringBuffer und StringBuilder verwenden.

    Es gibt viele Methoden in den Klassen Strings, StringBuilder und StringBuffer. Entdecken Sie sie mit Javadocs. Veröffentlichen Sie sie in den Kommentaren, wenn Sie weitere interessante Dinge über Strings finden, die auch für andere nützlich sein könnten. Danke fürs Lesen.

    Dieser Artikel wurde ursprünglich unter veröffentlicht Java-Tutorials – Lasst uns ins Meer springenhier mit Genehmigung des Autors und als Teil des JBC-Programms erneut veröffentlicht.

    Kommentar verfassen

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

    Nach oben scrollen