【Java疑难杂症】有return的情况下try catch finally的执行顺序
有这样一个问题,异常处理大家应该都不陌生,类似如下代码:
public class Test {
public static void main(String[] args) {
int d1 = 0;
int d2 = 1;
try {
d2--;
d1 = 1 / d2;
System.out.println("try");
}catch (Exception e){
System.out.println("Catch An Exception.");
}finally {
System.out.println("finally");
}
}
}
运行到第7行的时候,会出现算术异常,try语句块捕获到这个异常,然后开始执行catch语句块中的内容,最后执行,finally语句块中的内容,因此输出如下:
Catch An Exception.
finally
但是,如果try,catch,finally语句中有return的时候,会怎样呢?
我们都知道,finally语句块是不论如何都会执行的,那三个块中的return,会先返回谁呢?我们来进行一下测试:
public class Test {
public static void main(String[] args) {
int i = Test.getReturn();
System.out.println(i);
}
public static int getReturn(){
int a = 0;
int d1 = 0;
int d2 = 1;
try {
//try语句块中没有发生异常
a = 10;
d1 = 1 / d2;
return a;
}catch (Exception e){
a = 20;
System.out.println("Catch An Exception.");
return a;
}finally {
a = 30;
System.out.println("finally");
return a;
}
}
}
这里的try语句块中没有发生异常,那么执行顺序如何呢?在try中的return是直接返回吗?finally的return该怎样处理呢?先让我们看一下结果:
finally
30
结果是执行完成finally语句块之后,使用的是finally语句块中的a,而不是try语句块中的a。
那如果try中出现异常呢?我们改动一下:
public class Test {
public static void main(String[] args) {
int i = getReturn();
System.out.println(i);
}
public static int getReturn(){
int a = 0;
int d1 = 0;
int d2 = 1;
try {
a = 10;
d1 = 1 / (--d2);
return a;
}catch (Exception e){
a = 20;
System.out.println("Catch An Exception.");
return a;
}finally {
a = 30;
System.out.println("finally");
return a;
}
}
}
好的,现在try中出现了算术异常,catch语句块将被执行,然后再执行finally语句块,这样的话返回结果如何呢?
Catch An Exception.
finally
30
还是返回30,也就是finally中a的值
如果去掉finally中的return会怎样?
public class Test {
public static void main(String[] args) {
int i = getReturn();
System.out.println(i);
}
public static int getReturn(){
int a = 0;
int d1 = 0;
int d2 = 1;
try {
a = 10;
d1 = 1 / (--d2);
return a;
}catch (Exception e){
a = 20;
System.out.println("Catch An Exception.");
return a;
}finally {
a = 30;
System.out.println("finally");
//return a;
}
}
}
输出如下:
Catch An Exception.
finally
20
返回的是catch语句块中的a。先执行catch语句块中的代码,finally语句虽然执行了,a的值应该也被修改成30了,但实际返回的却是20,。
我们再来做一个测试,把catch和finally语句块中的return都注释掉,来看看返回情况:
public class Test {
public static void main(String[] args) {
int i = getReturn();
System.out.println(i);
}
public static int getReturn(){
int a = 0;
int d1 = 0;
int d2 = 1;
try {
a = 10;
d1 = 1 / (d2);
return a;
}catch (Exception e){
a = 20;
System.out.println("Catch An Exception.");
//return a;
}finally {
a = 30;
System.out.println("finally");
//return a;
}
return a;
}
}
输出如下:
finally
10
所以finally中虽然修改了a的值,但实际返回的是修改之前的值。也就是相当于程序先用一个瓶子将try中的return的值装起来,后面不管finally如果修改a的值,返回值都不会变,但这只是因为返回的是基本数据类型,如果是引用类型,还是有点区别的,来看个栗子。
先声明一个Stu类:
public class Stu {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试一下:
public class Test {
public static void main(String[] args) {
Stu stu = getReturn();
System.out.println(stu.getName());
}
public static Stu getReturn(){
Stu stu = new Stu();
int d1 = 0;
int d2 = 1;
try {
stu.setName("1");
d1 = 1 / (d2);
return stu;
}catch (Exception e){
stu.setName("2");
System.out.println("Catch An Exception.");
}finally {
stu.setName("3");
System.out.println("finally");
}
return stu;
}
}
输出如下:
finally
3
所以你看,现在还是变成了finally中的修改值,所以瓶子里装的只是变量中的内容,只能保证这个内容不会变,如果是引用变量,变量中存储的是引用对象的地址,finally中对引用对象的修改还是会影响到返回对象的。
所以结论其实很简单,try,catch,finally语句块的return的优先级由低到高,先执行try中return之前的语句,如果遇到异常,则执行catch语句中return之前的代码,最后执行finally语句块,finally语句块中如果有return,那么程序就会提前返回,如果没有,则返回catch语句块中的return,如果没有遇到异常,则直接执行finally中的语句块,再看finally语句块中是否有return来决定返回结果。
结论:
1、不管是否出现异常,finally块中的代码都会执行;
2、当try和catch中有return时,finally仍然会执行,finally中的return优先级大于catch大于try;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
【Java疑难杂症】有return的情况下try catch finally的执行顺序的更多相关文章
- Java基础知识强化之IO流笔记06:有return的情况下try catch finally的执行顺序
1. 给出结论: (1)不管有木有出现异常,finally块中代码都会执行:(2)当try和catch中有return时,finally仍然会执行:(3)finally是在return后面的表达式运算 ...
- 有return的情况下try catch finally的执行顺序(转)
结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...
- 有return的情况下try catch finally的执行顺序
结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...
- 有return的情况下try catch finally的执行顺序(最有说服力的总结)
结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...
- 有return的情况下try catch finally的执行顺序(转)
结论:1.不管有没有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...
- [转]有return的情况下try catch finally的执行顺序
结论: 1.不管有没有出现异常,finally块中代码都会执行: 2.当try和catch中有return时,finally仍然会执行: 3.finally是在return后面的表达式运算后执行的(此 ...
- throw和throws的区别以及try,catch,finally在有return的情况下执行的顺序
一,抛出异常有三种形式,一是throw,一个throws,还有一种系统自动抛异常.下面它们之间的异同. (1).系统自动抛异常 1.当程序语句出现一些逻辑错误.主义错误或类型转换错误时,系统会自动抛出 ...
- 【转】C# 异常处理 throw和throw ex的区别 try catch finally的执行顺序(return)
[转]throw和throw ex的区别 之前,在使用异常捕获语句try...catch...throw语句时,一直没太留意几种用法的区别,前几天调试程序时无意中了解到几种使用方法是有区别的,网上一查 ...
- Java之HashMap在多线程情况下导致死循环的问题
PS:不得不说Java编程思想这本书是真心强大.. 学习内容: 1.HashMap<K,V>在多线程的情况下出现的死循环现象 当初学Java的时候只是知道HashMap<K,V& ...
随机推荐
- Hello World -- 第一篇博客
今年注定是不寻常的一年,因为技术,接触了许多大牛.通过一篇篇博文,看到了大牛们勤奋好学.孜孜不倦的精神,于是决定也开个博客,向大牛学习. 博客开了,写点什么呢?奈何肚子里墨水不多,吐出来也多是白沫,不 ...
- Django 模型中自定义Manager和模型方法
1.自定义管理器(Manager) 在语句Book.objects.all()中,objects是一个特殊的属性,通过它来查询数据库,它就是模型的一个Manager. 每个Django模型至少有一个m ...
- vue——实例方法 / 数据
目录 1.vm.$set 2.vm.$watch 3.vm.$delete 1.vm.$set 哎呀呀,周五啦,大家应该都很开心吧,放假了可以好好休息休息啦,然而小颖明天要面试,所以小颖今天就回去放了 ...
- linux 内核 zImage 生成过程分析
1. 依据arch/arm/kernel/vmlinux.lds 生成linux内核源码根目录下的vmlinux,这个vmlinux属于未压缩,带调试信息.符号表的最初的内核,大小约23MB: arm ...
- STM32 AD采样电压计算公式
在使用STM32的ADC进行检测电压时必须回涉及到电压值的计算,为了更高效率的获取电压,现在有以下三种方法: 你得到的结果是你当前AD引脚上的电压值相对于3.3V和4096转换成的数字.假如你得到的A ...
- HTML5-前端开发很火且工资很高?
前言 晚上逛论坛看到一篇对从事HTML5前端开发的文章写的非常不错,和目前的市场形势差不多,然后我在其基础上给大家进行加工总结一下分享给大家.今天我们谈论的话题是<<为什么从事HTML5前 ...
- LINUX 笔记-crontab命令
用户所建立的crontab文件中,每一行都代表一项任务,每行的每个字段代表一项设置,它的格式共分为六个字段,前五段是时间设定段,第六段是要执行的命令段,格式如下: minute hour da ...
- 进程,线程,GIL,Python多线程,生产者消费者模型都是什么鬼
1. 操作系统基本知识,进程,线程 CPU是计算机的核心,承担了所有的计算任务: 操作系统是计算机的管理者,它负责任务的调度.资源的分配和管理,统领整个计算机硬件:那么操作系统是如何进行任务调度的呢? ...
- Swift 之Protocol在cocoa中的使用范例搜集(一)
protocol Reusable: class { static var reuseIndentifier: String {get} static var nib: UINib? {get} } ...
- JavaScript+HTML5 实现打地鼠小游戏
一.游戏简介 打地鼠这个游戏相信大家都不陌生,也是童年时候一款经典的游戏.本次游戏的编写是以html文件形式完成的,并且使用HBulider软件进行编写,使用谷歌浏览器展示效果,游戏将会采用JavaS ...