Java中的String运算符

Sam*_*ijo 7 java string operator-overloading string-concatenation

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

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

String ab = "ab";
String cd = "cd";
String both = ab + cd; //both = "abcd"
Run Code Online (Sandbox Code Playgroud)

实施的地方在哪里?

Jos*_*Lee 12

精细手册:

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

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


Sea*_*ean 7

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

String both = new StringBuilder().append(ab).append(cd).toString();
Run Code Online (Sandbox Code Playgroud)

编辑:任何参考?好吧,如果我编译并反编译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."<init>":()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
Run Code Online (Sandbox Code Playgroud)

所以,就像我说的那样.


Bil*_*l K 5

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

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

我相信这可以归结为:

"a"+"b"+"c"
Run Code Online (Sandbox Code Playgroud)

=

new StringBuilder().append("a").append("b").append("c")
Run Code Online (Sandbox Code Playgroud)

但随后一些魔法发生了。这变成:

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

而大多数人认为它会创建一个包含“ab”的2字符数组,然后当它创建一个包含“abc”的三字符数组时将其丢弃。它实际上知道它正在被链接,并在您假设这些是简单的库调用时进行一些超出您假设的操作。

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

事实上,如果不共享,它可以扩展字符串数组的长度并在附加时复制新字符。

现在我只是感到困惑。阅读源代码——这相当酷。

非常晚的编辑:有关共享底层数组的部分不再完全正确。他们必须对字符串进行一些去优化,因为人们正在下载巨大的字符串,获取一个很小的子字符串并保留它。这将整个底层数组保存在存储中,在删除所有子引用之前无法对其进行 GC。

  • 没有`new String().append("a").append("b").append("c")`,而是`new StringBuilder().append("a").append("b) .append("c").toString()`。 *no-stringbuilder* 方式将是 `"a".concat("b").concat("c")`,这是低效的方式,因为你(但是当将 + 与编译时常量一起使用时,所有这些都已经由编译器完成了。) (3认同)