当String是类时,为什么在Java中可以使用+运算符添加String?在String.java代码中,我没有找到该操作符的任何实现。这个概念是否违反了面向对象?
String.java
让我们看一下下面的Java简单表达式
int x=15; String temp="x = "+x;
编译器"x = "+x;在StringBuilder内部进行转换,并用于.append(int)将整数“添加”到字符串中。
"x = "+x;
StringBuilder
.append(int)
5.1.11。字符串转换
可以通过字符串转换将任何类型转换为String类型。
首先将原始类型T的值x转换为参考值,就像通过将其作为适当的类实例创建表达式的参数(第15.9节):
现在只需要考虑参考值:
有关字符串转换上下文的详细信息,请参见§5.4。
15.18.1。
字符串连接的优化: 实现可以选择一步执行转换和连接,以避免创建然后丢弃中间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习惯用法的简写形式。