good day


As many people know, it is undesirable to use such a construction in Java

 "Hello" + "Name" + "Surname" + etc.; //ΠΈΠ»ΠΈ ΠΆΠ΅ String text = "Hello"; text += "Name"; text += "Surname"; text += etc...; 

And it is worthwhile to use StringBuilder in these cases, although I had a question about this, I would like to know if I use it correctly?

 public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Name: " + this.getName()); builder.append("\nSurname: " + this.getSurname()); builder.append("\nAge: " + this.getAge()); builder.append(this.isSex() ? "\nWoman " : "\nMan "); builder.append("\nCourse: " + this.course); builder.append("\nFaculty: " + this.faculty); builder.append("\nGroup: " + this.group); String result = new String(builder); return result; } 

Looking at the code, I think that I use it incorrectly ... If so, tell me how to use it, and what is desirable to use in such situations?

  • and on the return builder.toString() replace - Senior Pomidor

4 answers 4

The concatenation operations in append are replaced by the continuation of the call chain of the append itself, in order to minimize the creation of new String strings:

 builder.append("\nAge: ").append(this.getAge()); 

etc. But in general - everything is fine. And the question of optimization in this case is questionable, although it is not excluded ...

  • All in one line or something? - E1mir
  • @KryTer_NexT and do you think that your code creates any other variables?) The code I gave does exactly the same as yours;) I meant replacing concatenation (+ sign, creating a new String type) The append () method in your code. In your version it happens like this: "\ nAge:" + this.getAge () - creates an extra new string String. The append () call chain removes this "problem". - Ep1demic
  • Aaaa understood) Thank you)) - E1mir
 "Hello" + "Name" + "Surname" + etc.; // всС ΠΎΠΊ, Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΎ Π² sb.append(...).append(...). ... А сумма строк-констант Π·Π°Ρ€Π°Π½Π΅Π΅ склССтся Π΅Ρ‰Π΅ Π½Π° этапС ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π° Π² Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄. Π― Π±Ρ‹ Π½Π΅ сказал, Ρ‡Ρ‚ΠΎ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ ΠΏΠ»ΠΎΡ…ΠΎΠΉ. String text = "Hello"; text += "Name"; text += "Surname"; text += etc...; // ΠΊΡ€Π°ΠΉΠ½Π΅ Π½Π΅ эффСктивный ΠΊΠΎΠ΄, ΠΏΠ΅Ρ€Π΅Π΄ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ слоТСния Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Π² StringBuilder, Π° Π·Π°Ρ‚Π΅ΠΌ снова Π² String. Π’Π°ΠΊΠΆΠ΅, Π·Π°Ρ€Π°Π½Π΅Π΅ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Π½ΠΈΠΊΠ°ΠΊΠΈΡ… вычислСний. 

