在java中使用null进行类型转换时没有异常

Posted

技术标签:

【中文标题】在java中使用null进行类型转换时没有异常【英文标题】:No Exception while type casting with a null in java 【发布时间】:2013-09-14 10:32:27 【问题描述】:
String x = (String) null;

为什么这个说法没有例外?

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

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

【问题讨论】:

你在说什么异常,编译器? 【参考方案1】:

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

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

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

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

对于您的其他困惑,如果不是特殊情况,对空对象调用任何方法都应该引发空指针异常。

【讨论】:

@JunedAhsan 什么特殊情况会导致它不抛出 NPE? @Trengot 检查下面彼得回答中提到的一项。【参考方案2】:

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

顺便说一句,有一个棘手的情况,您可以在 null 值上调用静态方法。

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

【讨论】:

哇。如果被问到,我会 100% 确定它会抛出异常。确实是一个棘手的案例。 @Magnilex:当然!这是一个典型的 OCPJP 考试技巧题。 这不是因为字节码中的编译器将其“优化”为t.yield() -> Thread.yeld()吗?类似于 final int i = 1; while (i == 1) 如何优化为 while(true) @SGal 更好,因为第二个优化是 AFAIK 不是强制性的,而第一个是。【参考方案3】:

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

【讨论】:

谢谢!这篇关于将 null 分配给引用变量的说明真的很有帮助!【参考方案4】:

在方法重载的以下构造中需要强制转换 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 输入测试它的行为。不过,很高兴知道,在找到你的答案之前,我正要写一个类似的答案。 有趣的事实:l instanceof Longs instanceof String 在这些情况下会返回 false【参考方案5】:

Println(Object) 使用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);

【讨论】:

【参考方案6】:

这里很多答案已经提到了

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

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

我想知道它是在哪里指定的,并查阅了 Java 规范:

The null reference can always be assigned or cast to any reference type (§5.2, §5.3, §5.5).

If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l).

【讨论】:

【参考方案7】:

正如其他人所写,您可以将 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】:

Print:

打印一个对象。 String.valueOf(Object) 方法产生的字符串被翻译成字节

ValueOf:

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

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

【讨论】:

【参考方案9】:

这在使用不明确的方法时非常方便。例如: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)

【讨论】:

【参考方案10】:

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

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

如果 memberHashMap.get("Name") 返回 null,您仍然希望上面的方法返回 null 而不会引发异常。不管是什么类,null就是null。

【讨论】:

以上是关于在java中使用null进行类型转换时没有异常的主要内容,如果未能解决你的问题,请参考以下文章

null 不能强制转换为非 null 类型 kotlin.String NullPointer 异常

面试准备-Java知识

致命异常 java.lang.NullPointerException: null 不能转换为非 null 类型 kotlin.String

JAVA中对null进行强制类型转换(null可以强转为任意对象,并执行对象的静态方法)

Flutter 未处理的异常:类型“Null”不是类型转换中“List<dynamic>”类型的子类型

Java异常