Java 编译器强制处理未检查异常的重试

Java 编译器强制处理未检查异常的重试,java,exception-handling,Java,Exception Handling,我在处理异常时遇到了一个场景,下面是示例代码。我试图理解为什么下面的代码无法编译。我在重试之前检查异常类型,这是未检查的异常 public class TestException { public void test() throws FileNotFoundException { FileReader test = new FileReader(""); } public static void main(String[] args){

我在处理异常时遇到了一个场景,下面是示例代码。我试图理解为什么下面的代码无法编译。我在重试之前检查异常类型,这是未检查的异常

public class TestException {

    public void test() throws FileNotFoundException {
        FileReader test = new FileReader("");

    }
    public static void main(String[] args){
        TestException test=new TestException();
        try {
            test.test();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            if(e instanceof ArithmeticException){
                throw e;
            }
            else{
                e.printStackTrace();
            }

        }
    }
}

尝试按如下方式更改捕捉块:-

if(e instanceof ArithmeticException){
     throw (ArithmeticException)e;
 }
 else{
     e.printStackTrace();
 }

您仍在抛出类型为Exception的引用变量e。异常是一个选中的类型。编译器只知道引用变量的类型,而不知道被引用对象的类型。如果希望保持main的方法签名不变,则需要将e包装为未经检查的异常类型,例如算术异常:

或将其强制转换为未经检查的异常:

if(e instanceof ArithmeticException){
     throw (ArithmeticException)e;
 }

我建议使用两个挡块。 在catch块中进行类型检查并不是一种好的做法,因为您可以使用其他catch语句捕获特定的类

catch (ArithmeticException e) {
    // TODO Auto-generated catch block
    throw e;
 }
catch(Exception e)
{
     e.printStackTrace();
}

@愚蠢的怪胎,我同意你的看法。

如果你抛出任何异常,那么你应该处理它,但在你的程序中,你可以抛出,但没有地方处理异常,所以只需通过在主类中添加抛出来处理异常,如下所示:-

package first;

import java.io.FileNotFoundException;
import java.io.FileReader;


class A3{

    public void test() throws FileNotFoundException {
        FileReader test = new FileReader("");

    }
    public static void main(String[] args) throws Exception{
        A3 test=new A3();
        try {
            test.test();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            if(e instanceof ArithmeticException){
                throw e;
            }
            else{
                e.printStackTrace();
            }

        }
    }
}

由于引用变量e的类型为java.lang.Exception,因此throw e将抛出checked Exception。因此,它必须在方法签名的throws部分声明。

您还可以使用泛型的hack将选中的异常作为未选中的异常抛出:

我喜欢在新的RuntimeExceptionOne上使用它,因为后者在Stacktrace中创建了不必要的输出,并且在其他地方很难捕获,您必须检查原因,而不是异常本身

catch (Exception e) {
这是e的有效声明

在这里,您正在执行e类型的运行时检查


此时,编译时类型e是异常的。因此编译器强制执行其规则。

throw e;line正在抛出异常,尽管您知道它是算术异常的一个实例,但e的类型仍然是异常。异常未被取消选中。为什么不使用两个单独的catch块?
catch (Exception e) {
    if(e instanceof ArithmeticException){
        throw e;