内容简介:看一下下面的异常处理代码,猜一下会打印什么呢?熟悉Java异常处理的你,可能一眼就看出来了,结果是打印
问题一:有意思的异常处理
看一下下面的异常处理代码,猜一下会打印什么呢?
public static void main(String[] args) { System.out.println(decision()); } private static boolean decision() { try { return true; } finally { return false; } }
熟悉 Java 异常处理的你,可能一眼就看出来了,结果是打印 false
,如果你觉得会打印 true
的话,那说明你的基础还是有点小问题的。虽然这里比较简单,但我们还是来简单说明下。
解惑1:
我们既然学过java中的异常处理,那么原因的话也比较简单:
在 try-finally
块中,无论 try
语句是否是正常结束,是否抛出异常,是否直接返回,最终都会执行 finally
块中的语句;
但有一点需要注意,如果在try语句中执行了 System.exit(0)
,那么便不会走到finally块了,因为该操作会直接停止当前线程。
1. try-finally顺序问题
我们接着来看try-finally的问题,下面来看下try-finally的顺序问题,看下下面的程序会打印什么?
public static void main(String[] args) { System.out.println(decision()); } private static boolean decision() { try { System.out.println("---try---"); return true; } finally { System.out.println("---finally---"); } }
很显然,这里try语句中使用了return语句,而finally中没有return,那么最终打印的结果:
---try--- ---finally--- true
和上面相比,也就是说
try会尝试执行return语句,如果finally块中没有return语句,那么try的尝试将会成功;如果finally中有return,那么try的尝试将会被finally替代。
2. try-catch-finally的问题
这次我们加入catch操作来看下(main方法由于都一样,这里就不贴上来了):
private static boolean decision() { try { System.out.println("---try---"); int temp = 23 / 0; return true; } catch (Exception e) { System.out.println("---catch---"); return false; } finally { System.out.println("---finally---"); } }
因为程序有异常,所以一定会走进catch块,那么最终的打印结果想必大家也知道了:
---try--- ---catch--- ---finally--- false
而如果finally中也有return语句的话呢,会不会也会覆盖掉catch中的return呢?我们简单修改下代码:
private static boolean decision() { try { System.out.println("---try---"); int temp = 23 / 0; return true; } catch (Exception e) { System.out.println("---catch---"); return true; } finally { System.out.println("---finally---"); return false; } }
没错,大家的猜想是正确的:
---try--- ---catch--- ---finally--- false
3. try-catch-finally 语句相加问题
再来看一下最后一个例子。猜测一下下面会打印什么呢?
private static int decision() { int temp = 10; try { System.out.println("--try---"); return temp += 5; } catch (Exception e) { System.out.println("---catch---"); } finally { System.out.println("---finally---"); temp = 25; } return temp; }
这里在进行try-catch-finally中的时候虽然有一个运算操作,不过大家应该一眼就看出来了:
--try--- ---finally--- 15
这个和上面的try-catch流程类似,因为try语句中有return语句,所以永远不会走到最下面的return语句,并且因为finally里没有return,所以无论我们在finally里怎么修改temp的值,最终返回的仍然是try语句中的temp的值。
这里可能还需要注意的就是 return temp += 5
;如果finally中也有return的话,那么最终将执行finally里的return:
private static int decision() { int temp = 10; try { System.out.println("--try---"); return temp += 5; } catch (Exception e) { System.out.println("---catch---"); } finally { System.out.println("---finally---"); return temp; } }
很显然,这里会执行finally块中的return,但最终的temp的值是由 return temp += 5
这里计算出来的,这里会分成两步计算: temp + 5;
, return temp;
,所以最终返回的temp仍然是15。
问题二:checked与unchecked异常
看下下面的代码会打印什么呢?
public static void main(String[] args) { try { System.out.println("Hello World"); } catch (IOException e) { System.out.println("exception"); } }
猜测一下这个程序会打印什么呢,会打印 Hello World
么?很遗憾,这个程序编译不通过,更谈不上打印些什么了。
解惑2:
这个问题原因也是很简单,因为:
-
Java语言规范将继承自Error类或者RuntimeException类的所有异常称为 未检查异常(unchecked) ,而所有其他的异常则称为 已检查异常(checked) ;
-
针对checked异常也就是说,一个方法不仅需要告诉编译器将要返回什么值,还要告诉编译器有可能发生什么错误 ;所以Java规范要求,如果cache语句要捕获一个checked异常,那么相应的try子句便要抛出对应checked异常或子类型的异常;
-
因为
IOException
属于checked异常,所以这里编译不通过;
那么来看一下下面的程序呢,会打印什么呢?
public static void main(String[] args) { try { System.out.println("Hello World"); } catch (Exception e) { System.out.println("exception"); } }
很显然,这个程序肯定是可以编译通过的,并且会打印对应的 Hello world
,因为:
在Java中,捕获 Exception
或者 Throwable
的catch语句是合法的;因为Exception本身是个基础类,不属于unchecked异常,也不属于checked异常,在Java中直接捕获 Exception
或者 Throwable
的都是没问题的;
那我们再来看一下面的程序,最终会通过编译么?
public class Main implements Type3{ public static void main(String[] args) { Type3 main = new Main(); main.f(); } @Override public void f() { System.out.println("hello world"); } } interface Type1 { void f() throws IOException; } interface Type2 { void f() throws InterruptedException; } interface Type3 extends Type1, Type2 {}
首先, IOException
和 InterruptedException
都是checked异常,Type3继承自上面这两个接口,看上去应该编译不通过。但很遗憾,这个程序不但可以编译通过,而且运行没有问题。虽然我们在学习异常的时候,了解到:
一个方法要么捕获其方法体可以抛出的所有受检查异常,要么声明它将抛出这些异常;
就本例而言, Main
调用了 f()
方法,但却没有处理这两个受检查异常,但是:
一个方法可以抛出的受检查异常集合,是它所适用的所有类型声明要抛出的受检查异常集合的交集,而不是合集;
简单来说,这里如果会抛出的话,只能抛出这两个异常的交集,但因为没有交集,所以无需抛出,自然也能编译通过,成功运行。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 答疑解惑之nginx
- 移动端H5解惑-页面适配(二)
- 移动端H5解惑-概念术语(一)
- 解惑3:时间频度,算法时间复杂度
- 解惑:这个 Spark 任务是数据倾斜了吗?
- Serverless 解惑——函数计算如何访问 PostgreSQL 数据库
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Learn Python 3 the Hard Way
Zed A. Shaw / Addison / 2017-7-7 / USD 30.74
You Will Learn Python 3! Zed Shaw has perfected the world’s best system for learning Python 3. Follow it and you will succeed—just like the millions of beginners Zed has taught to date! You bring t......一起来看看 《Learn Python 3 the Hard Way》 这本书的介绍吧!