2022-07-29 第八组 卢睿 学习心得

Java 异常处理

今日重点

  1. Exception
  2. try...catch
  3. 异常链
  4. throws
  5. finally关键字
  6. 编译期异常
  7. 运行期异常
  8. try...catch..finally
  9. 自定义异常类

思维导图

image

学习心得

今天学到了异常处理,个人感觉主要就是try...catch,throws,finally和自定义异常类,try...catch就是捕获异常,使程序能够正常运行,throws就是抛出去异常,但是最终还要处理,不要抛给虚拟机处理,finally就是最终一定执行一次,自定义异常就是遇到Exception类里面没有的异常,需要自己定义异常,开发中也会经常使用。异常处理主要还是配合别的知识一块运用的。

异常处理

  1. 下标越界
  2. 空指针
  3. 类型转换异常
  4. 数字格式化
  5. 算术异常(数学异常)

编程界:

  1. 除数为0
  2. IO流,没有关闭
  3. 停电

当一个程序抛出异常时,抛异常后面的语句不再执行,类似于return的功能,终止方法的执行。

public class Ch01 {

    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        if(num2 != 0){
            System.out.println(num1 / num2);
        }
//        double num2 = 0;
//        BigDecimal bigDecimal1 = new BigDecimal(13.0);
//        BigDecimal bigDecimal2 = new BigDecimal(0);
//        System.out.println(bigDecimal1.divide(bigDecimal2));
        System.out.println("我很重要...");
    }
}

异常的继承体系结构

最顶级的Throwable:错误,异常

Error

正常情况下,不太可能出现的。绝大多数Error都会导致程序处于非正常的状态下,很难恢复。外力的作用下,不考虑。Error是Throwable的子类。它是在Java程序处理范围之外的。

Exception

Java语言中,将程序执行中发生的不正常的情况称之为异常。

  • 编译期异常:写代码的时候,抛异常。如果编译器不解决,会编译不通过,一直报红。

  • 运行期异常:RuntimeException,运行时会抛异常,平时没事

  • 自定义异常:

Java中异常机制,但是结合实际业务。

怎么自定义异常?

  1. 所有异常必须是Throwable的子类(大材小用,没必要)
  2. 如果要定义一个编译期异常,需要继承Exception类。
  3. 如果要定义一个运行期异常,需要继承RuntimeException类。
public class Ch02 {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 2;
        try{
            // 把有可能抛异常的代码放到try语句块里
            System.out.println(num1 / num2);
        }catch (Exception e){
            System.out.println("除数不能为0");
            e.printStackTrace();
        }
        System.out.println("我很重要...");
    }
}

try...catch

在一个语句块中,如果使用throw抛出一个编译期异常,就必须在方法的声明处使用throws关键字来标记异常类型
还有一种处理方式,就是直接try...catch
我们为什么要手动抛异常?
因为要配合全局异常处理机制来解决问题

public class Ch03 {

    public static void fun(int i,int j) throws MyException {
        if(j == 0){
            throw new MyException("除数不能为0");
        }
        System.out.println(i / j);
    }

    public static void main(String[] args) {
        try {
            fun(1,1);
        } catch (MyException e) {
            // 打印异常信息
            e.printStackTrace();
        }
    }
}

throw语句是可以当做方法的返回值的。
在一个有返回值的方法中,如果有条件分支,一定要保证每种情况下都有返回值,哪怕是抛异常。
开发中,大部分情况下使用的都是运行期异常!!!

public class Ch04 {

    public static String show(String str) {
        if(!Objects.isNull(str)){
            return str.concat("hello");
        }
//        throw new RuntimeException("参数不能是空");
        throw new ServiceException(101,"账号不能为空。");
    }

    public static void main(String[] args) {
        show(null);
    }
}

异常链

一个异常被抛出去之后会继续被调用这个方法的方法捕获或抛出,异常会扩散。
只要说解决异常,处理异常,捕获,就是try...catch。

class A{
    public void a() {
        throw new ServiceException(201,"业务异常...");
    }
}
class B {
    public void b() {
        A aa = new A();
        try {
            aa.a();
        } catch (Exception e) {
           e.printStackTrace();
        }
        System.out.println("b方法的语句");
    }
}
class C {
    public void c(){
        B b = new B();
        b.b();
        System.out.println("c方法的语句..");
    }
}
public class Ch05 {

