Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序

发布时间:2021-12-30 17:47:08 作者:柒染
来源:亿速云 阅读:146

Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

文章的标题看似自相矛盾,然而我在“正确”二字上打了引号。我们来看一个例子,关于Java异常处理(Exception Handling)的一些知识点。

看下面这段程序。方法pleaseThrow接受一个Exception的实例,然后简单地将该实例抛出。然后调用这个方法时,我传入了一个SQLException的实例。因为pleaseThrow的调用包裹在一个try catch块里,

问题:plesseThrow方法抛出的SQLException可以成功被catch住么?

public class ExceptionForQuiz<T extends Exception> {      private void pleaseThrow(final Exception t) throws T {             throw (T) t;
      }     public static void main(final String[] args) {          try {               new ExceptionForQuiz<RuntimeException>().pleaseThrow(new SQLException());
          }         catch( final SQLException ex){
              System.out.println("Jerry print");
              ex.printStackTrace();
        }
}
}

Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序

答案:上面这段代码有语法错误,不能通过编译!

Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序

我们来一步步分析。

Java类ExceptionForQuiz<T extends Exception>使用了一个泛型语法,T extends Exception意思是这个泛型类实例化的时候,传入的类型参数T必须是Exception以及它的子类。

我在实例化类ExceptionForQuiz时,传入的类型参数是RuntimeException。

RuntimeException在Java里是一种Unchecked异常,即使一个方法运行时可能会抛出RuntimeException,也不需要开发人员在方法前用代码显式声明。

看JDK RuntimeException的注释说的很清楚:Unchecked exceptions do NOT need to be declared in a method or constructor's clause if they can be thrown by the execution of the method or constructor.

这个作者Frank Yellin一定是个大牛。

Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序

因为泛型是 Java 1.5 版本才引进的概念,关于泛型有一个类型擦除的概念,即泛型信息只存在于代码编译阶段,编译之后的代码里,与泛型相关的信息会被擦除掉。比如之前泛型类中的类型参数部分如果没有指定上限,像这种写法<T>, 则会被转译成普通的Object类型。如果指定了上限如<T extends String>则类型参数就被替换成类型上限。

为了简化起见,我们先把代码里的try catch块去掉。

Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序

下面是从ExceptionForQuiz.class反编译之后的代码:

Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序

我们从上图能观察到,方法pleaseThrow和雷ExceptionForQuiz的泛型参数RuntimeException已经被擦除掉了。pleaseThrow这个方法能抛出的异常类型已经被擦除成为Exception了。

使用javap观察编译生成的字节码,同样能发现类型参数RuntimeException被擦除的事实:

看第二个红色高亮区域:Exceptions: throw java.lang.Exception

Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序

现在我们来看编译器会报什么错误消息:Unreachable catch block for SQLException. This exception is never thrown from the try statement body.

Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序

根据异常类型擦除的事实,这个错误消息是合理的,因为pleaseThrow方法的声明现在只能抛出类型为Exception的异常,所以第14行的catch永远也没有办法接收到类型为SQLException的异常,所以编译器抛出错误。

如何消除掉这个编译器错误呢?把第14行的SQLException改成RuntimeException即可。

但是这样的话,虽然消除了语法错误,但是方法pleaseThrow抛出的SQLException没有办法被catch住,会报运行时错误:

Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序

如何把pleaseThrow抛出的SQLException也用catch语句接住呢?将第14行的RuntimeException改成所有异常的超类:Exception。

再次执行,这次既没有语法错误,也没有运行时错误了:SQLException已经成功地被第14行的catch语句捕捉住了。

Java异常处理中怎么写出“正确”但被编译器认为有语法错误的程序

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。

推荐阅读:
  1. 计算机配置似乎是正确的但该设备 DNS 服务
  2. android定义可以被其他程序调用的activity

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:SAP Cloud Platform integration上怎样创建一个最简单的iFlow

下一篇:如何在window命令行下编译C程序

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》