✨✨谢谢大家捧场,祝屏幕前的小伙伴们每天都有好运相伴左右,一定要天天开心哦!✨✨ 🎈🎈作者主页: 🎈丠丠64-CSDN博客🎈
✨✨ 帅哥美女们,我们共同加油!一起进步!✨✨
目录
一、前言
二、Exception 类的层次
三、异常的分类
1.编译时异常
2.运行时异常
四、异常的处理
1.异常的抛出throw
2.异常声明throws
3.try-catch捕获并处理
4.finally
五、自定义异常类
一、前言
在 Java 中,异常处理是一种重要的编程概念,用于处理程序执行过程中可能出现的错误或异常情况。异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。
二、Exception 类的层次
所有的异常类是从 java.lang.Exception 类继承的子类
Throwable:是异常体系的顶层类,其派生出两个重要的子类, Error 和 ExceptionError:错误指的是Java虚拟机无法解决的严重问题Exception:异常产生后程序员可以通过代码进行处理,使程序继续执行
三、异常的分类
1.编译时异常
在程序编译期间发生的异常,称为编译时异常,也称为受检查异常
public class Test {
private String name;
private String gender;
int age;
@Override
public Test clone() {
return (Test)super.clone();
}
}
像这样在没有编译之前就报错 提醒的称为编译时异常,不包括语法错误!
2.运行时异常
在程序执行期间发生的异常,称为运行时异常,也称为非受检查异常
System.out.println(10 / 0); //算数异常
int[] arr = {1, 2, 3}; //数组越界异常
System.out.println(arr[100]);
int[] arr = null; //空指针异常
System.out.println(arr.length);
这些在编译时没问题,运行时有问题的称为异常时处理
四、异常的处理
如果本方法中没有合适的处理异常的方式, 就会沿着调用栈向上传递,如果向上一直传递都没有合适的方法处理异常, 最终就会交给 JVM 处理, 程序就会异常终止
1.异常的抛出throw
在编写程序时,如果程序中出现错误,此时就需要将错误的信息告知给调用者
throw new
XXXException
(
"
异常产生的原因
"
);
这就是一段自定义异常的抛出
int a = 0;
if(a == 0){
throw new ArithmeticException("异常为 a = 0");
}
2.异常声明throws
修饰符 返回值类型
方法名
(
参数列表
)
throws
异常类型
1
,异常类型
2
...{
}
抛出运行时异常是不需要处理的;但是如果是一个编译性异常,我们需要处理这个异常,最简单的方式就是通过throws处理(一搬放在方法声明的地方)
public static void main(String[] args) {
int a = 0;
if(a == 0){
throw new CloneNotSupportedException("异常为 a = 0");
}
}
加上throws CloneNotSupportedException后,错误消失
调用声明抛出异常的方法时,调用者必须对该异常进行处理,或者继续使用
throws
抛出
public static void main(String[] args) {
test();
}
public static void test() throws CloneNotSupportedException{
int a = 0;
if(a == 0){
throw new CloneNotSupportedException("异常为 a = 0");
}
}
我们发现Test问题向上抛给main处理,但main没有处理继续向上抛,所以报错,解决方案有两种
一种是异常再声明声明一下 throws
3.try-catch捕获并处理
第二种使用try-catch捕获并处理
throws
对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,由调用者处理。如果真正要对异常进行处理,就需要try-catch
语法格式:
try
{
//
将可能出现异常的代码放在这里
}
catch
(
要捕获的异常类型
e
){
//
如果
try
中的代码抛出异常了,此处
catch
捕获时异常类型与
try
中抛出的异常类型一致时,或者是
try
中抛出异常的基类时,就会被捕获到
//
对异常就可以正常处理,处理完成后,跳出
try-catch
结构,继续执行后序代码
}
catch
(
异常类型
e
){
//
对异常进行处理
}
finally
{
//
此处代码一定会被执行到
}
public static void main(String[] args){
try {
int a = 10 / 0;
}catch (ArithmeticException e){
System.out.println("捕获到了异常");
}
System.out.println("后续的代码");
}
异常成功捕获,由程序员处理,退出代码为0
try {
int a = 10 / 0;
}catch (NullPointerException e){
System.out.println("捕获到了异常");
}
System.out.println("后续的代码");
}
异常捕获失败,异常类型不匹配,也就不会被处理,继续往外抛,直到JVM收到后中断程序,退出代码为1
异常一旦抛出,其后的代码就不会执行
try {
int a = 10 / 0;
System.out.println("66666666");
}catch (ArithmeticException e){
System.out.println("捕获到了异常");
}
System.out.println("后续的代码");
我们发现当异常抛出后,异常后面代码将不会执行
try
中可能会抛出多个不同的异常对象,则必须用多个
catch
来捕获,但是只能抛出一个异常
public static void main(String[] args){
try {
int a = 10 / 0;
}catch (ArithmeticException e){
System.out.println("捕获到了异常111");
}catch (NullPointerException e){
System.out.println("捕获到了异常222");
}
System.out.println("后续的代码");
}
如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则则会报错
public static void main(String[] args){
try {
int a = 10 / 0;
}catch (Exception e){
System.out.println("捕获到了异常111");
}catch (NullPointerException e){
System.out.println("捕获到了异常222");
}
System.out.println("后续的代码");
}
Exception 是所有异常的父类,所以报错
4.finally
有些特定的代码,不论程序是否发生异常,都需要执行,在程序正常或者异常退出时,必须要对资源进进行回收,异常会引发程序的跳转,可能导致有些语句执行不到
,
finally
就是用来解决这个问题的
语法格式:
try
{
//
可能会发生异常的代码
}
catch
(
异常类型
e
){
//
对捕获到的异常进行处理
}
finally
{
//
此处的语句无论是否发生异常,都会被执行到
}
//
如果没有抛出异常,或者异常被捕获处理了,这里的代码也会执行
public static void main(String[] args) {
try {
int a = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("捕获到了异常");
} finally {
System.out.println("finally代码");
}
System.out.println("后续的代码");
}
finally
中的代码一定会执行的,一般在
finally
中进行一些资源清理的扫尾工作
五、自定义异常类
我们先看一段代码
public class LogIn {
private String userName = "admin";
private String password = "123456";
public void loginInfo(String userName, String password) {
if (!this.userName.equals(userName)) {
System.out.println("名字错误");
}
if (!this.password.equals(password)) {
System.out.println("密码错误");
}
System.out.println("登陆成功");
}
public void main(String[] args) {
LogIn logIn = new LogIn();
logIn.loginInfo("admin", "123456");
}
}
此时我们在处理用户名密码错误的时候可能就需要抛出两种异常
.
我们可以基于已有的异常类进行扩展
(
继承
),
创建和我们业务相关的异常类
自定义异常类,然后继承自
Exception
或者
RunTimeException
继承自 Exception 的异常默认是受查异常 继承自 RuntimeException 的异常默认是非受查异常
class UserNameException extends RuntimeException {
public UserNameException() {
}
public UserNameException(String message) {
super(message);
}
}
class PasswordException extends Exception {
public PasswordException() {
}
public PasswordException(String message) {
super(message);
}
}
public class LogIn {
private String userName = "admin";
private String password = "123456";
public void loginInfo(String userName, String password) throws UserNameException,PasswordException{
if (!this.userName.equals(userName)) {
//System.out.println("名字错误");
throw new UserNameException("名字错误");
}
if (!this.password.equals(password)) {
//System.out.println("密码错误");
throw new PasswordException("密码错误");
}
System.out.println("登陆成功");
}
public static void main(String[] args) {
LogIn logIn = new LogIn();
try{
logIn.loginInfo("admin1", "123456");
} catch (PasswordException e) {
e.printStackTrace();
System.out.println("PasswordException");
}catch (UserNameException e) {
e.printStackTrace();
System.out.println("UserNameException");
}
}
}
这样就实现了自定义异常,使我们查找错误会特别方便
![](https://img-blog.csdnimg.cn/direct/09ffcbdc09674a67829f4b29b2ae98f1.png)
希望对你有帮助
|