在 Java 中连接空字符串

发布于 2024-10-04 01:15:12 字数 166 浏览 5 评论 0原文

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

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

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"

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

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

发布评论

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

评论(5

就是爱搞怪 2024-10-11 01:15:12

为什么它必须有效?

JLS 5,第 15.18 节.1.1 JLS 8 § 15.18.1“字符串连接运算符 +”,导致 JLS 8,§ 5.1.11“字符串转换”,要求此操作成功而不会失败:

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

它是如何工作的

我们来看看字节码!编译器获取您的代码:

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

并将其编译为字节码,就像您编写了这样的代码一样:

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

(您可以通过使用 javap -c)

StringBuilder 的追加方法全部处理空就好了。在本例中,由于 null 是第一个参数,因此会调用 String.valueOf(),因为 StringBuilder 没有采用任何任意引用类型的构造函数。

如果您改为执行 s = "hello" + s,则等效代码将是:

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

在本例中,append 方法采用 null 并then 将其委托给String.valueOf()

注意: 字符串连接实际上是编译器决定执行哪些优化的罕见位置之一。因此,“完全等效”的代码可能因编译器而异。 JLS 第 15.18 节允许此优化.1.2

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

我用来确定上面“等效代码”的编译器是 Eclipse 的编译器 ecj

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:

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

(You can do so yourself by using javap -c)

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.

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

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

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

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:

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.

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

素手挽清风 2024-10-11 01:15:12

请参阅 5.415.18

字符串转换仅适用于
二元 + 运算符的操作数当
参数之一是字符串。在
这个特殊情况,其他情况
+ 的参数被转换为
字符串,和一个新的字符串,它是
两个字符串的串联是
+ 的结果。字符串转换
中详细规定了
字符串的描述
连接+运算符。

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

See section 5.4 and 15.18 of the Java Language specification:

String conversion applies only to the
operands of the binary + operator when
one of the arguments is a String. In
this single special case, the other
argument to the + is converted to a
String, and a new String which is the
concatenation of the two strings is
the result of the +. String conversion
is specified in detail within the
description of the string
concatenation + operator.

and

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-10-11 01:15:12

第二行转换为以下代码:

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

append 方法可以处理 null 参数。

The second line is transformed to the following code:

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

The append methods can handle null arguments.

南汐寒笙箫 2024-10-11 01:15:12

您没有使用“null”,因此您不会收到异常。如果你想要 NullPointer,就做

String s = null;
s = s.toString() + "hello";

我认为你想做的是:

String s = "";
s = s + "hello";

You are not using the "null" and therefore you don't get the exception. If you want the NullPointer, just do

String s = null;
s = s.toString() + "hello";

And I think what you want to do is:

String s = "";
s = s + "hello";
聊慰 2024-10-11 01:15:12

这是 Java API 的 String.valueOf(Object) 方法。当您进行串联时,valueOf 用于获取String 表示形式。如果对象为 null,则有一种特殊情况,在这种情况下,将使用字符串 "null"

public static String valueOf(Object obj)

返回对象参数的字符串表示形式。

参数:
obj - 一个对象。

返回:

如果参数为 null,则字符串等于“null”;否则,返回 obj.toString() 的值。

This is behavior specified in the Java API's String.valueOf(Object) method. When you do concatenation, valueOf is used to get the String representation. There is a special case if the Object is null, in which case the string "null" is used.

public static String valueOf(Object obj)

Returns the string representation of the Object argument.

Parameters:
obj - an Object.

Returns:

if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.

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