编译器在内部将该短语 ("x = "+x) 转换为 StringBuilder,并使用 .append(int) 将整数“添加”到字符串中。
为了超越实际的“Java 如何做到这一点”,我将听取 Stephen 的建议并给出理论。从概念上讲,连接中的每个值首先转换为字符串,然后连接。 Null 被连接为单词“null”。
来自Java Language Specification:
15.18.1.1 字符串转换
任何类型都可以通过字符串转换转换为String类型。一个值
原始类型 T 的 x 首先被转换为参考值,就像通过
将其作为适当的类实例创建的参数
表达式:
如果 T 是布尔值,则使用 new Boolean(x)。如果 T 是 char,则使用 new
字符(x)。如果 T 是 byte、short 或 int,则使用 new Integer(x)。如果
T 很长,然后使用 new Long(x)。如果 T 是浮点数,则使用 new Float(x)。
如果 T 为 double,则使用 new Double(x)。然后这个参考值
通过字符串转换转换为String类型。现在仅供参考
值需要考虑。如果引用为空,则为
转换为字符串“null”(四个 ASCII 字符 n、u、l、l)。
否则,转换就像通过调用
不带参数的被引用对象的 toString 方法;但如果
调用 toString 方法的结果为 null,则字符串“null”
改为使用。
toString 方法由原始类 Object 定义;许多
类覆盖它,特别是 Boolean、Character、Integer、Long、Float、
双精度和字符串。
15.18.1.2 字符串拼接的优化
实现可以选择执行转换和连接
一步避免创建然后丢弃中间体
字符串对象。提高重复字符串的性能
连接,Java 编译器可以使用 StringBuffer 类或
减少中间字符串对象数量的类似技术
通过评估表达式创建的。对于原始类型,
实现还可以优化包装器的创建
对象通过直接从原始类型转换为字符串。
优化后的版本实际上不会先进行完整的字符串转换。
这是编译器使用的优化版本的一个很好的说明,尽管没有转换原语,您可以在其中看到编译器在后台将内容更改为 StringBuilder:
http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/
这个java代码:
public static void main(String[] args) {
String cip = "cip";
String ciop = "ciop";
String plus = cip + ciop;
String build = new StringBuilder(cip).append(ciop).toString();
}
生成这个 - 看看这两种连接样式如何导致相同的字节码:
L0
LINENUMBER 23 L0
LDC "cip"
ASTORE 1
L1
LINENUMBER 24 L1
LDC "ciop"
ASTORE 2
// cip + ciop
L2
LINENUMBER 25 L2
NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 3
// new StringBuilder(cip).append(ciop).toString()
L3
LINENUMBER 26 L3
NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 4
L4
LINENUMBER 27 L4
RETURN
编译器已将“cip+ciop”转换为“new StringBuilder(cip).append(ciop).toString()”。换句话说,“+”实际上是更冗长的 StringBuilder 习语的简写。