Java源代码中的string“+”在哪里实现?
String
是Java中的特例。 这是一个类,我可以在源代码中查看,但它也有自己的中缀运算符+
,这似乎是StringBuilder
语法糖。
例如,
"Hello " + yourName;
可能成为
new StringBuilder().append("Hello ").append(yourName).toString();
在Java中没有用户定义的运算符,那么在String
指定的是哪里?
是否可以使用相同的机制来创build额外的运算符,如向量?
+
在java 编译器中实现。 编译器用 编译时常量或StringBuilder
代码replace String
+ String
。 请注意,这也适用于原语 。 即在编译期间int i=1+2
可以直接replace为int i=3
。
你可以检查规格。 编译器有它的实现,而不是Java源代码。
Java Language Specification- 15.18.1. String Concatenation Operator +
实现可以select一步执行转换和连接,以避免创build并丢弃中间的String对象。 为了提高重复string连接的性能,Java编译器可以使用StringBuffer类或类似技术来减less通过评估expression式创build的中间String对象的数量。
它显示了实现依赖于编译器的证据。
Java编译器具有+的实现。 Javadocs说:
Java语言为string连接运算符(+)提供特殊支持,并将其他对象转换为string。 string连接是通过StringBuilder(或StringBuffer)类及其附加方法实现的。 string转换通过toString方法实现,由Object定义并由Java中的所有类inheritance。 有关string连接和转换的更多信息,请参阅Gosling,Joy和Steele,Java语言规范。
你可以试试看这个:
public static void main(String[] args) { String s1 = "s1"; String s2 = "s2"; String s3 = s1 + s2; String s4 = new StringBuilder(s1).append(s2).toString(); }
上面的代码为+生成相同的字节码,当使用StringBuilder时:
L0 LINENUMBER 23 L0 LDC "s1" ASTORE 1 L1 LINENUMBER 24 L1 LDC "s2" ASTORE 2 // s3 = s1 + s2 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 // s4 = new StringBuilder(s1).append(s2).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
虽然目前大多数使用StringBuilder
链的Java编译器,但没有指定它总是以这种方式。 特别是有一个build议 ,在Java-9中用单一invokedynamic
调用来彻底改变这种情况,并引入新的metafactory,它将在运行时生成一个合适的MethodHandle
来执行连接。
至于语言,不,它不可扩展。 这是特定行为,没有其他类扩展+
运算符。
至于在哪里完成,请在以下文件中searchstring_add
(不是真正的JVM操作) :
-
运算符定义
-
代码生成器
至于为什么,Java应该是简单的,或者至less比C ++简单,像string操作这样的基本事情是强制性的。 但是,运算符超载会增加复杂性。