异常

异常

一、什么是异常

程序在运行过程当中发生的问题

package com.mine.demo01;

public class Main1 {
    public static void main(String[] args) {
        System.out.println("发生异常前");
        int i = 1 / 0; //这里发生异常
        System.out.println("发生异常后");
    }
}


结果:
发生异常前
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.mine.demo01.Main1.main(Main1.java:6)

结论:

异常会打断程序的进行

什么是异常?

所以异常当然是指程序运行过程当中出现的问题,但是其本质,就是一个标识。

二、异常的结构和分类

1.Throwable:是所有异常和错误的共同父类

2.Error:错误是不可挽回的,不可修改的。(编译错误,类的缺失)

3.Exception:异常,是可以通过程序修正的。修正并不是把问题修改到没有,而是去进行策略上的弥补。

​ a.Exception:受查异常(要么捕获,要么抛出)

​ b.RuntimeException:运行时异常

三、异常的处理方式

1.异常的捕获

package com.mine.demo01;

public class Main1 {
    public static void main(String[] args) {
        System.out.println("发生异常前");
        try {
            int i = 1 / 0; //这里发生异常
        }catch (ArithmeticException e){
            e.printStackTrace();//打印异常的堆栈信息
        }
        System.out.println("发生异常后");
    }
}


结果:
发生异常前
发生异常后
java.lang.ArithmeticException: / by zero
	at com.mine.demo01.Main1.main(Main1.java:7)

结论:尽管异常发生了,但程序依然继续运行

(1)使用try,捕获某个区域当中,可能会发生的异常

(2)catch用于匹配异常

package com.mine.demo01;

public class Main1 {
    public static void main(String[] args) {
        System.out.println("发生异常前");
        try {
            int i = 1 / 0; //这里发生异常
        }catch (NullPointerException e){
            e.printStackTrace();//打印异常的堆栈信息
        }
        System.out.println("发生异常后");
    }
}


结果:
发生异常前
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.mine.demo01.Main1.main(Main1.java:7)

如果异常不匹配,则try-catch不生效

(3)多catch匹配可以同时捕获多种异常

package com.mine.demo01;

public class Main1 {
    public static void main(String[] args) {
        System.out.println("发生异常前");
        try {
            int i = 1 / 0; //这里发生异常
        }catch (NullPointerException e){
            e.printStackTrace();//打印异常的堆栈信息
        }catch (ArithmeticException e){
            e.printStackTrace();//打印异常的堆栈信息
        }
        System.out.println("发生异常后");
    }
}


结果:
发生异常前
发生异常后
java.lang.ArithmeticException: / by zero
	at com.mine.demo01.Main1.main(Main1.java:7)
package com.mine.demo01;

public class Main1 {
    public static void main(String[] args) {
        System.out.println("发生异常前");
        try {
            String str = null;
            str.length();//这里发生异常,终止try当中的运行,直接抵达catch
            int i = 1 / 0;
        }catch (NullPointerException e){
            e.printStackTrace();//打印异常的堆栈信息
        }catch (ArithmeticException e){
            e.printStackTrace();//打印异常的堆栈信息
        }
        System.out.println("发生异常后");
    }
}


结果:
发生异常前
发生异常后
java.lang.NullPointerException
	at com.mine.demo01.Main1.main(Main1.java:8)

注意:在try当中,只要发生异常,try代码块中无论还有多少代码没执行,都将停止。抵达对应的异常catch,执行catch中的内容。

(4)在异常的catch列表当中,父类异常必须在后面

package com.mine.demo01;

