【问题标题】:java: throws RuntimeException [duplicate]java:抛出RuntimeException [重复]
【发布时间】:2014-04-10 18:42:34
【问题描述】:

下面这一项如何正确?我希望编译器告诉我使用throws Exceptionthrows RuntimeException

public void method1() throws NullPointerException { 

        throw new RuntimeException();
    }

为什么我认为它不正确 -> 因为 NPE 是 RTE,但 RTE 不是 NPE

这是正确的吗?我希望编译器告诉我使用throws Exceptionthrows RuntimeExceptionthrows NumberFormatException

public void method2() throws NullPointerException { 


    throw new NumberFormatException();
}


public void method3() throws Exception { // this is fine, as expected

        throw new RuntimeException();
    }


    public void method4() throws RuntimeException { // this is fine, as expected

        throw new NullPointerException();
    }

    public void method5() throws Exception { // this is fine, as expected

        throw new NullPointerException(); 
    }

答案:

对于 RTE,即使你没有在方法中添加 throws 子句,编译器也不会说什么

public void method6()  { // no compile time errors!!

        throw new NullPointerException(); 
    }

但是当我们明确地说 'throw new NullPointerException();' 时,为什么编译器会忽略它? 等同于'throw new SQLException();' 它不会在运行时抛出,说某个对象被评估为 null,并在该 null 对象上调用了一个操作。 通常一个函数必须声明它可以抛出的所有异常,但是 RTE 会绕过它!

RTE 是未经检查的异常。但是当你说 throw new RTE 时,仍然没有选中?!

问题 - 这不是缺陷吗?或者请纠正我理解为什么会这样

  • 更新:

请注意,这个问题不是关于已检查异常和未检查异常之间的区别。 问题不在于任何类型的异常或错误之间的区别。

问题是为什么不处理显式标记的 RunTimeException,或者不强制编译器处理它。

例如:

public void methodA() { // methodA is not forced to handle the exception.
        methodB(); 
    }

    public void methodB() throws RuntimeException {

    }

【问题讨论】:

  • 谢谢,有很多信息,我只介绍了一些。但是此刻,我的脑海中浮现的是——为什么显式抛出的 RTE 在 Java 中被归类为未经检查的异常?
  • 不要将 unchecked 解读为编译器看不到的内容。 unchecked 仅仅意味着它不必被处理。
  • 因为它们就是这样设计的。
  • 这太宽泛了,无法在这里回答。如果你真的有兴趣,网上有很多关于它的争论。

标签: java


【解决方案1】:

你误会了。

检查的异常是在编译时检查的异常(因此它们的名字)。因此,如果您有抛出异常 BarException 的方法 doFoo,则必须声明该方法抛出 BarException:

void doFoo() throws BarException { }

未经检查的异常是编译器不检查的异常,所以你不必声明你抛出它们

throw new Exception() 只会抛出一个已检查异常的新实例,或者在RuntimeException 的情况下未检查。仅当您使用 throw 子句实际抛出已检查异常时才会考虑检查因素。

至于它是否是一个缺陷,现在这是一个自以为是的话题。使用抛出大量未经检查的异常而不记录它们抛出这些异常的 API 往往是相当烦人的。但是,有时可能会根据应用程序的独特运行时状态发生异常,在这种情况下,您无法声明可以抛出某个已检查的异常,这就是运行时异常大放异彩的地方(例如NullPointerException

【讨论】:

  • 谢谢,事实上我并不热衷于它是什么,我更想了解这种规范背后的原因。
  • @prash 需要未经检查的异常的原因...它们被定义为运行时发生的异常。我不能给你一个明确的工程决策(只有 Oracle 工程师可以)这是它背后的......但我怀疑这是因为某些异常只能在运行时发生,比如空指针,所以未经检查的异常是完全必要的。但是,检查可能是保护开发人员免受与异常相关的愚蠢问题的设计决策……Java 还提供了其他东西的编译器强制执行(例如 @overload 标记)。
  • 感谢您提供这些详细信息。事实上,我同意我们需要未经检查的异常,例如 NullPointerException、ArithmeticException 等在运行时发生,在执行期间。我的问题是当我们明确抛出一个新的 RuntimeException 时,比如throw new RunTimeException()throws RunTimeException,情况就不同了。这与您写的 throw new SQLException 类似。
  • @prash 所以你想知道为什么如果你用throws 明确声明未经检查的异常,java 编译器不会检查这些异常是否被捕获?好吧,是的,如果我们只需将未检查的异常添加到throws 子句中,就可以将它们转换为已检查的异常,这将是很酷且非常有用的。您的问题的答案是 java 编译器 unconditionally 不检查未经检查的异常。将未经检查的异常添加到 throw 子句实际上并没有在编译器级别执行任何操作,但是当您知道某些 RuntimeExceptions 是预期的时,这是一种很好的做法。
  • 今天看我的问题......我当时是不是很倾倒没有意识到我怎么能期望编译器给出关于 UNCHECKED 异常的提示?我的错 !!大声笑
【解决方案2】:

我想我理解了这个问题,您想知道您在方法的 throws 子句中包含的任何异常都不会被视为已检查是否属于设计缺陷。

检查异常的核心前提是,我们可以在抛出异常的地方判断是否有人想要处理这个异常。没有任何考虑是否应将 NullPointerException 视为在某些情况下检查但在其他情况下不检查,其想法是它始终是一回事。此外,如果要在最初包含此内容,则在截止日期紧迫的情况下要编写更多代码,之后对此进行更改将意味着破坏现有的用户代码。所以这可能就是 Java 没有该功能的原因。

【讨论】:

  • 是的,您对我的问题的理解是正确的。不仅在 throws 子句中,而且当我们明确地说 throw new RunTimeException() 时也是如此。
  • 这个答案也是正确的,因为它清楚地解决了我的具体问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
  • 2015-01-25
  • 2023-03-24
  • 2018-07-10
  • 2011-10-02
  • 2012-11-23
相关资源
最近更新 更多