以下编译:
System.out.println("true" + null);
我假设是因为字符串的存在,也将“null”转换为字符串。
然而,由于这有效:
System.out.println(true);
似乎以下内容也会编译,因为显然“true”函数是一个字符串。
System.out.println(true + null);
但是,它没有编译。
任何人都可以解释一下吗?
答案 0 :(得分:2)
+
运算符适用于数字(int
,float
,double
)和String
s,但在这种情况下,您使用的是添加 boolean
和Object
(null
),这是错误的。
但是,因为这可行
System.out.println(true);
似乎以下内容也会编译,因为显然“true”函数是一个字符串。
System.out.println(true + null);
自System.out.println(boolean)
以来,以前的作品会将boolean
转换为String
。后者不会。
对null
为什么转换为"null"
而不会产生任何问题进行一些研究,因为:
null.toString()
由于显而易见的原因无法编译StringBuilder.append(null)
无法编译String.valueOf(null)
编译但在运行时抛出NullPointerException
看起来编译器直接使用null
,它会首先创建一个Object o
然后String s
变量并为其分配null
,然后使用String.valueOf(s)
}。所以,这段代码:
System.out.println("true" + null);
实际上是
System.out.println(new StringBuilder().append("true").append((Object)null).toString());
如果我们做反向:
System.out.println(null + "true");
这将成为:
System.out.println(new StringBuilder().append((Object)null).append("true").toString());
为了表明这既不是魔法也不是黑魔法,我只是写了一个简单的代码来复制这种情况:
public class TestNullString {
public static void main(String[] args) {
nullPlusString();
stringPlusNull();
}
public static void nullPlusString() {
System.out.println(null + "foo");
}
public static void stringPlusNull() {
System.out.println("foo" + null);
}
}
使用java TestNullString.java
编译该类,然后使用生成的javap -c TestNullString.class
对其进行反编译(由反编译器本身生成的注释,而不是我的):
Compiled from "TestNullString.java"
public class TestNullString {
public TestNullString();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #2 // Method nullPlusString:()V
3: invokestatic #3 // Method stringPlusNull:()V
6: return
public static void nullPlusString();
Code:
0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
3: new #5 // class java/lang/StringBuilder
6: dup
7: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
10: aconst_null
11: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
14: ldc #8 // String foo
16: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: return
public static void stringPlusNull();
Code:
0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
3: new #5 // class java/lang/StringBuilder
6: dup
7: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
10: ldc #8 // String foo
12: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: aconst_null
16: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
19: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: return
}
通过执行StringBuilder#append(Object)
,它显示:
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
String#valueOf(Object)
实施:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
这完全说明了为什么null
最终成为"null"
。
解释这一点的另一项努力是在这里完成的:Concatenating null strings in Java
答案 1 :(得分:1)
它无法编译,因为语句操作数true
和null
不适用于+
操作。适用的夫妇是:
new Integer(1) + new Integer(2)
.toString()
方法)。例如:"newObject().toString() + "cde"
。 "abc" + null
备注(感谢@Luiggi和@Sotirios):
String.valueOf(null)
将无法作为可能的操作数,因为它会抛出NullPointerException
... String.valueOf((Object) null)
将返回String
值"null"
答案 2 :(得分:1)
since apparently "true" functions as a string.
这个假设是错误的。它有效,因为你打电话
public void println(boolean x)
然而,
true + null
不是Java中的有效语句,因为您不能添加或附加布尔值和对象。
答案 3 :(得分:1)
答案 4 :(得分:0)
parens之间的语句在打印之前执行。问题不在于字符串转换,正如其他人所说,问题是
true + null
是一个没有意义的补充问题。
"true" + null
然而,不是添加 - 它是字符串连接。由于“true”是一个字符串,+
的含义从“添加”变为“连接”。
答案 5 :(得分:0)
如果是
System.out.println(true + null);
它尝试将null转换为boolean
,因为boolean只有false
和true
值,所以它不能转换,也不能编译。
如果是
System.out.println("true" + null);
null
已投放到字符串,因为String
可以有null
值(字符串是Object
)