Answers:
让我们看一下下面的Java简单表达式
int x=15;
String temp="x = "+x;
编译器"x = "+x;
在StringBuilder
内部进行转换,并用于.append(int)
将整数“添加”到字符串。
可以通过字符串转换将任何类型转换为String类型。
首先将原始类型T的值x转换为参考值,就像通过将其作为适当的类实例创建表达式的参数(第15.9节):
- 如果T为布尔值,则使用新的Boolean(x)。
- 如果T为char,则使用新的Character(x)。
- 如果T为byte,short或int,则使用新的Integer(x)。
- 如果T长,则使用新的Long(x)。
- 如果T为float,则使用新的Float(x)。
- 如果T为double,则使用新的Double(x)。
然后,通过字符串转换将该参考值转换为String类型。
现在只需要考虑参考值:
- 如果引用为空,则将其转换为字符串“ null”(四个ASCII字符n,u,l,l)。
- 否则,转换的执行就好像是通过调用不带参数的引用对象的toString方法进行的;但是,如果调用toString方法的结果为null,则使用字符串“ null”。
toString方法由原始类Object(第4.3.2节)定义。许多类都覆盖它,特别是布尔,字符,整数,长整型,浮点型,双精度和字符串。
有关字符串转换上下文的详细信息,请参见§5.4。
字符串连接的优化: 实现可以选择一步执行转换和连接,以避免创建然后丢弃中间String对象。为了提高重复字符串连接的性能,Java编译器可以使用StringBuffer类或类似的技术来减少通过对表达式求值而创建的中间String对象的数量。
对于基本类型,实现还可以通过直接从基本类型转换为字符串来优化包装对象的创建。
优化版本实际上不会先进行完全包装的String转换。
这是编译器使用的优化版本的一个很好的说明,尽管没有转换原语,但您可以在其中看到编译器在后台将事物更改为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
习惯用法的简写形式。
它是Java编译器功能,用于检查运算+
符的操作数。并根据操作数生成字节码:
这就是Java规范所说的:
运算符+和
-
称为加法运算符。AdditiveExpression:MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression-MultiplicativeExpression加法运算符具有相同的优先级,并且在语法上是左关联的(它们的组从左到右)。如果
+
运算符的任何一个操作数的类型为String
,则该操作为字符串连接。否则,运算
+
符的每个操作数的类型必须是可转换(第5.1.8节)为原始数字类型的类型,否则会发生编译时错误。在每种情况下,二进制
-
运算符的每个操作数的类型都必须是可转换(第5.1.8节)为原始数值类型的类型,否则会发生编译时错误。
首先(+)超载而不是被覆盖
Java语言为字符串连接运算符(+)提供了特殊支持,该运算符已被Java Strings对象重载。
如果左侧操作数为String,则它可以作为串联。
如果左侧操作数为Integer,则用作加法运算符
int
,然后应用Java的常规规则。
Java语言为字符串连接运算符(+)以及将其他对象转换为字符串提供了特殊支持。字符串连接是通过StringBuilder
(或StringBuffer
)类及其append
方法实现的。
+
)运算符是Java的语言功能。