Java 异常(Part 2)相关面试题

问:请简单描述下面方法的执行流程和最终返回值是多少?

答:本题旨在考察 try-catch-finally 块的用法踩坑经验,具体解析如下。

test1 方法运行返回 0,因为执行到 try 的 return ret; 语句前会先将返回值 ret 保存在一个临时变量中,然后才执行 finally 语句,最后 try 再返回那个临时变量,finally 中对 ret 的修改不会被返回。

test2 方法运行返回 2,因为 5/0 会触发 ArithmeticException 异常,但是 finally 中有 return 语句,finally 中 return 不仅会覆盖 try 和 catch 内的返回值且还会掩盖 try 和 catch 内的异常,就像异常没有发生一样(特别注意,当 finally 中没有 return 时该方法运行会抛出 ArithmeticException 异常),所以这个方法就会返回 2,而且不再向上传递异常了。

test3 方法运行抛出 hello 异常,因为如果 finally 中抛出了异常,则原异常就会被掩盖。

因此为避免代码逻辑混淆,我们应该避免在 finally 中使用 return 语句或者抛出异常,如果调用的其他代码可能抛出异常,则应该捕获异常并进行处理。

问:如果执行 finally 代码块之前方法返回了结果或者 JVM 退出了,这时 finally 块中的代码还会执行吗?

答:只有在 try 里面通过 System.exit(0) 来退出 JVM 的情况下 finally 块中的代码才不会执行,其他 return 等情况都会调用,所以在不终止 JVM 的情况下 finally 中的代码一定会执行。

问:分别说说下面代码片段都有什么问题?

 

上面代码段对于 func 方法后面 throws 列出的异常类型是不分先后顺序的,所以 func 方法是没问题的;对于 main 方法中在捕获 RuntimeException 类型变量 re 的地方会编译错误,因为 Exception 是 RuntimeException 的超类,func 方法执行的异常都会被第一个 catch 块捕获,所以会报编译时错误。

 

如上代码片段在编译时子类 func 方法会出现编译异常,因为在 java 中重写方法抛出的异常不能是原方法抛出异常的父类,这里 func 方法在父类中抛出了 IOException,所有在子类中的 func 方法只能抛出 IOExcepition 或是其子类,但不能是其父类。

 

上面代码段编译时在 IOException 时会出现编译错误,因为 IOException 是受检查异常,而 func 方法并没有抛出 IOException,所以编译报错,但是如果将 IOException 改为 Exception(或者 NullPointerException 等)则编译报错将消失,因为 Exception 可以用来捕捉所有运行时异常,这样就不需要声明抛出语句。

答:通过上面几个代码片段可以看出我们在书写多 catch 块时要保证异常类型的优先级书写顺序,要保证子类靠前父类靠后的原则;此外在 java 中重写方法抛出的异常不能是原方法抛出异常的父类;如果方法没有抛出受检查类型异常则在调用方法的地方就不能主动添加受检查类型异常捕获,但是可以添加运行时异常或者 Exception 捕获。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值