String x = (String) null;
为什么这个语句中没有异常?
String x = null;
System.out.println(x);
它打印出 null
。但是 .toString()
方法应该抛出空指针异常。
String x = (String) null;
为什么这个语句中没有异常?
String x = null;
System.out.println(x);
它打印出 null
。但是 .toString()
方法应该抛出空指针异常。
您可以将null
强制转换为任何引用类型,而不会引发任何异常。
println
方法不会抛出null指针异常,因为它首先检查对象是否为空。如果为空,则只打印字符串"null"
。否则,它会调用该对象的toString
方法。
添加更多细节: 内部的打印方法在输入对象上调用String.valueOf(object)
方法。在valueOf
方法中,这个检查有助于避免空指针异常:
return (obj == null) ? "null" : obj.toString();
针对您的疑惑,调用空对象上的任何方法应该会抛出一个空指针异常,如果不是特殊情况的话。
您可以将null
转换为任何引用类型。您还可以调用处理null
作为参数的方法,例如System.out.println(Object)
,但您不能引用null
值并调用它的方法。
顺便说一下,有一个棘手的情况,其中似乎可以在null
值上调用静态方法。
Thread t = null;
t.yield(); // Calls static method Thread.yield() so this runs fine.
t.yield() -> Thread.yeld()
进行“优化”吗?这类似于final int i = 1; while (i == 1)
被优化为while(true)
的方式。 - SGal这是设计上的考虑。你可以将 null
转换为任何引用类型,否则你将无法将其赋值给引用变量。
在下面这种方法重载的情况下,强制转换 null 值是必需的。如果将 null 传递给这些重载方法,则编译器不知道如何消除歧义,因此我们需要在这些情况下对 null 进行类型转换。
class A {
public void foo(Long l) {
// do something with l
}
public void foo(String s) {
// do something with s
}
}
new A().foo((String)null);
new A().foo((Long)null);
否则你将无法调用所需的方法。String bar = null;
将null
值转换为String
。到目前为止,我只需要在一个测试中显式地转换null,其中一个方法被重载并且我想要测试其对null输入的行为。不过,知道这一点还是很好的,因为我正准备写一个类似的答案,然后发现了你的答案。 - Vlasecl instanceof Long
和 s instanceof String
将返回 false
。 - Attila TanyiPrintln(Object)
uses String.valueOf()
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Print(String)
进行空值检查。
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
这里已经有很多答案提到:
你可以将null转换为任何引用类型
和
如果参数为null,则字符串等于“null”
我想知道这是在哪里规定的,于是查阅了Java规范:
这种语言特性在这种情况下非常方便。
public String getName() {
return (String) memberHashMap.get("Name");
}
正如其他人所写,你可以将null转换为任何类型。通常情况下,你不需要这样做,你可以编写:
String nullString = null;
不需要添加转换。
但是有时候这样的转换也是有意义的:
a) 如果你想要确保调用一个特定的方法,比如:
void foo(String bar) { ... }
void foo(Object bar) { ... }
如果您输入的话,这会有所不同。
foo((String) null) vs. foo(null)
b) 如果您打算使用IDE生成代码;例如,我通常编写单元测试如下:
@Test(expected=NullPointerException.class)
public testCtorWithNullWhatever() {
new MyClassUnderTest((Whatever) null);
}
我正在进行TDD,这意味着类“MyClassUnderTest”可能还不存在。通过编写该代码,我可以使用我的IDE首先生成新类;然后生成一个接受“Whatever”参数的构造函数“开箱即用”-IDE可以根据我的测试推断构造函数应该正好接受一个类型为Whatever的参数。
当使用可能会产生歧义的方法时,这非常方便。例如:JDialog具有以下签名的构造函数:
JDialog(Frame, String, boolean, GraphicsConfiguration)
JDialog(Dialog, String, boolean, GraphicsConfiguration)
我需要使用这个构造函数,因为我想设置GraphicsConfiguration,但是我没有这个对话框的父级,所以第一个参数应该是null。使用
JDialog(null, String, boolean, Graphicsconfiguration)
这里存在歧义,因此我可以通过将null转换为其中一个支持的类型来缩小调用范围:
JDialog((Frame) null, String, boolean, GraphicsConfiguration)