我有一个异常链,其中method1
向method2
抛出异常,将异常抛出到main
。出于某种原因,编译器强迫我处理method2
中的错误并将其标记为错误,如果我不这样做,表明它是一个已检查的异常。但是当同一Exception
向下抛到main
时,编译器允许我忽略它并且不显示任何错误。
method1
中的原始异常是ParseException
,会进行检查。但是该方法在头文件中有一个通用throws Exception
子句,并且同一个对象被抛出到method2,它具有相同的throws Exception
子句。此异常何时以及如何失去编译器检查/捕获的状态?
编辑澄清:
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
条款。我删除了它,代码现在按预期运行。谢谢你的帮助!
答案 0 :(得分:6)
是否检查异常完全取决于它是什么类型的异常:如果它是RuntimeException
或它的子类,则不检查;否则就是。 (是的,RuntimeException
是Exception
的子类 - Java库设计的失败之一,但不是最重要的。)
编译器检查的是方法签名。因此抛出的实际异常是无关紧要的(为此目的)。如果方法说throws Exception
,则必须在方法中捕获Exception
或声明方法throws Exception
。方法应始终使用最窄的 throws
子句 - 例如,不 throws Exception
但throws ParseException
。
(我说“无关紧要(为此目的)”因为,当然,编译器将执行的其他事项之一是检查您是否抛出未涵盖的已检查异常通过您的throws
条款。)
编辑您在编辑中添加的代码将无法编译:1。它正在调用没有实例的实例方法,并且2. main
需要声明它抛出{{ 1}}。
此代码解决了其他问题,并且(正确地)证明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();
}
}
答案 1 :(得分:3)
已检查的异常不会停止成为已检查的异常。你可以将检查过的异常转换成未经检查的方法是将它包装在一个RuntimeException类型中并重新抛出它。
答案 2 :(得分:2)
在您的情况下,它将是Exception
s all the way down到调用堆栈的根目录。如果声明一个方法抛出Exception
(这种方法很少应该这样做),那么调用方法也必须说它抛出Exception
,或者抓住它并处理它。
编辑对于已编辑的OP中的示例,将无法编译。如果你不想处理它,你可以声明main
抛出Exception
。
答案 3 :(得分:0)
您的编译器是否可能不会在main()
中抱怨此问题,因为它会在method2()
中遇到问题并在此时停止检查语法?两者都应该是一个错误。您是否已在method2()
修复了调用并获得了干净的编译?