在 Java 中连接空字符串 [英] Concatenating null strings in Java

查看:27
本文介绍了在 Java 中连接空字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么下面的方法有效?我希望抛出一个 NullPointerException.

Why does the following work? I would expect a NullPointerException to be thrown.

String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"

推荐答案

为什么必须有效?

JLS 5, 第 15.18.1.1 节 JLS 8 § 15.18.1字符串连接运算符 +",导致 JLS 8, § 5.1.11 字符串转换",要求此操作成功且不失败:

Why must it work?

The JLS 5, Section 15.18.1.1 JLS 8 § 15.18.1 "String Concatenation Operator +", leading to JLS 8, § 5.1.11 "String Conversion", requires this operation to succeed without failure:

...现在只需要考虑参考值.如果引用为空,则转换为字符串空"(四个ASCII字符n、u、l、l).否则,转换就像通过调用不带参数的引用对象的 toString 方法来执行一样;但如果调用 toString 方法的结果为 null,则使用字符串null"代替.

...Now only reference values need to be considered. If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l). Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.

它是如何工作的?

让我们看看字节码!编译器接受你的代码:

How does it work?

Let's look at the bytecode! The compiler takes your code:

String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"

并将其编译为字节码,就像您编写的那样:

and compiles it into bytecode as if you had instead written this:

String s = null;
s = new StringBuilder(String.valueOf(s)).append("hello").toString();
System.out.println(s); // prints "nullhello"

(您可以自己使用 javap -c)

StringBuilder 的 append 方法都可以很好地处理 null.在这种情况下,因为 null 是第一个参数,所以 String.valueOf() 被调用,因为 StringBuilder 没有接受任何任意引用类型的构造函数.

The append methods of StringBuilder all handle null just fine. In this case because null is the first argument, String.valueOf() is invoked instead since StringBuilder does not have a constructor that takes any arbitrary reference type.

如果你用 s = "hello" + s 代替,等效的代码是:

If you were to have done s = "hello" + s instead, the equivalent code would be:

s = new StringBuilder("hello").append(s).toString();

在这种情况下,append 方法接受 null,然后 then 将其委托给 String.valueOf().

where in this case the append method takes the null and then delegates it to String.valueOf().

注意: 字符串连接实际上是编译器决定执行哪些优化的少数地方之一.因此,完全等效"的代码可能因编译器而异.JLS 第 15.18 节允许此优化.1.2:

Note: String concatenation is actually one of the rare places where the compiler gets to decide which optimization(s) to perform. As such, the "exact equivalent" code may differ from compiler to compiler. This optimization is allowed by JLS, Section 15.18.1.2:

为了提高重复字符串连接的性能,Java 编译器可能会使用 StringBuffer 类或类似技术来减少通过评估表达式创建的中间 String 对象的数量.

To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.

我用来确定上面等效代码"的编译器是 Eclipse 的编译器,ecj.

The compiler I used to determine the "equivalent code" above was Eclipse's compiler, ecj.

这篇关于在 Java 中连接空字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