内容简介:看一下下面的异常处理代码,猜一下会打印什么呢?熟悉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 数据库
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
恰如其分的软件架构
George Fairbanks / 张逸、倪健、高翌翔 / 华中科技大学出版社 / 2013-9-1 / 88.00
本书描述了一种恰如其分的软件架构设计方法。作者建议根据项目面临的风险来调整架构设计的成本,并从多个视角阐述了软件架构的建模过程和方法,包括用例模型、概念模型、域模型、设计模型和代码模型等。本书不仅介绍方法,而且还对方法和概念进行了归类和阐述,将软件架构设计融入开发实践中,与 敏捷开发方法有机地结合在一起,适合普通程序员阅读。 . 这是一本超值的书,案例丰富有趣,言简意赅,阅读轻松。当年......一起来看看 《恰如其分的软件架构》 这本书的介绍吧!