【问题标题】:Why is "throw null" not creating a compilation error in Java?为什么“throw null”不会在 Java 中创建编译错误?
【发布时间】:2011-07-06 05:27:26
【问题描述】:
class ThrowNull {
    public static void main(String[] args) {
        throw null;
    }
}

我们知道 throw 的规则是 throw ThrowableInstance;,其中 ThrowableInstance 必须是 Throwable 类型的对象或 Throwable 的子类。

简单类型,例如 int 或 char,以及 non-Throwable 类,例如 String 和 Object,不能用作异常。 null 是一个特殊的 Java 字面量,它表示一个空值。

那么为什么throw null; 会在这段代码中编译呢?

【问题讨论】:

  • 为什么会导致编译时错误?
  • 虽然目前 Java 编译器本身并未将其标记为问题(除非语言规范在未来某个时间发生变化),但它显然是静态检查器(如“Sonar”)的候选者根除并指出给开发者。也许开发者想写“return null”...
  • 我们知道规则是调用String a() {return null}的结果必须是(子)类或String的对象。简单的类,如 Throwable 或 BigInteger 不能用作字符串。 Null 是一种特殊的 Java 文字,它表示一个空值。那为什么return null 没有产生任何编译时错误??????!!!我在这里暴露你的双重标准。为什么你抱怨throw null 而不是抱怨return null?因此,我不能赞成你的问题。采用双重标准的方式过于本土化。

标签: java exception-handling null


【解决方案1】:

根据language specificationthrow语句定义为:

throw Expression

如果Expression 的计算结果为null,则抛出NullPointerException。具体来说,

如果 Expression 的评估正常完成,产生 null 值,则创建并抛出 NullPointerException 类的实例 V' 而不是 @987654329 @。

由于NullPointerException 扩展了RuntimeException,它是一个未经检查的异常。这可以解释为什么这个构造没有报告编译时错误。

【讨论】:

  • 所以 null 会以某种方式转换为 NullPointer 异常,但是如果我抛出一个字符串或数字怎么办?我给出了运行时异常并说No exception of type String can be thrown; an exception type must be a subclass of Throwable 为什么会这样?
  • 这不是空的“以某种方式转换”为 NPE。语言规范说,当throw 获得空值时,它需要创建并抛出 NullPointerException。确实如此。规范说 throw 必须被赋予“1)一个引用类型的变量或值,该变量或值可分配给 Throwable 类型(第 5.2 节),或 2)空引用”。其他任何事情都会导致编译器错误。
  • 还不清楚您希望该语言做什么。 NullPointerException 通常在预期值但收到 null 时抛出(例如,参见 java.io.File 的构造函数)。但是,抛出任意对象并没有明显的 正确 行为。 (它会产生异常吗?哪个?选中还是未选中?或者你是否也希望捕获任意对象?你会catch(String s),还是catch("oops")?)让编译器拒绝不清楚的东西通常比有潜在的惊喜要好运行时的行为。
【解决方案2】:

编译器不会检查很多事情,它假定您做事情是有充分理由的,而它可能不知道。它确实试图防止的是开发人员常犯的错误。

可能有人认为这是一个很好的速记

throw new NullPointerException();

Integer i = null;
try {
    i.intValue();
} catch (NullPointerException npe) {
    System.err.println("Caught NPE");
    npe.printStackTrace();
}

try {
    throw null;
} catch (NullPointerException npe) {
    System.err.println("Caught NPE");
    npe.printStackTrace();
}

在 Java 6 更新 38 中打印

Caught NPE
java.lang.NullPointerException
    at Main.main(Main.java:9)

【讨论】:

  • @DanielWerner 所有异常和错误,甚至可以捕获 OutOfmemoryError 和 ThreadDeath。 ;) 看我的例子。
【解决方案3】:

我认为因为 Null 可以转换为任何类型的引用。所以在编译时,如果你抛出 null 而不是 throwable,这没什么错。

【讨论】:

  • 没错。您的返回字符串的方法可能返回 null。为什么字符串变量可以为空而 Throwable 变量不能? OP 绝对不是短视(x)就是双重标准。
  • 这听起来不错,但事实并非如此。查看接受的答案。
【解决方案4】:

在一般情况下,而不仅仅是扔。任何对象变量都可以赋值为空。所以我们可以看到 throw 并不是一个特例。应该是吗?也许。是否一致?是的。

【讨论】:

    猜你喜欢
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    • 2011-06-09
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    相关资源
    最近更新 更多