public class Main1 {
    public static void main(String[] args) {
        System.out.println("发生异常前");
        try {
            String str = null;
            str.length();//这里发生异常,终止try当中的运行,直接抵达catch
            int i = 1 / 0;
        }catch (NullPointerException e){
            e.printStackTrace();//打印异常的堆栈信息
        }catch (ArithmeticException e){
            e.printStackTrace();//打印异常的堆栈信息
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("发生异常后");
    }
}


(5)finally:无论如何都会被执行的代码块,即便return也无法阻止,想要阻止他,只能强制关闭虚拟机

package com.mine.demo01;

public class Main1 {
    public static void main(String[] args) {
        System.out.println("发生异常前");
        try {
            String str = null;
            str.length();//这里发生异常,终止try当中的运行,直接抵达catch
            int i = 1 / 0;

        }catch (NullPointerException e){
            e.printStackTrace();//打印异常的堆栈信息
        }catch (ArithmeticException e){
            e.printStackTrace();//打印异常的堆栈信息
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.exit(1);//强制关闭虚拟机
            System.out.println("无论如何都会执行");
        }
        System.out.println("发生异常后");
    }
}


结果:
发生异常前
java.lang.NullPointerException
	at com.mine.demo01.Main1.main(Main1.java:8)

一些应用场景:比如关闭连接,关闭流,等等。

2.自动抛出异常

checked异常通常可以考虑抛出

处理异常的策略:谁调用谁处理

C.java

package com.mine.demo01;

import java.text.ParseException;
import java.text.SimpleDateFormat;

public class C {
    public void fun() throws ParseException,Exception{
        SimpleDateFormat sdf = new SimpleDateFormat("");
        sdf.parse("");
    }
}

B.java

package com.mine.demo01;

public class B {
    C c = new C();
    public void fun() throws Exception{
        c.fun();
    }
}

A.java

package com.mine.demo01;

public class A {
    B b = new B();
    public void fun() throws Exception{
        b.fun();
    }
}

Main.java

package com.mine.demo01;

public class Main2 {
    public static void main(String[] args) {
        A a = new A();
        try { //捕获异常为最终处理异常的方式
            a.fun();
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}



异常的堆栈信息

Exception in thread "main" java.lang.RuntimeException: java.text.ParseException: Unparseable date: ""
	at com.mine.demo01.Main2.main(Main2.java:9)
Caused by: java.text.ParseException: Unparseable date: ""
	at java.text.DateFormat.parse(DateFormat.java:366)
	at com.mine.demo01.C.fun(C.java:9)
	at com.mine.demo01.B.fun(B.java:6)
	at com.mine.demo01.A.fun(A.java:6)
	at com.mine.demo01.Main2.main(Main2.java:7)

打印堆栈信息:e.printStackTrace();

最下面的是最开始的调用方法,最上面的是最开始出现异常的地方。

异常的信息包含:

1.异常的内容

2.异常的类型

3.异常所发生的类

4.异常所发生的方法

5.异常发生的位置,即行数

3.手动抛出异常

由开发者自己定义的异常行为

Person.java

package com.mine.demo02;

public class Person {
    private Integer age;

    public Integer getAge(){
        return age;
    }

    public void setAge(Integer age){
        if(age < 0 || age > 120){
            throw new RuntimeException("年龄不符合,您确定您是人类吗?");
        }
        this.age = age;
    }
}

Main.java

package com.mine.demo02;

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        person.setAge(250);
    }
}


结果:
Exception in thread "main" java.lang.RuntimeException: 年龄不符合,您确定您是人类吗?
	at com.mine.demo02.Person.setAge(Person.java:12)
	at com.mine.demo02.Main.main(Main.java:6)

4.自定义异常

自定义异常的创建方式

1.继承Exception或者RuntimeException

2.名字通常是XxxException

3.对父类构造进行调用

AgeBoundException.java

package com.mine.demo02;

public class AgeBoundException extends RuntimeException{
    private Integer age;
    public AgeBoundException(){
        super();
    }
    public AgeBoundException(String message){
        super(message);
    }

    public AgeBoundException(Throwable cause){
        super(cause);
    }
    public AgeBoundException(String message,Throwable cause){
        super(message,cause);
    }

    protected AgeBoundException(String message,Throwable cause,Boolean enableSuppression,boolean writableStackTrace){
        super(message, cause,enableSuppression,writableStackTrace);
    }
    public void setAge(Integer age){
        if(age < 0 || age > 120){
            throw new RuntimeException("年龄不符合,您确定您是人类吗?");
        }
        this.age = age;
    }
}

Main.java

package com.mine.demo02;

public class Main1 {
    public static void main(String[] args) {
        AgeBoundException ageBoundException = new AgeBoundException();
        ageBoundException.setAge(250);
    }
}


结果:
Exception in thread "main" java.lang.RuntimeException: 年龄不符合,您确定您是人类吗?
	at com.mine.demo02.AgeBoundException.setAge(AgeBoundException.java:24)
	at com.mine.demo02.Main1.main(Main1.java:6)
posted @ 2023-03-23 20:45  DFshmily  阅读(16)  评论(0编辑  收藏  举报