🔎一个简单的异常
public static void main(String[] args) { System.out.println(1 / 0); }
红框表示异常就是一个class(类)
🔎异常的简单分类
🌻编译时异常/受查异常(IOException)
这是一个简单的编译时异常,需要在参数后面添加一个thorws声明,程序才能正常运行
如下
🌻运行时异常/非受查异常(RuntimeException)
public static void main(String[] args) { char[] arr = null; System.out.println(arr); System.out.println("运行时异常--空指针异常"); }
这是一个简单的运行时异常,是在程序执行时发生的异常
RunTimeException以及其子类对应的异常,都称为运行时异常
🔎异常的体系结构
红框表示Throwable是一个class(类)
🌻一个简单的Error
public static void func() { func(); } public static void main(String[] args) { func(); }
Error:指的是Java虚拟机无法解决的严重问题
比如:JVM的内部错误、资源耗尽等
典型代表:StackOverflowError和OutOfMemoryError
🔎异常的处理
🌻 防御式编程
🌼 LBYL: Look Before You Leap
在操作之前就做充分的检查. 即:事前防御型
通俗点解释:
1.你认识一个女生很久了
2.你问她我可以拉你手吗
3.不可以
事前防御(doge)
🌼 EAFP: It’s Easier to Ask Forgiveness than Permission
先操作, 遇到问题再处理. 即:事后认错型
通俗点解释:
1.你认识一个女生很久了
2.你去拉她的手
3.Pia!(o ‵-′)ノ”(ノ﹏<。)
4.你挨了一个大嘴巴子
5.你给这个女生认错
6.你俩还是好朋友
事后认错(doge)
🌻 异常的抛出
🌼代码执行过程中产生异常
public static void main(String[] args) { int[] arr = {1,2,3}; System.out.println(arr[100]); }
🌼手动抛出异常
public static void method(int a,int b) { if(b == 0) { throw new ArithmeticException(); } System.out.println(a / b); } public static void main(String[] args) { method(2,0); }
注意事项:
手动抛出异常一般用于自定义的异常
throw必须写在方法体内部
抛出的对象必须是Exception及其子类
抛出的异常如果是RuntimeException及其子类,则可以不用处理
抛出的异常如果是IOException及其子类,则必须处理,否则编译无法通过
异常一旦抛出,其后的代码将不再执行
🌻 异常的捕获
🌼异常声明
作用:当他人看到这个方法时,声明可能会出现的异常
🌼异常捕获
public static void find(int b) throws CloneNotSupportedException {//声明可能存在的异常 if(b == 0) { throw new CloneNotSupportedException(); } System.out.println(b); } public static void main(String[] args) throws CloneNotSupportedException { try {//存放可能抛出异常的代码 find(0); }catch (CloneNotSupportedException e) { e.printStackTrace(); System.out.println("捕获到了 CloneNotSupportedException异常"); } System.out.println("没有异常的代码"); }
注意事项:
catch可以有多个
对于受查异常来说,try当中如果没有可能存在受查异常的代码catch便会报错
可以将多个catch写在同一行
当try中存在多个可能的异常时,执行顺序自上而下,与catch顺序无关
如果抛出的异常类型与cach捕获的类型不匹配,则继续向外抛,直到jvm进行处理,那么后面的代码也就不被执行了(finally例外)
catch可以有多个
对于受查异常来说,try当中如果没有可能存在受查异常的代码catch便会报错
可以将多个catch写在同一行
缺点是不能准确得出出现的问题是哪种异常
当try中存在多个可能的异常时,执行顺序自上而下,与catch顺序无关
如果抛出的异常类型与cach捕获的类型不匹配,则继续向外抛,直到jvm进行处理,那么后面的代码也就不被执行了(finally例外)
🌼finally
public static void main(String[] args) { try { int[] arr = {1,2,3}; System.out.println(arr[100]); }catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); System.out.println("捕获到了 ArrayIndexOutOfBoundsException异常"); }catch (NullPointerException e) { System.out.println("捕获到了 NullPointerException异常"); }finally { System.out.println("finally"); } System.out.println("没有异常的代码"); }
当抛出异常时,catch捕获到了异常,finally顺利执行,sout也正常执行
public static void main(String[] args) { try { int[] arr = {1,2,3}; System.out.println(arr[100]); }catch (ArithmeticException e) { e.printStackTrace(); System.out.println("捕获到了 ArithmeticException异常"); }catch (NullPointerException e) { System.out.println("捕获到了 NullPointerException异常"); }finally { System.out.println("finally"); } System.out.println("没有异常的代码"); }
当抛出异常时,catch未捕获到了异常,finally顺利执行,sout不执行
总结:
finally无论什么情况都会被执行
finally一般用于资源的释放(因为无论如何finally都会被执行)
🔎throw和throws的区别
throw代表抛出异常
throws代表声明异常,可用于编译(受查)异常,使其编译正常
🔎自定义异常类
小练习
自定义异常实现登录
实现一个简单的控制台版用户登陆程序
程序启动提示用户输入用户名密码
如果用户名密码出错
使用自定义异常的方式来处理
🌼Test类
public class Test { public String name; public String password; public Test(String name,String password) { this.name = name; this.password = password; } public void login(String name,String password) throws UserNameException,PasswordException { if(!this.name.equals(name)) { throw new UserNameException("用户名异常"); } if(!this.password.equals(password)) { throw new PasswordException("密码异常"); } } public static void main(String[] args) { Test test = new Test("bibubibu","biubiubiu"); try(Scanner scan = new Scanner(System.in)) { System.out.println("请输入你的用户名:"); String name = scan.nextLine(); System.out.println("请输入你的密码:"); String password = scan.nextLine(); test.login(name,password); }catch(UserNameException e) { e.printStackTrace(); System.out.println("用户名错误"); }catch(PasswordException e) { e.printStackTrace(); System.out.println("密码错误"); } } }
🌼UserNameException(用户名异常)
public class UserNameException extends RuntimeException{ public UserNameException(String s) { super(s); } }
🌼PasswordException(密码异常)
public class PasswordException extends RuntimeException{ public PasswordException(String s) { super(s); } }
🌼运行结果