在 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
Concatenating null strings in Java
提问by yavoh
Why does the following work? I would expect a NullPointerException
to 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 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.
StringBuilder
所有处理 null的 append 方法都很好。在这种情况下,因为null
是第一个参数,String.valueOf()
而是调用,因为 StringBuilder 没有接受任何任意引用类型的构造函数。
If you were to have done s = "hello" + s
instead, 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 null
arguments.
append 方法可以处理null
参数。
回答by wkl
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.
这是在 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:
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”代替该操作数。