Java中的字符串+运算符

几分钟前我看到了这个问题 ,并决定查看java String类来检查+运算符是否有一些重载。

我找不到任何东西,但我知道我能做到这一点

 String ab = "ab"; String cd = "cd"; String both = ab + cd; //both = "abcd" 

实施的地方在哪里?

从精细手册 :

Java语言为字符串连接运算符(+)提供特殊支持,并为其他对象转换为字符串。 字符串连接是通过StringBuilder (或StringBuffer )类及其append方法实现的。 字符串转换是通过方法toString实现的,由Object定义并由Java中的所有类inheritance。 有关字符串连接和转换的其他信息,请参阅Gosling,Joy和Steele, Java语言规范

请参阅JLS中的字符串连接 。

编译器将您的代码视为您编写的代码:

 String both = new StringBuilder().append(ab).append(cd).toString(); 

编辑:任何参考? 好吧,如果我编译并反编译OP的代码,我得到这个:

 0: ldc #2; //String ab 2: astore_1 3: ldc #3; //String cd 5: astore_2 6: new #4; //class java/lang/StringBuilder 9: dup 10: invokespecial #5; //Method java/lang/StringBuilder."":()V 13: aload_1 14: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 17: aload_2 18: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 21: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 24: astore_3 25: return 

所以,就像我说的那样。

它由编译器处理。

这是语言规范中记录的特殊行为。

15.18.1字符串连接运算符+

如果只有一个操作数表达式是String类型,则在另一个操作数上执行字符串转换以在运行时生成字符串。 结果是对String对象的引用(新创建,除非表达式是编译时常量表达式(第15.28节)),它是两个操作数字符串的串联。 左侧操作数的字符位于新创建的字符串中右侧操作数的字符之前。 如果String类型的操作数为null,则使用字符串“null”而不是该操作数。

这里的大多数答案都是正确的(它由编译器处理,+转换为.append()……)

我想补充一点,每个人都应该看看String的源代码,并在某些时候附加,这非常令人印象深刻。

我相信它归结为:

 "a"+"b"+"c" 

=

 new String().append("a").append("b").append("c") 

但后来发生了一些魔术。 这变成了:

  • 创建一个长度为3的字符串数组
  • 将a复制到第一个位置。
  • 将b复制到第二个
  • 将c复制到第三个

虽然大多数人认为它会创建“ab”,然后在创建“abc”时抛弃它。 它实际上知道它被链接并进行一些操作。

还有一个技巧,如果你有字符串“abc”,并且你要求一个子串,结果是“bc”,他们可以共享完全相同的底层数组。 您会注意到有一个起始位置,结束位置和“共享”标志。

事实上,如果没有共享,它可以扩展字符串的长度并复制其他字符串。

现在我只是在困惑。 阅读源代码 – 它相当酷。

它是在语言层面完成的。 Java语言规范非常具体地说明了添加字符串必须做什么 。

String在编译器级别上被定义为标准类型,就像int,double,float等。 基本上,所有编译器都有运算符重载。 未为开发人员定义运算符重载(与C ++不同)。

有趣的是:这个问题被记录为一个错误: http : //bugs.sun.com/view_bug.do?video_id = 4905919