【问题标题】:does the compiler consider actual types in error handling in java编译器是否在 java 中的错误处理中考虑实际类型
【发布时间】:2018-09-30 07:06:09
【问题描述】:

为什么会这样

class blah{
    public void someMethod(){
        try{
            throw new NullPointerException();
        }
        catch(Throwable t){
            System.out.println("Caught!");
            throw t;
        }
    }
}

似乎编译器有些如何看到 t 的实际类型

【问题讨论】:

    标签: java error-handling try-catch throwable


    【解决方案1】:

    该代码在 Java 7 之前将无法编译。

    来自Java SE 7 Features and Enhancements,部分Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking

    使用更具包容性的类型检查重新引发异常

    与早期版本的 Java SE 相比,Java SE 7 编译器对重新抛出的异常执行更精确的分析。这使您可以在方法声明的throws 子句中指定更具体的异常类型。

    考虑以下示例:

    static class FirstException extends Exception { }
    static class SecondException extends Exception { }
    
    public void rethrowException(String exceptionName) throws Exception {
      try {
        if (exceptionName.equals("First")) {
          throw new FirstException();
        } else {
          throw new SecondException();
        }
      } catch (Exception e) {
        throw e;
      }
    }
    

    这个例子的try 块可以抛出FirstExceptionSecondException。假设您想在rethrowException 方法声明的throws 子句中指定这些异常类型。在 Java SE 7 之前的版本中,您不能这样做。因为catch子句的异常参数eException类型,并且catch块重新抛出异常参数e,所以只能在throws子句中指定异常类型Exception rethrowException 方法声明。

    但是,在 Java SE 7 中,您可以在 rethrowException 方法声明的 throws 子句中指定异常类型 FirstExceptionSecondException。 Java SE 7 编译器可以确定语句throw e 抛出的异常一定来自try 块,而try 块抛出的异常只能是FirstExceptionSecondException。即使catch 子句的异常参数eException 类型,编译器也可以确定它是FirstExceptionSecondException 的实例:

    public void rethrowException(String exceptionName)
    throws FirstException, SecondException {
      try {
        // ...
      }
      catch (Exception e) {
        throw e;
      }
    }
    

    【讨论】:

      【解决方案2】:

      NullPointerException 是异常的孩子。异常是 Throwable 的孩子。所以这应该是因为多态性。

      【讨论】:

      • 你不能正常地 throwThrowable (即t)而不捕获它(catch)或声明它(throws Throwable),因为它既不是@987654326 @ 或 Error
      【解决方案3】:

      之所以有效,是因为NullPointerExceptionThrowable 的一个实例。 catch 子句捕获声明类型的所有实例。

      【讨论】:

      • 你不能正常地 throwThrowable (即t)不抓住它(catch)或声明它(throws Throwable),因为它既不是@987654328 @ 或 Error
      • 我从来没有说过你可以这样做。
      • 问题是为什么throw t 不会编译失败,因为它被声明Throwable 类型,这不是两个未选中的类型之一类型(RuntimeExceptionError)。
      • 因为Throwable 是它们的超类。
      • 但是Throwable 本身是一个 checked 类型,所以问题是“为什么这个工作”,即为什么throw t 不抱怨检查Throwable 是没有被抓住或宣布?你根本没有回答这个问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 1970-01-01
      • 1970-01-01
      • 2021-09-09
      • 1970-01-01
      相关资源
      最近更新 更多