+;Java中字符串的运算符

+;Java中字符串的运算符,java,string,operator-overloading,string-concatenation,Java,String,Operator Overloading,String Concatenation,几分钟前我看到了,并决定查看一下java字符串类,以检查+操作符是否有一些重载 我什么也找不到,但我知道我能做到 String ab = "ab"; String cd = "cd"; String both = ab + cd; //both = "abcd" 在哪里实现的?它由编译器处理。来自: Java语言为字符串连接运算符(+)以及其他对象到字符串的转换提供了特殊支持。字符串连接是通过StringBuilder(或StringBuffer)类及其append方法实现的。字符串转换是通过

几分钟前我看到了,并决定查看一下java字符串类,以检查
+
操作符是否有一些重载

我什么也找不到,但我知道我能做到

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

在哪里实现的?

它由编译器处理。

来自:

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


请参见JLS中的。

这是在语言级别完成的。Java语言规范是。

这是中记录的特殊行为

15.18.1字符串连接运算符+

如果只有一个操作数表达式为 输入String,然后进行字符串转换 对要删除的另一个操作数执行 在运行时生成字符串。这个 结果是对字符串的引用 对象(新创建的,除非 表达式是编译时常量 表达式(§15.28)),即 两个操作数的并置 串。这本书的特点 左操作数位于 右操作数的字符 在新创建的字符串中。如果 字符串类型的操作数为null,则 使用字符串“null”代替 那个操作数


编译器将您的代码视为您编写了以下内容:

String both = new StringBuilder().append(ab).append(cd).toString();
"a"+"b"+"c"
编辑:有参考资料吗?如果我编译和反编译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
0:ldc#2//字符串ab
2:astore_1
3:最不发达国家3//字符串cd
5:astore_2
6:新#4//类java/lang/StringBuilder
9:dup
10:特别是#5//方法java/lang/StringBuilder。“”:()V
13:aload_1
14:invokevirtual#6//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17:aload_2
18:invokevirtual#6//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21:invokevirtual#7//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
24:astore_3
25:返回

就像我说的。

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


有趣的是:这个问题被记录为一个bug:

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

我想补充一点,每个人都应该看看String和append的源代码,这非常令人印象深刻

我相信这可以归结为:

String both = new StringBuilder().append(ab).append(cd).toString();
"a"+"b"+"c"
=

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

  • 创建长度为3的字符串数组
  • 将a复制到第一个位置
  • 将b复制到第二个
  • 将c复制到第三个
然而大多数人相信它会创造“ab”,当它创造“abc”时,就把它扔掉。它实际上知道它被锁起来了,并进行了一些操作

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

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


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

令人印象深刻的答案。你考虑过当老师吗?@Willi Schönborn:嗯,这是一个简单而正确的答案。当我写的时候,我没有时间写更多,当我回到电脑前,有很多答案更详细地解释了它。很抱歉,但我不认为复制其他答案有什么意义,如果你需要更多信息,我建议你阅读@Sean's和@jleedev's(是的,我的简历上有教学内容)。重点是:你的答案非常笼统,几乎可以回答约75%与java相关的问题。@Will Schönborn 75%的java问题都不是由编译器处理的。事实上,在大多数情况下,编译器只是将源代码编译成字节码。少数例外是字符串上的+运算符,以及一些结果是内在函数内联的情况。我的答案是第一个,唯一的目的是快速回答,在等待更完整的答案的同时,指出OP的正确方向。在开会之前,我有大约30秒的空闲时间,并将它们奉献给大家。如果您不喜欢,请访问hyphen网站或其他网站,或亲自构建一些代表,而不要抱怨。
StringBuilder
如果不需要同步,则应首选。@gpampara编译器知道如何使用StringBuilder。StringBuffer在引入StringBuilder之前在旧版本中使用。没有
新字符串().append(“a”).append(“b”).append(“c”)
,而是
新的StringBuilder().append(“a”).append(“b”).append(“c”).toString()
。没有StringBuilder的方式是
a.concat(“b”).concat(“c”)
,正如您所描述的,这是一种低效的方法。(但是,当将+与编译时常量一起使用时,所有这些都已由编译器完成。)