    public static void main(String[] args) {
        C c = new C();
        c.c();
        System.out.println("Ch05的语句");
    }
}

throws

如果一个方法没有捕获一个编译期异常,该方法必须使用throws来声明。
throws并不是真正的解决了异常,只是把异常抛给了下一级调用者。

throws出现在什么地方?
方法的声明处,抛出多个异常,用逗号隔开。

public class Ch06 {

    public void show() throws MyException,RuntimeException,NullPointerException,IndexOutOfBoundsException {

    }

    public void info() throws MyException {
        show();
    }

    // JVM
    public static void main(String[] args) {
        try {
            new Ch06().info();
        } catch (MyException e) {
            throw new RuntimeException(e);
        }
    }
}

finally关键字

finally用来创建在try代码块后面执行的代码块
无论是否发生异常,finally代码块中的代码一定会执行。一般finally中的代码都是用来释放资源。
try...catch...finally

public class Ch07 {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 2;
        String str = null;
        try {
            System.out.println(num1 / num2);
            System.out.println(str.length());
//            main(args);
        }finally{
            System.out.println("finally...");
        }
    }
}

catch

catch可以写多个,有顺序问题。
先写小的,再写大的

public class Ch08 {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        try {
            System.out.println(num1 / num2);
            // 开发角度来说,应该写指定的。
        } catch (ArithmeticException e) {
//            e.printStackTrace();
            System.out.println("除数不能为0");
        } catch (Exception e){
            System.out.println("未知错误");
        }
    }
}

方法的重写

重写的方法不能抛出比被重写方法更大的异常类型

interface Inter01 {

    void show() throws Exception;
}

public class Ch09 implements Inter01  {

    @Override
    public void show() throws NullPointerException {

    }
}

编译期异常

public class MyException extends Exception  {

    public MyException(String message) {
        super(message);
    }
}

运行期异常

public class MyRuntimeException extends RuntimeException {

    public MyRuntimeException(String message) {
        super(message);
    }
}

try...catch..finally执行顺序

finally永远是在最后执行的

public class Question01 {

    public static int test1(){
        int i = 10;
        try {
            i++;
            System.out.println("try:" + i);
        }catch (Exception e){
            i--;
            System.out.println("catch:" + i);
        }finally {
            i = 100;
            System.out.println("finally:" + i);
        }
        return i;
    }

    public static int test2(){
        int i = 10;
        try {
            i++;
//            System.out.println("try:" + i);
            throw new Exception();
        }catch (Exception e){
            i--;
            System.out.println("catch:" + i);
        }finally {
            i = 100;
            System.out.println("finally:" + i);
        }
        return i;
    }
    // try---finally---return
    public static int test3(){
        int i = 10;
        try {
            i++;
            System.out.println("try:" + i);
            return i;
        }catch (Exception e){
            i--;
            System.out.println("catch:" + i);
            return i;
        }finally {
            i = 100;
            System.out.println("finally:" + i);
        }
    }
    // try...finally...return
    public static int test4(){
        int i = 10;
        try {
            i++;
            System.out.println("try:" + i);
//            System.exit(-1);
            return i;
//            i = 100;
//            System.out.println("finally:" + i);
        }catch (Exception e){
            i--;
            System.out.println("catch:" + i);
            return i;
        }finally {
            i = 100;
            System.out.println("finally:" + i);
//            return i;
        }
    }

    public static void main(String[] args) {
//        System.out.println(test1());
//        System.out.println(test2());
//        System.out.println(test3());
        System.out.println(test4());
    }
}

自定义异常类

错误码通常使我们自己定义的规则:
例如:

  • 100-成功
  • 101-账号不存在
  • 102-账号格式不对
  • 103-账号已存在
public class ServiceException extends RuntimeException {

    // 错误码
    private Integer code;

    // 异常信息
    private String message;

    public ServiceException() {
    }

    public ServiceException(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
posted @ 2022-07-29 20:30  LegendR  阅读(41)  评论(0)    收藏  举报