🔎一个简单的异常
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);
}
}