【问题标题】:Are multiply-thrown Exceptions checked or runtime?是检查多次抛出的异常还是运行时?
【发布时间】:2010-05-06 14:30:34
【问题描述】:

我有一个异常链,其中method1method2 抛出异常,而main 又向main 抛出异常。出于某种原因,编译器强迫我处理method2 中的错误,如果我不这样做,则将其标记为错误,表明这是一个已检查的异常。但是当同样的Exception 被进一步抛出到main 时,编译器允许我忽略它并且不显示任何错误。

method1 中的原始异常是 ParseException,已检查。但是该方法在标头中有一个通用的throws Exception 子句,并且将相同的对象抛出给具有相同throws Exception 子句的method2。这个异常何时以及如何失去被编译器检查/捕获的状态?

编辑澄清:

public void method1() throws Exception{
   // code that may generate ParseException
}

public void method2() throws Exception{
   method1(); //compiler error (if the throws clause is left out)
}

public static void main(String[] args){
   method2(); //ignored by compiler, even though the exception isn't caught or thrown or handled at all
}

编辑: 对不起大家,这个问题是基于一个错误......主要方法实际上有一个我错过的throws Exception子句。我已经删除了它,代码现在按预期运行。感谢大家的帮助!

【问题讨论】:

  • 你能澄清一下吗? method1 是否抛出“ParseException”,被 method2 和 main 视为“异常”?一些方法签名和 try-catch-throw 代码 sn-ps 会有所帮助。
  • ParseException 是自定义类吗?如果是这样,您是否也可以将其添加到您的示例代码中?
  • 您发布的代码不会按照编写的方式编译,因为 method1() 和 method2() 都需要是静态的才能被 main 调用。一旦将它们设为静态,编译错误就会出现在 main 中,因为它不处理或抛出检查的异常。
  • @ColinD - 是的,这段代码并不完全准确,只是想给出一个大致的想法。 method1 和 method2 实际上是对象方法,main 实例化一个对象并从该对象中调用它们
  • @Jarle Hansen - ParseException 不是自定义类。您可以查看 javadoc:java.sun.com/javase/6/docs/api/java/text/ParseException.html。当在Format 上调用parse 时,它经常被抛出。例如,请参阅DateFormat.parse(String)

标签: java exception runtime checked-exceptions


【解决方案1】:

是否检查异常完全取决于它是哪种异常:如果是RuntimeException或其子类,则不检查;否则,它是。 (是的,RuntimeExceptionException 的子类——这是 Java 库设计的失败之一,但不是最严重的。)

编译器检查的是方法签名。所以抛出的实际异常是无关紧要的(为此)。如果方法说throws Exception,那么你必须在你的方法中捕获Exception,或者声明方法throws Exception。方法应始终使用尽可能窄的 throws 子句——例如,不是 throws Exception 而是throws ParseException

(我说“不相关(出于此目的)”,因为当然,编译器会做的其他件事之一是检查您是否抛出未涵盖的已检查异常通过您的throws 子句。)

编辑 您在编辑中添加的代码将无法编译:1. 它正在调用没有实例的实例方法,并且 2. main 需要声明它会抛出 Exception

这段代码解决了其他问题,并且(正确地)证明了main 需要throws Exception 子句:

public class CheckTest
{
    public static final void main(String[] params)
    {
        new CheckTest().method2();
    }

    public void method1() throws Exception{
        throw new java.text.ParseException("foo", 2);
    }

    public void method2() throws Exception{
        this.method1();
    }
}

结果:

CheckTest.java:27: unreported exception java.lang.Exception; must be caught or declared to be thrown

                new CheckTest().method2();
                                       ^
1 error

【讨论】:

  • 那为什么 main 没处理好,method2 需要处理呢?
  • 哎呀!我才意识到我的错误。在 main 的标题中实际上有一个 throws Exception 子句......当我把它拿出来时,我期望出现的编译器错误。很抱歉,感谢您的帮助!
【解决方案2】:

已检查的异常不会停止成为已检查的异常。将已检查的异常变为未检查的方法是将其包装在 RuntimeException 类型中并重新抛出它。

【讨论】:

    【解决方案3】:

    在您的情况下,调用堆栈的根将是 Exceptions all the way down。如果一个方法被声明为抛出Exception(这些方法很少应该这样做),调用方法要么不得不说它也抛出Exception,要么抓住它并处理它。

    编辑 至于编辑过的 OP 中的示例,那将无法编译。如果你不想处理它,你可以声明main 来抛出Exception

    【讨论】:

      【解决方案4】:

      您的编译器是否有可能没有抱怨main() 中的问题,因为它遇到了method2() 中的问题并在那时停止检查语法?两者都应该是错误的。您是否修复了method2() 中的调用并进行了干净的编译?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-21
        • 2023-04-08
        • 2011-11-09
        • 2010-11-02
        • 2013-08-23
        • 1970-01-01
        相关资源
        最近更新 更多