Kotlin - 字符串插值 $ 与使用加等于 += 连接

The*_*Boy 2 string string-concatenation string-interpolation kotlin

var name: String问题很简单:这两个版本(都已初始化和val someInt: Int)有什么区别?

name += " $someInt"

name = "$name $someInt"

我还读到String 插值$使用 StringBuilder,因此第二个代码应该优先于第一个代码(使用串联)?

Мих*_*аль 5

找到差异的最佳方法是查看生成的字节码(我将使用 Kotlin 1.4.10)。

生成的字节码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
Run Code Online (Sandbox Code Playgroud)

生成的字节码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
Run Code Online (Sandbox Code Playgroud)

结果几乎相同,但在第一种情况下有一个额外的SWAP操作,因为第一个append操作的参数太早加载到堆栈中(在StringBuilder创建之前,现在需要交换它们)。

长话短说

事实证明:

  1. StringBuilder在两种情况下都会创建
  2. 两种情况下都有 3 个附加(name、 空格 & )someInt
  3. 第二种稍微有效一些。