在 java 中使用 null 进行类型转换时没有例外

No Exception while type casting with a null in java

提问人:Vicky 提问时间:9/10/2013 最后编辑:anubhavaVicky 更新时间:2/1/2019 访问量:206826

问:

String x = (String) null;

为什么这句话没有例外?

String x = null;
System.out.println(x);

它打印 .但是方法应该抛出一个空指针异常。null.toString()

java nullpointerexception 类型转换运算符

评论

0赞 Sajan Chandran 9/10/2013
你在说什么例外,编译器?

答:

8赞 rocketboy 9/10/2013 #1

Println(Object)使用String.valueOf()

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

Print(String)执行 null 检查。

public void print(String s) {
    if (s == null) {
        s = "null";
    }
    write(s);
}
45赞 André Stannek 9/10/2013 #2

这是设计使然。可以强制转换为任何引用类型。否则,您将无法将其分配给引用变量。null

评论

1赞 Max 1/8/2020
谢谢!这个关于将 null 分配给引用变量的说明真的很有帮助!
385赞 Juned Ahsan 9/10/2013 #3

可以强制转换为任何引用类型,而不会出现任何异常。null

该方法不会引发 null 指针,因为它首先检查对象是否为 null。如果为 null,则它只打印字符串 。否则,它将调用该对象的方法。println"null"toString

添加更多详细信息:内部打印方法对输入对象调用方法。在方法中,此检查有助于避免空指针异常:String.valueOf(object)valueOf

return (obj == null) ? "null" : obj.toString();

为了避免混淆,如果不是特殊情况,对 null 对象调用任何方法都应该引发 null 指针异常。

评论

1赞 Holloway 11/25/2014
@JunedAhsan哪些特殊情况会导致它不抛出NPE?
0赞 Juned Ahsan 11/26/2014
@Trengot 检查下面彼得回答中提到的一个。
2赞 Jeroen Vannevel 9/10/2013 #4

打印

打印对象。String.valueOf(Object) 方法生成的字符串将转换为字节

ValueOf

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

当对象为 时,它只会返回一个值为“null”的字符串。null

163赞 Peter Lawrey 9/10/2013 #5

可以强制转换为任何引用类型。您还可以调用将 a 作为参数处理的方法,例如 ,但不能引用值并对其调用方法。nullnullSystem.out.println(Object)null

顺便说一句,有一种棘手的情况,似乎您可以对值调用静态方法。null

Thread t = null;
t.yield(); // Calls static method Thread.yield() so this runs fine.

评论

14赞 Magnilex 2/17/2015
哇。如果被问到,我会 100% 确定它会抛出异常。这确实是一个棘手的案例。
2赞 ccpizza 3/18/2016
@Magnilex:当然!这是一个典型的OCPJP考试技巧问题。
3赞 SGal 2/1/2018
这难道不是因为字节码中的编译器无论如何都会“优化”它吗?与如何优化类似t.yield() -> Thread.yeld()final int i = 1; while (i == 1)while(true)
0赞 Paul Stelian 11/30/2019
@SGal 它甚至更好,因为第二个优化是 AFAIK,而不是强制性的,而第一个是强制性的。
26赞 Mewel 1/24/2015 #6

以下构造需要转换 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);

否则,无法调用所需的方法。

评论

0赞 Vlasec 4/13/2016
在大多数情况下,强制转换是隐式的,例如 将值转换为 。到目前为止,我只需要在方法重载的测试中显式转换 null,并且我想使用 null 输入测试其行为。不过,很高兴知道,在我找到你的答案之前,我正要写一个类似的答案。String bar = null;nullString
0赞 Attila Tanyi 3/22/2018
有趣的事实:在这些情况下会返回。l instanceof Longs instanceof Stringfalse
2赞 Marten Jacobs 7/23/2015 #7

当使用本来会模棱两可的方法时,这非常方便。例如: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)
3赞 GhostCat 4/13/2016 #8

正如其他人所写的,你可以将 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 类型的参数。

8赞 Arigion 8/17/2017 #9

这里的许多答案已经提到

可以将 null 转换为任何引用类型

如果参数为 null,则字符串等于“null”

我想知道在哪里指定了它,并在 Java 规范中查找了它:

始终可以将 null 引用赋值或强制转换为任何引用类型(§5.2、§5.3、§5.5)。

如果引用为 null,则将其转换为字符串“null”(四个 ASCII 字符 n、u、l、l)。

4赞 Changgull Song 2/1/2019 #10

在这种情况下,此语言功能很方便。

public String getName() {
  return (String) memberHashMap.get("Name");
}

如果 memberHashMap.get(“Name”) 返回 null,您仍然希望上述方法返回 null 而不会引发异常。无论类是什么,null 都是 null。