8

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

我找不到任何东西,但我知道我可以做到

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

这是在哪里实现的?

4

7 回答 7

13

来自精细手册

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

请参阅JLS 中的字符串连接

于 2010-02-24T18:34:10.323 回答
8

编译器将您的代码视为您编写了类似的内容:

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."<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

所以,就像我说的那样。

于 2010-02-24T18:35:48.137 回答
3

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

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

我相信它归结为:

"a"+"b"+"c"

=

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

但随后发生了一些神奇的事情。这变成:

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

而大多数人认为它会创建“ab”,然后在创建“abc”时将其丢弃。它实际上了解它被链接并进行了一些操作。

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

事实上,如果它不共享,它可能会扩展字符串的长度并将其他字符串复制进去。

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

于 2010-02-24T18:44:36.917 回答
2

它由编译器处理。

于 2010-02-24T18:33:02.433 回答
2

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

15.18.1 字符串连接运算符 +

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

于 2010-02-24T18:35:47.903 回答
0

它是在语言级别完成的。Java 语言规范对字符串添加必须执行的操作非常具体

于 2010-02-24T18:35:09.247 回答
0

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

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

于 2010-02-24T18:40:57.627 回答