JDK 7通过改进的类型检查来捕获多个异常类型和重新发现异常 [英] JDK 7 Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking

查看:130
本文介绍了JDK 7通过改进的类型检查来捕获多个异常类型和重新发现异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java 7之前,如果我们不得不从方法中重新抛出异常,那么我们将不得不采取两种方式之一,

  public void rethrowException(String exceptionName)throws FirstException,SecondException {
try {
if(exceptionName.equals(First)){
throw new FirstException();
} else {
throw new SecondException();
}
} catch(FirstExceptione){
throw e;
} catch(SecondException){
throw e;
}
}

,第二个是

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

根据我的理解,一种方法可以捕获异常异常的异常,并且仍然在方法定义中保留狭义的异常,就像下面的代码一样,

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

Java SE 7编译器可以确定抛出的异常通过语句throw e必须有
来自try块,并且try块抛出的唯一异常可以是FirstException和
SecondException。即使catch子句的异常参数e是类型为Exception,
编译器也可以确定它是FirstException或SecondException的一个实例。如果catch参数分配给catch块中的另一个值,则此
分析将被禁用。但是,如果将catch参数分配给另一个值,则
,则必须在方法声明的throws子句中指定
中的异常类型异常。



从Oracle文档中,



详细来说,在Java SE 7及更高版本中,当您在catch子句中声明一个或多个异常类型时,
并重新抛出由此catch块处理的异常,编译器验证
重新抛出异常的类型是否满足以下条件:

  1)try块能够抛出它。 
2)没有其他前面的catch块可以处理它。
3)它是一个子类型或超类型的一个catch子句的异常参数。
4)在Java SE 7之前的版本中,您不能抛出异常,它是
之一的超类型的catch子句的异常参数。来自Java SE 7之前的发行版的编译器会生成
的错误,$未指定的异常异常;必须被捕获或声明为抛出在
语句throw e。编译器检查抛出异常的类型是否可以分配给rethrowException方法声明的throws子句中声明的类型的任何
。但是,
catch参数的类型e是Exception,它是一个超类型,而不是子类型,
FirstException和SecondException。

我没有理论上第3和第4点。有人可以用上述代码解释我吗?

解决方案

考虑以下情况:



您的应用程序抛出一个例外 FirstException SecondException 异常



异常 FirstException SecondException 因为它们扩展了异常



它也应该应用 SecondException扩展FirstException 。所以 FirstException 是一个超类型的 SecondExeption SecondException 一个子类型的 FirstException



现在我们有一个方法总是抛出 SecondException

第一种情况:

 尝试{
[...]
} catch(SecondException se){
//异常总是被抓到这里
[...]
} catch FirstException fe){
[...]
} catch(异常e){
[...]
}
/ pre>

第二种情况:

  try { 
[...]
} catch(异常e){
//异常总是在这里
//因为异常是所有其他异常的超类型
[...]
} catch(FirstException fe){
[...]
} catch(SecondException se){
//永远不会调用。
[...]
}

你看到了点吗? / p>

Prior to Java 7, if we had to rethrow an exception from a method, then we will have to do either of the 2 ways,

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

and the second one being,

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

As per my understanding, New Java 7.0 has improved in a way that you can catch wide level of exception of exceptions and still keeps the narrow exceptions in the method definition, just like below code,

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

The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be FirstException and SecondException. Even though the exception parameter of the catch clause, e, is type Exception, the compiler can determine that it is an instance of either FirstException or SecondException. This analysis is disabled if the catch parameter is assigned to another value in the catch block. However, if the catch parameter is assigned to another value, you must specify the exception type Exception in the throws clause of the method declaration.

From Oracle docs,

In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions:

1) The try block is able to throw it.
2) There are no other preceding catch blocks that can handle it.
3) It is a subtype or supertype of one of the catch clause's exception parameters.
4) In releases prior to Java SE 7, you cannot throw an exception that is a supertype of one of   
the catch clause's exception parameters. A compiler from a release prior to Java SE 7 generates 
the error, "unreported exception Exception; must be caught or declared to be thrown" at the 
statement throw e. The compiler checks if the type of the exception thrown is assignable to any 
of the types declared in the throws clause of the rethrowException method declaration. However, 
the type of the catch parameter e is Exception, which is a supertype, not a subtype, of 
FirstException andSecondException.

I failed to undertand the 3rd and the 4rth point theoritically. Can someone explain me in context with the code mentioned above?

解决方案

Consider following situation:

Your application throws one of the exceptions FirstException, SecondException, Exception

Exception is the supertype of FirstException, SecondException because they extend Exception.

It should also apply that SecondException extends FirstException. So FirstException is a supertype of SecondExeption and SecondException a subtype of FirstException.

Now we have a method which always throws SecondException.

First Case:

try {
[...]
} catch(SecondException se) {
// Exception gets always caught in here
[...]
} catch(FirstException fe) {
[...]
} catch(Exception e) {
[...]
}

Second Case:

try {
[...]
} catch(Exception e) {
// Exception gets always caught in here
// because Exception is supertype of all other Exception
[...]
} catch(FirstException fe) {
[...]
} catch(SecondException se) {
// is never called.
[...]
} 

Do you see the point?

这篇关于JDK 7通过改进的类型检查来捕获多个异常类型和重新发现异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