The problem is quite simple:
What is the difference between these 2 versions (both have initialized var name: String
and val someInt: Int
)?
name += " $someInt"
name = "$name $someInt"
I also read that the String interpolation $
uses a StringBuilder, so the second code should be preferred to the first one (which uses concatenation) ?
The best way to find the difference is to look at the generated bytecode (I will use Kotlin 1.4.10).
Bytecode generated for name += " $someInt"
:
ALOAD 0
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
SWAP
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
BIPUSH 32
INVOKEVIRTUAL java/lang/StringBuilder.append (C)Ljava/lang/StringBuilder;
ILOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 0
Bytecode generated for name = "$name $someInt"
:
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
ALOAD 0
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
BIPUSH 32
INVOKEVIRTUAL java/lang/StringBuilder.append (C)Ljava/lang/StringBuilder;
ILOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 0
Results are pretty much the same, but in the first case there is an extra SWAP
operation, cause argument for first append
operation was loaded onto stack too early (before StringBuilder
was created, and now they need to be swapped).
TL;DR
Turns out that:
StringBuilder
is created in both casesname
, whitespace & someInt
) in both cases