从零开始学java(27)--- 异常

本文深入探讨Java中的异常处理机制,包括异常的分类、处理流程、关键字使用、自定义异常等核心内容,帮助读者理解如何有效管理和处理程序中的异常。

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

Day17

今天了解java中的异常处理机制

java使用面向对象的方式来处理异常,它把程序中发生的每个异常分别封装到一个对象中,该对象包含有异常的信息.所有异常的根类Throwable,Throwable又派生了两个子类,Error和Exception,Exception包括运行时异常(RuntimeException)和受检异常。

在这里插入图片描述常见的运行时异常有:

NullPointerException

ClassCastException

ArrayIndexOutOfBoundsException

ArithmeticException

IllegalArgumentException

IllegalStateException

1.异常处理机制

异常是程序不希望出现的情况,在异常出现以后,需要处理,才能让程序继续执行。Java提供了若干的异常类,当异常发生时,JVM会创建对应异常类的实例

异常类的层次:

Exception:需要处理 Error:无需处理
RuntimeException:该异常及其子类都是运行时异常,语法上无需显式处理
除RuntimeException之外,其他的Exception都是受检异常,语法上必须显式处理。

2.关键字:

try,catch,finally ,throw ,throws

1.捕获异常

捕获异常是通过3个关键词来实现的:try-catch-finally。用try来执行一段程序,如果出现异常,系统抛出一个异常,可以通过它的类型来捕捉(catch)并处理它,最后一步是通过finally语句为异常处理提供一个统一的出口,finally所指定的代码都要被执行(catch语句可有多条;finally语句最多只能有一条,根据自己的需要可有可无)。
 
注意点:
1、一个try语句必须带有至少一个catch语句块或一个finally语句块,当异常处理的代码执行结束以后,不会回到try语句去执行尚未执行的代码。
2、每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。
3、不管是否发生了异常,即使try和catch块中存在return语句,finally都必须要执行
4、finally语句块只有一种情况是不会执行的,那就是在执行finally之前遇到了System.exit(0)结束程序运行(结束当前正在运行中的java虚拟机)。

try{
    //可能抛出异常的代码
}catch(Exception e){
}finally{
  //可选,无论try是否有异常,finally中的语句都会执行
}

可以出现多个catch子句,抛出的异常会依次进行catch的比较,有互斥的效果(也就是只会catch try中的第一个异常)。

try{
    //可能抛出异常的代码
}catch(RuntimeException e){//如果有父子关系,先子
}catch(Exception e){//后父
}finally{
  //可选,无论try是否有异常,finally中的语句都会执行
}

多个异常有父子关系,先catch子类异常,后面catch父类异常。

finally主要释放try里代码打开的资源。

在Java1.7 提供了新的语法:
1.catch(多个并列的异常,使用 | 分隔)

2.try(实例化实现了AutoCloseable接口的类) 在执行完try-catch后自动调用其close方法

2.声明异常(throws子句)

当CheckedException产生时,不一定立刻处理它,可以再把异常throws出去。如果一个方法抛出多个已检查异常,就必须在方法的首部列出所有的异常,之间以逗号隔开。
throw:在条件成立时,throw 异常实例。
1:只能用于方法体内。
2:后面跟异常对象。
3:只能跟一个异常对象
throws:用于方法声明,表示该方法可能抛出异常,如果异常是受检异常,调用该方法的时候必须处理。

1:用在方法的声明处。参数列表的后面方法体的前面。
2:后面跟异常的类型。
3:可以跟多个异常类型。使用 逗号 分隔。

一些注意的点

1.异常被成功catch之后,代码会继续向后执行
正常情况下要输出错误相关堆栈信息,或输出可以帮助定位问题的日志信息。也可以为空(不推荐)。//一般用e.printStackTrace();

2.异常未被成功catch,则不会继续向下执行代码
异常会继续向上抛,后续代码不会继续执行。

3.成功捕获异常后使用throw直接抛出,不对异常进行处理,代码不会继续向下执行。

4.方法名后使用throws声明可能会抛出的异常,异常产生后交给上层调用方法处理。

5.try-catch-finally成功捕获异常,执行finally中代码,并继续执行try-catch-finally块后面的代码。

6.try-catch-finally未成功捕获异常,执行finally中代码,停止执行try-catch-finally块后面的代码。

注:
1.try-catch-catch-catch-finally中如果成功捕获异常,只会有一个catch起作用,如果有其他的异常,只会捕获第一个。

2.java异常处理用到了多态的概念,如果在异常处理过程中,先捕获了基类,然后在捕获子类,那么捕获子类的代码块永远不会执行.因此,在进行异常捕获时,正确的写法是先捕获子类,再捕获父类的异常信息。

3.异常能处理就处理,不能处理就抛出.对于一般异常,如果不能进行行之有效的处理,最好转换成运行时异常抛出.

3.关于受检异常和非受检异常

一直以来,关于在程序中到底是该使用受检异常还是非受检异常,开发者之间一直存在着争议,毕竟两类异常都各有优缺点。

受检异常的特点在于它强制要求开发人员在代码中进行显式的声明和捕获,否则就会产生编译错误。这种限制从好的方面来说,可以防止开发人员意外地忽略某些出错的情况,因为编译器不允许出现未被处理的受检异常;从不好的方面来说,受检异常对程序中的设计提出了更高的要求。不恰当地使用受检异常,会使代码中充斥着大量没有实际作用、只是为了通过编译而添加的代码。而非受检异常的特点是,如果不捕获异常,不会产生编译错误,异常会在运行时刻才被抛出。

非受检异常的好处是可以去掉一些不需要的异常处理代码,而不好之处是开发人员可能忽略某些应该处理的异常。一个典型的例子是把字符串转换成数字时会发生java.lang.NumberFormatException异常,忽略该异常可能导致一个错误的输入就造成整个程序退出。

目前的主流意见是,最好优先使用非受检异常。

4.自定义异常

前面所讲的异常,都是系统自带的,系统自己处理,但是很多时候项目会出现特有问题,而这些问题并未被java所描述并封装成对象,所以对于这些特有的问题可以按照java的对问题封装的思想,将特有的问题进行自定义异常封装。在Java中要想创建自定义异常,需要继承Throwable或者他的子类Exception。

1.继承类

一般会选择继承Exception或RuntimeException,如果不要求调用者一定要处理抛出的异常,就继承RuntimeException。
目前业界推荐使用继承RuntimeException。

2.自定义异常类构造方法

class  自定义异常类 extends 异常类型(Exception){

 	/** 因为父类已经把异常信息的操作都完成了,所在子类只要在构造时,
 	将异常信息传递给父类通过super 语句即可。**/
  	// 具体有哪些构造方法有参或者无参可以查看父类的API。
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值