在 Java 中连接空字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4260723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 15:07:15  来源:igfitidea点击:

Concatenating null strings in Java

javastringconcatenationstring-concatenation

提问by yavoh

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

为什么下面的工作?我希望 aNullPointerException被抛出。

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

采纳答案by Mark Peters

Why mustit work?

为什么一定要工作?

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

JLS 5,第15.18.1.1节JLS 8§15.18.1 “字符串连接运算符+” ,导致JLS 8,§5.1.11 “字符串转换”,要求该操作无故障成功:

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

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

Howdoes 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)

(您可以自己使用javap -c

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

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

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

如果您改为这样做s = "hello" + s,则等效代码将是:

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

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

在这种情况下, append 方法接受 null然后将其委托给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:

注意:字符串连接实际上是编译器决定执行哪些优化的少数地方之一。因此,“完全等效”的代码可能因编译器而异。JLS 第 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.

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

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

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

回答by Roland Illig

The second line is transformed to the following code:

第二行转化为如下代码:

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

The append methods can handle nullarguments.

append 方法可以处理null参数。

回答by wkl

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

这是在 Java API 的String.valueOf(Object)方法中指定的行为。当您进行连接时,valueOf用于获取String表示。如果 Object is null,则有一种特殊情况,在这种情况下使用字符串"null"

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.

public static String valueOf(Object obj)

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

参数: obj - 一个对象。

返回:

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

回答by krico

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

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

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

And I think what you want to do is:

我认为你想做的是:

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

回答by Jonathon Faust

See section 5.4and 15.18of the Java Language specification:

请参阅Java 语言规范的第5.415.18节:

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.

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