Java异常那些事

本文讨论了Java中的受检异常与非受检异常的区别,强调了异常处理的重要性,即使非受检异常也不应忽视。在捕获异常时,提供异常cause有助于定位问题根源。同时,详细阐述了finally块中return语句对结果的影响,提醒开发者避免在finally中直接返回结果,以免干扰正常流程。最后,介绍了try-with-resources语句在自动资源管理中的作用,确保资源的正确关闭。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 受检异常和非受检异常

  • 非受检异常:继承RuntimeException的异常都是非受检异常,非受检异常不需要在函数上明确声明throws exception;

  • 那么为啥异常要分受检和非受检呢。如果需要明确函数抛出的异常,那么就需要明确一下,并且编译器会自动监测受检异常是否处理,否则会编译报错。非受检异常,这个表示是运行期错误,是不应该发生的,发生了就应该出错才对。

  • 那么我们写程序的时候,到底是写受检异常好呢还是非受检异常好。其实不管是定义受检和还是非受检,都要在适当的时候捕获异常,不能因为非受检异常编译器不检查,就不处理异常了,特别是需要资源释放等场景时都要主动去捕获异常。

2. 捕获异常重新生成异常,cause不要忘了

  1. 先看一下不输出异常cause,那么获取的异常堆栈是什么样的?
    首先看一下,如果捕获异常后直接生成新的异常,不带cause,下游输出异常栈的结果是什么?
try {
	try {
		double r = 1/0;
	} catch (Exception e) {
		throw new NewException(e.getMessage());
	}
} catch(Exception e) {
	e.printStackTrace();
}

输出结果异常堆栈信息是,这样的话,只知道异常是由throw new NewException这个地方抛出的,但是什么原因导致这个异常抛出,就不知道了。

org.example.NewException: / by zero
	at org.example.AppTest.testException(AppTest.java:99)
  1. 如果加上异常cause,那么异常堆栈是什么样的?
    把上面的抛出异常的语句改一下,改成加上异常原因的方式,throw new NewException(e.getMessage(), e);
try {
	try {
		double r = 1/0;
	} catch (Exception e) {
		throw new NewException(e.getMessage(), e);
	}
} catch(Exception e) {
	e.printStackTrace();
}

输出的异常堆栈如下:
因为加上了异常cause,所以很清楚知道最源头的异常是如何发生的。

org.example.NewException: / by zero
	at org.example.AppTest.testException(AppTest.java:99)
Caused by: java.lang.ArithmeticException: / by zero
	at org.example.AppTest.testException(AppTest.java:97)```
  1. 备注,NewExeption的定义如下:
class NewException extends Exception{
    public NewException(String msg) {
        super(msg);
    }
    public NewException(String msg, Throwable e) {
        super(msg, e);
    }
}

3. finnally 对return的影响

  1. 如果finnally中也有return语句,那么输出结果是什么?
    如下所示,那么test的最终返回结果是try中的ret++,还是ret+3?正确答案是:首先计算try中的return语句,ret++,此时ret=1,然后把返回结果1记录下来,这个时候再去执行finally中的return语句,这个时候直接返回ret + 3,即结果是4,那么 直接返回。所以,最终的输出结果是4。
public int test() {
        int ret = 0;
        try {
            return ret++;
        } catch (Exception e) {
            throw new NewException(e.getMessage(), e);
        } finally {
            return ret+3;
        }
    }
  1. 如果finnally中没有return语句,但是也对try中的return变量,做了操作,会影响try中的return结果吗?
    最终test输出结果是1,finally中的ret+2不会影响return结果。为啥呢?因为try中return中的语句执行完成之后,会把计算结果值拷贝下来,然后再去计算finally中的语句,finally不会对return语句的结果造成影响。
public int test() throws NewException {
        int ret = 0;
        try {
            return ret + 1;
        } catch (Exception e) {
            throw new NewException(e.getMessage(), e);
        } finally {
            ret = ret + 2;
            System.out.println("result:" + ret);
        }
    }
  1. 综上所述,不要在finally中return结果,以免影响try中的return结果。其次,finally中对try中return的变量做操作,不会影响

4. try中释放资源

try语句中后面带有一个(),()理解可以创建资源,比如文件、网络端口,等try语句执行完成之后,会自动调用资源的close方法,释放资源。

try(Resource res1 = new Resource();Resource res2 = new Resource())//可指定多个资源,用;隔开{
		xx
     }                                                                       

如果不使用该方法,之前的方法,需要在finally中主动释放

try {
	Resource res1 = new Resource();
 } catch (Exception ex) {
    ex.printStackTrace();
} finally {
    if (res1 != null) {
       rest1.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值