The big advantage of the variant A, return x + creditCard.substring(15, 19);
is that it is simple and clean and it works in all Java versions from 1
to 8
. In the case that its compiled form uses StringBuffer
, a simple recompile for Java 5 or newer will make it use StringBuilder
instead. This flexibility is lost when you work with either, StringBuffer
or StringBuilder
, manually.
The exact compiled form is not fixed. Since the semantic of the method String.substring
is not fixed by the Java Language Specification, compilers usually won’t touch this and compile it as an ordinary method invocation. The specification encourages compiler vendors to use StringBuilder
for string concatenation (the +
operator) whenever there is a benefit and most compilers will do so, even when there is no benefit. Here, both, x
and the result of substring
, are String
s so a simple String.concat
would be simpler but most compilers always use StringBuilder
, compiling variant A to the equivalent of
return new StringBuilder().append(x).append(creditCard.substring(15, 19)).toString();
.
Comparing this typical form with your variant B, we can conclude that variant B has two advantages performance-wise:
new StringBuilder(x)
initializes the StringBuilder
to a capacity of x.length()+16
which is sufficient for the entire operation, whereas the default capacity of new StringBuilder()
, typically used for variant A, is fixed to 16
characters which misses the mark here as we have a result of 19
characters, thus a reallocation and copying of the underlying character array will occur
sb.append(creditCard, 15, 19);
will copy the four characters without the need to create an intermediate String
representation of these characters. The expenses of the substring
operation differ depending on the implementation, e.g. in Oracle’s implementation there was a significant change with version 1.7.0_06
; starting with this version a substring requires a new char[]
array holding a copy of the affected character data as it doesn’t maintain a separate offset
and length
field
But note that all these differences of variant A and B only affect the formal description of the operation to perform. What will actually happen, is up to the JVM/JRE and usually the Hotspot optimizer knows a lot of string related operations and may fuse operations or elide intermediate string representations. Thus, the outcome regarding performance is rather unpredictable and may be affected by subtle changes to the implementation.
That’s why developers might stick to variant A which is, as said, simpler and more readable, and only care for performance once a profiler tells them that there is a performance problem that could be solved by dealing with Stringbuilder
manually.