Making Java Strings Simple
Your professor may tell you that using the String concatenation operator "+" can be inefficient. This is not entirely true.
The above code is optimized by the compiler into something like this
So which is more efficient for you, typing 97 characters or 191 characters? More than 100% more typing for the same byte code.
There are exceptions though. The most important one being loops.
The above is preferred to this
because the second example creates a new StringBuffer/Builder for each iteration (read "more resources are used").
Here is some bytecode to back these claims. First the slower way:
And now the quicker way:
As you can see in this example only the append() method is called inside the loop, whereas in the slower example
*Prior to Java 5 StringBuffer was used, now the preferred class is StringBuilder.
String str = "foo" + "bar" + "Oh my, there must be a more efficient way to concatenate a String";
The above code is optimized by the compiler into something like this
StringBuffer/Builder* _temp = new StringBuffer/Builder().append("foo").append("bar")
.append("Oh my, there must be a more efficient way to concatenate a String");
String str = _temp.toString();
.append("Oh my, there must be a more efficient way to concatenate a String");
String str = _temp.toString();
So which is more efficient for you, typing 97 characters or 191 characters? More than 100% more typing for the same byte code.
There are exceptions though. The most important one being loops.
StringBuffer/Builder _temp = new StringBuffer/Builder();
while(moreDataToAppend()) {
_temp.append(someString);
}
String str = _temp.toString();
while(moreDataToAppend()) {
_temp.append(someString);
}
String str = _temp.toString();
The above is preferred to this
String str = "";
while(moreDataToAppend()) {
str + someString;
}
while(moreDataToAppend()) {
str + someString;
}
because the second example creates a new StringBuffer/Builder for each iteration (read "more resources are used").
Here is some bytecode to back these claims. First the slower way:
7: getstatic #3; //Field i:I <----Here is the beginning of the loop
10: bipush 36
12: if_icmpge 51
15: new #4; //class java/lang/StringBuilder
18: dup
19: invokespecial #5; //Method java/lang/StringBuilder."":()V <----Here is
the allocation of the StringBuilder (this is invoked in every iteration of the loop)
22: aload_1
23: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)
Ljava/lang/StringBuilder;
26: getstatic #7; //Field data:[Ljava/lang/String;
29: getstatic #3; //Field i:I
32: aaload
33: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)
Ljava/lang/StringBuilder;
36: invokevirtual #8; //Method java/lang/StringBuilder.toString:()
Ljava/lang/String; <----This can also be move outside of the loop
39: astore_1
40: getstatic #3; //Field i:I
43: iconst_1
44: iadd
45: putstatic #3; //Field i:I
48: goto 7 <----Here is the end of the loop
10: bipush 36
12: if_icmpge 51
15: new #4; //class java/lang/StringBuilder
18: dup
19: invokespecial #5; //Method java/lang/StringBuilder."
the allocation of the StringBuilder (this is invoked in every iteration of the loop)
22: aload_1
23: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)
Ljava/lang/StringBuilder;
26: getstatic #7; //Field data:[Ljava/lang/String;
29: getstatic #3; //Field i:I
32: aaload
33: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)
Ljava/lang/StringBuilder;
36: invokevirtual #8; //Method java/lang/StringBuilder.toString:()
Ljava/lang/String; <----This can also be move outside of the loop
39: astore_1
40: getstatic #3; //Field i:I
43: iconst_1
44: iadd
45: putstatic #3; //Field i:I
48: goto 7 <----Here is the end of the loop
And now the quicker way:
51: new #4; //class java/lang/StringBuilder
54: dup
55: invokespecial #5; //Method java/lang/StringBuilder."":()V <----Here is
the allocation of the StringBuilder
58: astore_2
59: iconst_0
60: putstatic #3; //Field i:I
63: getstatic #3; //Field i:I <----Here is the beginning of the loop
66: bipush 36
68: if_icmpge 94
71: aload_2
72: getstatic #7; //Field data:[Ljava/lang/String;
75: getstatic #3; //Field i:I
78: aaload
79: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)
Ljava/lang/StringBuilder;
82: pop
83: getstatic #3; //Field i:I
86: iconst_1
87: iadd
88: putstatic #3; //Field i:I
91: goto 63 <----Here is the end of the loop
94: aload_2
95: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
54: dup
55: invokespecial #5; //Method java/lang/StringBuilder."
the allocation of the StringBuilder
58: astore_2
59: iconst_0
60: putstatic #3; //Field i:I
63: getstatic #3; //Field i:I <----Here is the beginning of the loop
66: bipush 36
68: if_icmpge 94
71: aload_2
72: getstatic #7; //Field data:[Ljava/lang/String;
75: getstatic #3; //Field i:I
78: aaload
79: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)
Ljava/lang/StringBuilder;
82: pop
83: getstatic #3; //Field i:I
86: iconst_1
87: iadd
88: putstatic #3; //Field i:I
91: goto 63 <----Here is the end of the loop
94: aload_2
95: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
As you can see in this example only the append() method is called inside the loop, whereas in the slower example
*Prior to Java 5 StringBuffer was used, now the preferred class is StringBuilder.