文章目录
1.异常是什么?
异常指的就是程序在 运行时 出现错误时通知调用者的一种 机制。
- 有些错误是这样的, 例如将
System.out.println
拼写错了, 写成了system.out.println
. 此时编译过程中就会出错, 这是 “编译期” 出错。- 而 “运行时” 指的是程序已经编译通过得到 class 文件了, 再由 JVM 执行过程中出现的错误。
异常的种类有很多, 不同种类的异常具有不同的含义, 也有不同的处理方式。
2.防御式编程
异常的核心思想就是 EAFP。
错误在代码中是客观存在的,我们有两种主要的方式:
- LBYL: Look Before You Leap. 在操作之前就做充分的检查。
- EAFP: It’s Easier to Ask Forgiveness than Permission. “事后获取原谅比事前获取许可更容易”. 也就是先操作, 遇到问题再处理。
3.抛异常
语法:throw 异常类型的对象
public static void main(String[] args) {
System.out.println(divide(3,0));
}
public static int divide(int x, int y) {
if (y == 0) {
throw new ArithmeticException("抛出除 0 异常");
}
return x / y;
}
运行结果:
4.捕获异常
语法:try-catch-finally //若有try,则catch、finally至少要有一个
try{
有可能出现异常的语句 ;
}[catch (异常类型 异常对象) {
} ... ]
[finally {
异常的出口
}]
- try 代码块中放的是可能出现异常的代码。
- catch 代码块中放的是出现异常后的处理行为。
- finally 代码块中的代码用于处理善后工作(关闭连接、释放资源、释放锁等), 会在最后执行。
- 其中 catch 和 finally 都可以根据情况选择加或者不加。
4.1try-catch-finally执行逻辑
异常处理流程::
1.程序中先执行 try 里面的代码。
2.如果try中的代码出现异常,就会结束try中的其他代码.检查当前异常和catch中声明的异常类型是否匹配(是声明的异常类型的子类或者类型完全相同)。
3.如果找到匹配的异常类型,这个异常就被当前catch捕获了.就执行catch中的代码。
4.如果没找到匹配的异常类型,这个异常就会沿着调用栈,传递给方法的调用者。
5.无论是否找到匹配类型catch 语句, finally 都-定会在该方法结束前被执行到。
6.如果上层调用者,也没有合适的catch 代码,异常还是要继续传递给调用者。
7.如果一直向 上传递到main方法,都没有合适的catch语句,最终就交给 JVM 来处理。
try{
String str = null;
System.out.println(str.length());
System.out.println("str.lrngth() 之后的代码"); //异常后面的代码不执行
}catch (NullPointerException e){
System.out.println("捕捉到空指针异常");
}catch (Exception e){
System.out.println("异常已经捕捉了"); //异常已经被捕捉了 不执行
}finally {
System.out.println("无论如何都要执行finally");
//即使 try 或 catch 中包含 return 语句,finall 依旧会被执行
}
运行结果:
注意:
1.如果 try/catch 中有 return,finally 中也有 return ,则原来的 try/catch 中的 return 不执行。
2.如果 try/catch 中有 return,则 finally 中的代码会在 return 之前执行。
static int fun(){
try{
System.out.println("try 里不触发异常代码");
return 1;
} catch (NullPointerException e){
System.out.println("catch 捕捉到异常处理");
return 2;
}catch (Exception e){
System.out.println("异常已经捕捉了"); //不执行
}finally {
System.out.println("无论如何都要执行finally");
return 3;
}
}
//main方法中调用
System.out.println(fun());
运行结果:
static int fun2(){
try{
System.out.println("try 里不触发异常代码");
String s = null;
System.out.println(s.length());
System.out.println("str.lrngth() 之后的代码");
return 1;
} catch (NullPointerException e){
System.out.println("catch 捕捉到异常处理");
return 2;
}catch (Exception e){
System.out.println("异常已经捕捉了");
}finally {
System.out.println("无论如何都要执行finally");
}
return 3;
}
//main方法中调用
System.out.println(fun());
运行结果:
4.2出现异常之后的处理逻辑
1.直接让程序结束:对于致命问题。
2.打印日志:对于普通问题,可以记录一下出现问题的原因 / 代码位置。e.printStackTrace(); // 异常的调用栈,将 JVM 栈里面的方法之间的调用关系打印出来
3.给程序员通知:短信/电话/微信等。
5.异常体系
- 顶层类
Throwable
派生出两个重要的子类, Error 和 Exception - 其中
Error
指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常. 这种内部错误一旦出现,除了告知用户并使程序终止之外, 再无能无力. 这种情况很少出现. Exception
是我们程序猿所使用的异常类的父类.- 其中
Exception
有一个子类称为RuntimeException
, 这里面又派生出很多我们常见的异常类NullPointerException
,IndexOutOfBoundsException
等.
5.1哪些异常需要 catch ?
1)无法恢复的错误,例如:环境整个都出问题了、硬盘坏了、电量不足等——Error,Erro类型一般不会catch(Erroe指的是 Java 运行时内部错误和资源耗尽错误.,应用程序不抛出此类异常)。
2) 程序员导致的错误,例如:BUG等——继承子RuntimException,BUG尽早暴露,一般也不catch。
3)有机会修复的错误,例如:网络慢了、磁盘慢了等——catch并尝试修复。
- 如果程序正常结束,进程退出码 0 ;如果出现异常结束,此时退出码 非0。
6.定义异常
创建异常类,自定义的异常类如果继承自 Exception
,此时就是一个受查异常;如果继承自 RuntimeException
就是一个非受查异常。
自定义的异常类建议继承自 Exception
,毕竟自己创建的异常类,意图是想进行更进一步的处理的. 如果继承自 RuntimeException
就可能最终遗忘对异常进行处理。
7.异常分类
- 受查异常(checked exception):
Exception
类的子类,但不包含RuntimeException
的子类 - 非受查异常(unchecked exception):
Error
类的子类、RuntimeException
类的子类。
注意:不要从Error继承非受查异常。
8.为什么java设计时分受查和非受查异常?
答:受查异常——可恢复的异常,必须显示处理(I.使用try catch处理 II.使用 throws 把异常交给发放调用者处理);非受查异常——不用去catch。
9.受查异常在语法上有哪些特殊要求?
答:如果一个方法可能抛出受查类型的异常,则方法声明中必须给出一个异常列表说明。
10.Demo
class CheckedException extends Exception{ //受查异常
}
class CheckedException2 extends Exception{ //受查异常
}
class UnCheckedException extends RuntimeException{ //非受查异常
}
public class ExceptionDemo {
public static void throwCheckedException() throws CheckedException, CheckedException2{
if(true){
throw new CheckedException();
}else{
throw new CheckedException2();
}
}
public static void main(String[] args)throws CheckedException, CheckedException2 {
throwCheckedException(); //传染性强 必须给出异常列表说明
}
}