+运算符[重复]

问题描述 投票:0回答:7

几分钟前我看到这个问题,并决定看一下java String类以检查

+
运算符是否有一些重载。

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

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

在哪里实施?

java string operator-overloading string-concatenation
7个回答
14
投票

来自精品手册

Java 语言对字符串连接运算符(+)以及其他对象到字符串的转换提供了特殊支持。字符串连接是通过

StringBuilder
(或
StringBuffer
)类及其
append
方法实现的。字符串转换是通过toString方法实现的,该方法由Object定义,Java中所有类都继承。有关字符串连接和转换的其他信息,请参阅 Gosling、Joy 和 Steele,Java 语言规范

参见 JLS 中的 String Concatenation


9
投票

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

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

所以,就像我说的那样。


5
投票

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

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

我相信它归结为:

"a"+"b"+"c"

=

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

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

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

而大多数人认为它会创建一个带有“ab”的2字符数组,然后在创建带有“abc”的三字符数组时将其丢弃。它实际上理解它正在被链接,并在你假设这些是简单的库调用的情况下进行一些操作。

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

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

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

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


2
投票

由编译器处理。


2
投票

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

15.18.1 字符串连接运算符 +

如果只有一个操作数表达式是 类型String,则字符串转换为 对另一个操作数执行 在运行时产生一个字符串。这 结果是对字符串的引用 对象(新创建的,除非 表达式是编译时常量 表达式 (§15.28)) 即 两个操作数的连接 字符串。人物的 左手操作数先于 右操作数的字符 在新创建的字符串中。如果 String 类型的操作数为 null,则 使用字符串“null”代替 那个操作数。


0
投票

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


0
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.