The second block (directly with your code) has already been disassembled.

    In fact, you can combine strings with + if these are regular fields, and not a method call with some side-effect'Π°ΠΌΠΈ . The compiler is smart enough, and it replaces such places with java.lang.StringBuilder .

    You can verify this by considering the following example:

     public class Man { private String name; private String surname; public String firstMethod() { return name + surname; } public String secondMethod() { return new StringBuilder() .append(name) .append(surname) .toString(); }} 

    Let's see what is generated byte code. You can not delve into the details, the most important thing here is the explanations to it.

     public class ru.izebit.Man
       minor version: 0
       major version: 52
       flags: ACC_PUBLIC, ACC_SUPER
     Constant pool:
        # 1 = Methodref # 9. # 25 // java / lang / Object. "" :() V
        # 2 = Class # 26 // java / lang / StringBuilder
        # 3 = Methodref # 2. # 25 // java / lang / StringBuilder. "" :() V
        # 4 = Fieldref # 8. # 27 // en / izebit / Man.name: Ljava / lang / String;
        # 5 = Methodref # 2. # 28 // java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
        # 6 = Fieldref # 8. # 29 // en / izebit / Man.surname: Ljava / lang / String;
        # 7 = Methodref # 2. # 30 // java / lang / StringBuilder.toString: () Ljava / lang / String;
        # 8 = Class # 31 // en / izebit / Man
        # 9 = Class # 32 // java / lang / Object
       # 10 = Utf8 name
       # 11 = Utf8 Ljava / lang / String;
       # 12 = Utf8 surname
       # 13 = Utf8               
       # 14 = Utf8 () V
       # 15 = Utf8 Code
       # 16 = Utf8 LineNumberTable
       # 17 = Utf8 LocalVariableTable
       # 18 = Utf8 this
       # 19 = Utf8 Lru / izebit / Man;
       # 20 = Utf8 firstMethod
       # 21 = Utf8 () Ljava / lang / String;
       # 22 = Utf8 secondMethod
       # 23 = Utf8 SourceFile
       # 24 = Utf8 Man.java
       # 25 = NameAndType # 13: # 14 // "": () V
       # 26 = Utf8 java / lang / StringBuilder
       # 27 = NameAndType # 10: # 11 // name: Ljava / lang / String;
       # 28 = NameAndType # 33: # 34 // append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
       # 29 = NameAndType # 12: # 11 // surname: Ljava / lang / String;
       # 30 = NameAndType # 35: # 21 // toString: () Ljava / lang / String;
       # 31 = Utf8 en / izebit / Man
       # 32 = Utf8 java / lang / Object
       # 33 = Utf8 append
       # 34 = Utf8 (Ljava / lang / String;) Ljava / lang / StringBuilder;
       # 35 = Utf8 toString
     {
       public ru.izebit.Man ();
         descriptor: () V
         flags: ACC_PUBLIC
         Code:
           stack = 1, locals = 1, args_size = 1
              0: aload_0
              1: invokespecial # 1 // Method java / lang / Object. "" :() V
              4: return
           LineNumberTable:
             line 4: 0
           LocalVariableTable:
             Start Length Slot Name Signature
                 0 5 0 this Lru / izebit / Man;
    
       public java.lang.String firstMethod ();
         descriptor: () Ljava / lang / String;
         flags: ACC_PUBLIC
         Code:
           stack = 2, locals = 1, args_size = 1
              0: new # 2 // class java / lang / StringBuilder
              3: dup
              4: invokespecial # 3 // Method java / lang / StringBuilder. "" :() V
              7: aload_0
              8: getfield # 4 // Field name: Ljava / lang / String;
             11: invokevirtual # 5 // Method java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
             14: aload_0
             15: getfield # 6 // Field surname: Ljava / lang / String;
             18: invokevirtual # 5 // Method java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
             21: invokevirtual # 7 // Method java / lang / StringBuilder.toString: () Ljava / lang / String;
             24: areturn
           LineNumberTable:
             line 9: 0
           LocalVariableTable:
             Start Length Slot Name Signature
                 0 25 0 this Lru / izebit / Man;
    
       public java.lang.String secondMethod ();
         descriptor: () Ljava / lang / String;
         flags: ACC_PUBLIC
         Code:
           stack = 2, locals = 1, args_size = 1
              0: new # 2 // class java / lang / StringBuilder
              3: dup
              4: invokespecial # 3 // Method java / lang / StringBuilder. "" :() V
              7: aload_0
              8: getfield # 4 // Field name: Ljava / lang / String;
             11: invokevirtual # 5 // Method java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
             14: aload_0
             15: getfield # 6 // Field surname: Ljava / lang / String;
             18: invokevirtual # 5 // Method java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
             21: invokevirtual # 7 // Method java / lang / StringBuilder.toString: () Ljava / lang / String;
             24: areturn
           LineNumberTable:
             line 13: 0
             line 14: 11
             line 15: 18
             line 16:21
             line 13: 24
           LocalVariableTable:
             Start Length Slot Name Signature
                 0 25 0 this Lru / izebit / Man;
     }
    

    As we can see, both methods use java.lang.StringBuilder .

    With regards to your code, it is quite correct, with the exception of excessive verbosity. StringBuilder allows StringBuilder to write more concisely using the fluent style

    • For the case of concatenation of 3 or more fields \ variables, will a single StringBuilder be generated in a single expression, or will a new one be created for each separate concatenation? - Roxio0
    • one
      It does not depend on the number of lines, it depends on what you combine, for example, "hello" + getWorld () will not be optimized. Yes, there will be only one StringBuilder - Artem Konovalov
    • Is it possible to read somewhere in more detail, why does this not work with calling methods? - Roxio0
    • one
      @ Roxio0 in this report Lesha Shipelev mentions this optimization youtube.com/watch?v=SZFe3m1DV1A - Artem Konovalov

    Yes, the method in StringBuilder.append() will return an instance StringBuilder , that is, you can do as indicated by 'ep1demic'

     StringBuilder sb = new StringBuilder(); sb.append("") .append("") .append(""); 

    it is even better not to use this.getSurname() , just write instead

     this.surname 

    and sb.getString(); instead of new String(sb);

    • There is no such getString() method for StringBuilder ... And about the methods this.getSurname, this.getName(); was due to the fact that I encapsulated in the parent class, which I had to write like this, but already removed the private modifier opened full access :) - E1mir
    • crap toString (); you cannot remove the private modifier, or replace it with a protected one, or use the methods of the parent class. - JAVAvladuxa
    • Well, I used his methods, you wrote that remove this.getSurname(); and do this.surname - E1mir
    • well this is a pointer to the current class. if you can do this.name than this.getName (), so it’s more correct. - JAVAvladuxa
    • aaaaa, just register .append(getName()) ? - E1mir