+ Java 中字符串的运算符

发布于 2024-08-22 09:33:39 字数 290 浏览 11 评论 0原文

几分钟前我看到了这个问题,并决定在java String类中查看一下如果 + 运算符有一些重载。

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

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

在哪里实现的?

I saw this question a few minutes ago, and decided to take a look in the java String class to check if there was some overloading for the + operator.

I couldn't find anything, but I know I can do this

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

Where's that implemented?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

牵你手 2024-08-29 09:33:39

来自 精细手册

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

请参见 JLS 中的字符串连接

From the Fine Manual:

The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method. String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java. For additional information on string concatenation and conversion, see Gosling, Joy, and Steele, The Java Language Specification.

See String Concatenation in the JLS.

惟欲睡 2024-08-29 09:33:39

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

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

所以,就像我说的那样。

The compiler treats your code as if you had written something like:

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

Edit: Any reference? Well, if I compile and decompile the OP's code, I get this:

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

So, it's like I said.

新一帅帅 2024-08-29 09:33:39

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

我想补充一点,每个人都应该在某个时候看看String和append的源代码,它很漂亮感人的。

我相信这可以归结为:

"a"+"b"+"c"

=

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

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

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

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

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

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

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

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

Most of the answers here are correct (it's handled by the compiler, + is converted to .append()...)

I wanted to add that everyone should take a look at the source code for String and append at some point, it's pretty impressive.

I believe it came down to something like:

"a"+"b"+"c"

=

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

But then some magic happens. This turns into:

  • Create a string array of length 3
  • copy a into the first position.
  • copy b into the second
  • copy c into the third

Whereas most people believe that it will create a 2 character array with "ab", and then throw it away when it creates a three character array with "abc". It actually understands that it's being chained and does some manipulation outside what you would assume if these were simple library calls.

There is also a trick where if you have the string "abc" and you ask for a substring that turns out to be "bc", they CAN share the exact same underlying array. You'll notice that there is a start position, end position and "shared" flag.

In fact, if it's not shared, it's possible for it to extend the length of a string array and copy the new characters in when appending.

Now I'm just being confusing. Read the source code--it's fairly cool.

Very Late Edit:
The part about sharing the underlying array isn't quite true any more. They had to de-optimize String a little because people were downloading giant strings, taking a tiny sub-string and keeping it. This was holding the entire underlying array in storage, it couldn't be GC'd until all sub-references were dropped.

忘羡 2024-08-29 09:33:39

它由编译器处理。

It is handled by the compiler.

悲欢浪云 2024-08-29 09:33:39

这是语言规范。

15.18.1 字符串连接运算符 +

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

This is special behavior documented in the language specification.

15.18.1 String Concatenation Operator +

If only one operand expression is of
type String, then string conversion is
performed on the other operand to
produce a string at run time. The
result is a reference to a String
object (newly created, unless the
expression is a compile-time constant
expression (§15.28))that is the
concatenation of the two operand
strings. The characters of the
left-hand operand precede the
characters of the right-hand operand
in the newly created string. If an
operand of type String is null, then
the string "null" is used instead of
that operand.

冷弦 2024-08-29 09:33:39

这是在语言层面完成的。 Java 语言规范 对于什么字符串非常具体添加必须做

It's done at the language level. The Java Language Specification is very specific about what string addition must do.

我乃一代侩神 2024-08-29 09:33:39

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

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

String is defined as a standard type just like int, double, float, etc. on compiler level. Essentially, all compilers have operator overloading. Operator overloading is not defined for Developers (unlike in C++).

Interestingly enough: This question was logged as a bug: https://bugs.java.com/bugdatabase/view_bug?bug_id=4905919

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文