异常
在程序运行过程中可能出现的错误情况,当程序出现异常时,会抛出异常对象,如果没有处理,则终止运行
异常类型
隶属于java.lang包下的一个类,每个异常类型都是一个类
最顶层的异常:Throwable
异常(Exception)分类:
1,运行时异常(RuntimeException及子类)
在编译时期不报错,运行时期才会体现,可以不处理
2,编译时异常(非RuntimeException)
编译时期就会报错,提醒代码可能发生异常,强制要求处理
顶层类:Throwable
1,Error:由虚拟机抛出的严重错误,程序无法处理
常见的Error包括OutOfMemoryError,StackOverflowError等
2,Exception:可以通过代码进行处理的问题,即异常
异常可分为:
编译时异常:Checked Exception
运行时异常:在程序执行期间的异常Unchecked Exception
异常处理
1,自己处理(抛出,捕获)
2,JVM处理(把异常的信息以红色字体打印在控制台,并终止程序)
防御式编程:throw,try,catch,finally,throws
一般在下层代码中抛出,上层代码中捕获
这样下层出现异常会被throws抛出,剩余代码不会被执行,而上层代码使用try-catch捕获,依旧能执行,在不会导致额外错误的同时,还能一眼看出是什么位置的代码出现了异常
throw:
手动抛出异常
throw之后的语句不会执行
使用throw关键字抛出异常对象
throw new 异常类名称(构造函数参数);
参数内可以写异常出现的原因,再用getMessage()方法打印
可以在代码的具体某个位置抛出特定异常
public static int divide(int numerator, int denominator) {
if (denominator <= 0) {
throw new IllegalArgumentException("除数必须大于 0");
}
return numerator / denominator;
}
异常处理:
throws:
使用throws关键字在方法声明中声明可能抛出的异常,当异常出现时,会在异常处创建异常对象(包含异常信息)
将异常对象抛出给调用者,调用方法的代码要么捕获异常要么继续向上抛出
运行时期异常一定会抛出给虚拟机处理,无需手写抛出
如果抛给虚拟机会终止程序(闪退)
throws之后的代码也不会执行
public void methodName() throws ExceptionType1, ExceptionType2 {
// 抛出异常的代码
}
try-catch:
try{
//可能出现异常的代码,在抛出异常位置之后的代码不会被执行
}catch(需要捕获的异常类型 e){
//*如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时,或者是try中抛出异常的基类* 时,就会被捕获到
//在此代码块中处理异常
}
catch(处理异常类型 e2){
}finally(){
//无论是否被捕获都会被执行
//即使在trycatch语句中执行return语句,finally语句仍会执行
//finally不是try-catch中的必需结构
}
如果异常被捕获了,try-catch以后的代码一定会执行,但如果没有捕获到正确异常,后续代码不会被执行,如果没有出现异常,catch中的代码不会被执行
可以通过捕获Exception类来捕获所有类型的异常
可以使用e.printStackTrace()来查看异常代码的调用栈
如果没有找到匹配的异常类型,会向上传递寻求异常处理方案,直到main方法,如果仍未处理,则交给虚拟机处理
可以使用异常的printStackTrace()方法来查看异常信息(原因,类型,位置)
自定义异常
在编写程序时,根据特定需求自定义的异常类,继承自Java内置的Exception或者RuntimeException类,用于在程序运行过程中抛出特定的异常情况
抛出一个更符合代码实际意义的异常,更加见名知意
public class TestException extends Exception{
TestException(String message){
super(message);//message为会打印的错误信息
}
}
应用场景
1,遇到特定的异常情况,通过自定义异常来抛出并提供详细的异常信息,以便程序调试和错误处理
2,开发中的业务逻辑中,如果需要处理特定的异常情况,通过自定义异常去表示,并相应处理
3,自定义异常还可以在程序中定义特定的错误码,以便于在异常处理时进行更精确的判断和处理
异常的注意事项和应用
1,顺序:应遵循先捕获子类型异常再捕获父类型异常的顺序,因为java中的异常处理是基于继承关系,如果先捕获父类异常,子类异常将无法被捕获且报错
父类型一定要后于子类型捕获!!!
2,应根据具体情况进行具体处理,处理异常通过
打印异常信息
记录日志
或者是提供替代的逻辑
3,在处理异常时,应避免捕获所有异常而不做任何处理,会导致异常被吞没,无法及时发现和修复问题
4,在自定义异常时,应该提供有意义的异常信息,应该清晰,准确地描述异常的原因和可能的解决办法,以便于调试和问题排查
处理方式使用场景
1,捕获异常:
防止程序因为异常终止
对异常进行处理
2,抛出异常:
告知调用者,由调用者处理异常
逐层传递直到有人处理异常