To help figure out, I wrote the class as follows:
class Test { String a = "abc" ; StringBuilder buffer = new StringBuilder() ; public void normal() { buffer.append( "abc" ) ; buffer.append( "abc" ) ; } public void clever() { buffer.append( a ) ; buffer.append( a ) ; } }
If we compile this, then run javap on it to extract the bytecode:
14:09:58 :: javap $ javap -c Test Compiled from "Test.java" class Test extends java.lang.Object{ java.lang.String a; java.lang.StringBuilder buffer; Test(); Code: 0: aload_0 1: invokespecial
We can see 2 things.
Firstly, the normal method uses the same String instance for both of these calls (indeed, it is the same literal that is set to the member variable a this class in the initialization block)
And secondly, the clever method clever longer than normal . This is because additional steps are required to retrieve a property from the class.
So, the moral of this story is that in 99% of cases Java does everything right, and there is no need to try to be smart ;-) (and javap is a really cool tool when you want to know exactly what is going on)
source share