【Java】try中有return,finally还会执行吗?

本文详细介绍了Java中的异常处理机制,包括try...catch用于捕获异常,finally确保必要代码执行,以及return在try、catch和finally中的行为。特别强调了被屏蔽异常(SuppressedException)的概念以及如何处理返回值和异常传播。
摘要由CSDN通过智能技术生成

前言

Java内置了一套异常处理机制,在Java中异常是一种class,可以在任何地方抛出,但只需要在上层捕获,这样就和方法调用分离了。

1. 用try…catch捕获异常

捕获异常时通常使用try...catch语句,把可能发生异常的代码放到try {...}中,然后使用catch捕获对应的Exception及其子类。

public class Main {
    public static void main(String[] args) {
        String info = "error";
    	try {
    		getException(info);
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    }

    private static void getException(String info) throws CoreRuntimeException{
    	if ("error".equals(info)) {
    		throw new CoreRuntimeException();
    	}
    }
}

2. finally语句

无论是否有异常发生,如果我们都希望执行一些语句,例如清理工作,可以把正常执行的语句放到try中,总是会执行的语句放到finally中。

public class Main {
    public static void main(String[] args) {
	    try {
	    	System.out.println("Strart");
	        process();
	    } catch (IOException e) {
	        System.out.println("IO error");
	    } catch (Exception e) {
	        System.out.println("IO error");
	    } finally {
	    	System.out.println("END");
	    }
	}
	static void process() {
		//正常执行的语句
	}
}

上述代码无论是否发生异常,都会执行System.out.println("END");这条语句。

注意finally有几个特点:

  1. finally语句不是必须的,可写可不写;
  2. finally总是最后执行。

如果没有发生异常,就正常执行try { ... }语句块,然后执行finally。如果发生了异常,就中断执行try { ... }语句块,然后跳转执行匹配的catch语句块,最后执行finally

可见,finally是用来保证一些代码必须执行的。

3. try、catch、finally中同时存在return语句

那如果 try、catch、finally中同时存在return语句,方法到底该返回什么值呢?看看下面几段代码:

情况一:try正常执行,try、finally中都有return

public class TestReturn {
	public static void main(String[] args) {
		int result = getResult01();
		System.out.println(result);
	}

	public static int getResult01() {
		int result;
		try {
			result = 10 / 1;
			return result;
		} catch (Exception e) {
			result = 20;
			return result;
		} finally {
			result = 30;
			return result;
		}
	}
}

程序执行结果:
程序一运行结果
可见,就算try中有return且未抛出异常,但finally中的语句依旧会被执行。

情况二:try抛出异常,catch、finally中都有return

public class TestReturn {
	public static void main(String[] args) {
		int result = getResult01();
		System.out.println(result);
	}

	public static int getResult01() {
		int result;
		try {
			result = 10 / 0;
			return result;
		} catch (Exception e) {
			result = 20;
			return result;
		} finally {
			result = 30;
			return result;
		}
	}
}

程序执行结果:
程序二运行结果
可见,就算try中抛出异常,且catch中有return,但finally中的语句依旧会被执行。

结合前两种情况,可以判断,无论try或catch中是否有return,finally都一定会执行。

情况三:finally中无return,但改变了result值

public class TestReturn {
	public static void main(String[] args) {
		int result = getResult01();
		System.out.println(result);
	}

	public static int getResult01() {
		int result;
		try {
			result = 10 / 1;
			return result;
		} catch (Exception e) {
			result = 20;
			return result;
		} finally {
			result = 30;
		}
	}
}

程序运行结果:
程序三运行结果
可见,try中有return, 会先将值暂存,无论finally语句中对该值做什么处理,最终返回的都是try语句中的暂存值。

情况四:finally中有return,但不改变result值

public class TestReturn{
    public static void main(String[] args){
        System.out.print(getNumber(0));
        System.out.print(getNumber(1));
        System.out.print(getNumber(2));
        System.out.print(getNumber(4));
    }

    public static int getNumber(int num){
        try{
            int result = 2 / num;
            return result;
        }catch (Exception exception){
            return 0;
        }finally{
            if(num == 0){
                return -1;
            }
            if(num == 1){
                return 1;
            }
        }
    }    
}

程序运行结果:
程序四运行结果
可见,当try与finally语句中均有return语句,会忽略try中的return,即最终方法返回的是finally对应的return内容。

4. 被屏蔽的异常

如果在执行finally语句时抛出异常,那么原来在catch中准备抛出的异常就“消失”了,因为只能抛出一个异常。没有被抛出的异常称为“被屏蔽”的异常(Suppressed Exception)。

  • 如何保存所有的异常信息?方法是先用origin变量保存原始异常,然后调用Throwable.addSuppressed(),把原始异常添加进来,最后在finally抛出:
public class Main {
    public static void main(String[] args) throws Exception {
        Exception origin = null;
        try {
            System.out.println(Integer.parseInt("abc"));
        } catch (Exception e) {
            origin = e;
            throw e;
        } finally {
            Exception e = new IllegalArgumentException();
            if (origin != null) {
                e.addSuppressed(origin);
            }
            throw e;
        }
    }
}
  • 通过Throwable.getSuppressed()可以获取所有的Suppressed Exception
  • 绝大多数情况下,在finally中不要抛出异常。因此,我们通常不需要关心Suppressed Exception(白学警告)。

结论

  1. 无论try中是否有return,finally都一定会执行。
  2. try中有return, 会先将值暂存,无论finally语句中对该值做什么处理,最终返回的都是try语句中的暂存值。
  3. 当try与finally语句中均有return语句,会忽略try中的return,即最终方法返回的是finally对应的return内容。
  4. 在catch中抛出异常,不会影响finally的执行。JVM会先执行finally,然后抛出异常。
  5. 调用printStackTrace()可以打印异常的传播栈,对于调试非常有用。
  6. 捕获异常并再次抛出新的异常时,应该持有原始异常信息。

参考资料:
异常处理-廖雪峰的官方网站

  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值