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操作这样的基本事情是强制性的。 但是,运算符超载会增加复杂性。