Throwable


Throwable

java.lang.Throwable - 异常和错误的顶级的类

两个分支:

  1. java.lang.Error - 错误 - 错误一旦发生,程序员是么有办法进行扭转的 - 不需要在代码中进行处理.

    1-1. 子类VirtualMachineError虚拟机级别的错误

    ​ 1-1-1. 子类java.lang.StackOverflowError 堆栈溢出 - 应用程序因为递归太深没有指定出口的时候.

    ​ 1-1-2. 子类java.lang.OutOfMemoryError 内存泄漏 - [GC垃圾回收机制 - 后台自动回收垃圾对象]

  2. java.lang.Exception - 异常 - 程序在运行的过程中发生了不正常的情况.

异常的分类

运行时异常[RuntimeException]都是非运行时异常的子类[Exception]

  1. 运行时异常 - 未检测异常

    顶级的父类java.lang.RuntimeException

    1. java.lang.NullPointerException - 空指针异常

    2. java.util.InputMismatchException - 输入不匹配异常

      Scanner sc = new Scanner(System.in);
      int n = sc.nextInt();//只能获取整数.但是输入了一个字符串"abc"
      
    3. java.lang.ArithmeticException - 分母为0

    4. java.lang.IllegalArgumentException - 非法参数异常

      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      构造中的模板如果传入了一个非法模板
      
    5. java.lang.IndexOutOfBoundsException - 下标越界异常 - 比如list.get(100);

      5-1. java.lang.StringIndexOutOfBoundsException - 字符串下标越界异常

      5-2. java.lang.ArrayIndexOutOfBoundsException - 数组下标越界异常

    6. java.util.NoSuchElementException - 不存在此元素

       LinkedList<Character> list = new LinkedList<>();
       System.out.println(list.getFirst());//获取栈顶元素,但是栈顶没有元素
      
    7. java.lang.ClassCastException - 类型转换失败异常

      父类类型转换成子类类型之前,推荐先使用instanceof关键字进行类型的判断
      
  2. 非运行时异常 - 已检测异常

    1. java.text.ParseException - 解析失败异常 - 字符串的模板和pattern不匹配

    2. InterruptedException - 中断异常 - Thread.sleep(1000);

    3. java.lang.CloneNotSupportedException - 不允许被clone.

      当调用对象的clone方法,但是这个对象没有去实现java.lang.Cloneable接口
      
    4. java.io.IOExcetion - IO流异常

      4-1. java.io.EOFException - 已经读取到文件的末尾了.

      4-2. java.io.FileNotFoundException - 文件找不到异常

    5. java.sql.SQLException - SQL异常,比如程序中的sql语句要是写错了.

异常的处理方式

  1. 运行时异常不需要处理(也是可以处理的),只需要在编程的时候,注意一下验证/判断.稍微谨慎一点.

  2. 非运行时异常 - 编译期间就需要立即对其进行处理.处理的方式有俩种.一种是积极处理 - try..catch的方式

    另外一种是消极处理.

积极处理方式

  1. 语法一 - try….catch….catch….finally

    推荐使用到的 - 因为针对每种不同的异常进行单独的日志记录,单独的异常处理.

    try{
       //code..
      //code..
    }catch(异常类型1 e1){
      
    }catch(异常类型2 e2){
      
    }finally{
      //无论是否出现异常,都会执行
    }
    注意:上方的异常类型不能是下方的异常类型的父类.
    
  2. 语法二 - jdk7.0提供的新的写法

    try{
      //code...
      //code...
    }catch(异常类型1 | 异常类型2){
      //...
    }
    
  3. 语法三 - 简单粗暴

    try{
      //....
    }catch(异常总父类){
      //...
    }
    

消极处理

比如在某个方法中某些代码出现了非运行时异常,那么在自己方法的内部”不着急”去积极处理.而是把这个异常抛出去了.

为了自己不处理,而是抛出去? - 因为这个方法有可能会被反复在其他地方调用 - 原则:谁调用,谁负责最终处理.

原则谨记 - 不要把异常抛给main方法,等同于把异常抛给jvm,等同于一旦出现异常,程序就会崩溃.

  1. 直接在方法的签名[声明]上使用throws关键字+异常类型1,异常类型2

  2. 在方法体中使用throw+异常对象

    public static void d(int n) throws FileNotFoundException {
      if(n==0){
        //System.out.println("异常的描述....");
    
        //throw + 运行时异常对象,不需要在方法的签名上抛出异常 - 本身运行时异常就不需要处理呀!
        //throw new RuntimeException("发生异常了...");
    
        //throw + 非运行时异常 配合 必须要在方法的签名上throws+非运行时异常类型
        throw new FileNotFoundException("文件不存在!");
      }
      System.out.println("n:"+n);
    }
    

笔试题 - throws和throw有什么区别

笔试题1

try{
  //code...
  //code..
  return;//结束整个方法
}catch(异常类型 e){
  
}catch(异常类型 e){
  
}finally{
  //无论是否出现异常,都会执行
}
假设try{}中没有任何异常发生,所有的code都会顺利执行.
1. finally中的代码执行否? - 肯定会执行
2. return语句是在finally块之前执行还是之后执行? - 之后

笔试题2

package tech.aistar.day12.exception;

/**
 * 本类用来演示: 笔试题
 *
 * @author: success
 * @date: 2021/8/4 3:23 下午
 */
public class FinallyDemo {
    public static void main(String[] args) {
        System.out.println(test());//1

        System.out.println(change());//A{age=200}
    }

    //finally中修改了基本数据类型
    public static int test(){
        int i = 0;//①

        //try可以直接和finally一起使用....
        try{
            //此处将i自增后的结果缓存起来了.并且这个缓存的结果就是作为最终返回出去的一个结果 - 对待基本数据类型.
            return ++i;
        }finally {
            ++i;//③
            System.out.println("i:"+i);
        }
    }

    //finally修改了对象类型的属性
    public static A change(){
        A a = new A();
        try{
            a.age = 100;
            //return是在finally之后执行
            return a;
        }finally {
            //对待对象类型 - finally中的修改对象的属性值,是对return的结果是产生了影响的.
            a.age = 200;
        }
    }
}
class A{
    public int age = 18;

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("A{");
        sb.append("age=").append(age);
        sb.append('}');
        return sb.toString();
    }
}

笔试题3

final和finally和finalize三者之间的区别? - 一点关系都没有

  1. final

    a. 修饰的局部变量一旦赋值成功,不可改变

    b. 修饰的属性一旦赋值成功,不可改变

    c. 修饰的类不可被继承

    d. 修饰的方法不可被重写

  1. finally

    a. 一般是和try..catch搭配使用的.try块中无论是否出现异常,finally块中代码都会执行

    b. finally块中一般写的是释放或者关闭资源的代码

  1. finalize - Object类中提供的方法

    a. 当GC想去回收一个垃圾对象之前,会去调用这个对象的finalize方法.是由JVM去调用.

    b. 该方法未必一定会被调用得到.

自定义异常

项目中其实是专门包exception - 专门自定义自己的异常[大量的]

jdk内置的异常不够用,不符合实际的业务场景.

步骤

  1. 写一个异常类继承java.lang.Exception
  2. 提供父类的5个构造方法即可

思考为什么要自定义异常

System.out.println("余额小于0");
         
throw new BalanceLtZeroException("余额小于0!");

场景:有的时候访问某些网站的时候 - 跳转到一个友好的页面 - 显示比如服务器正在维护/升级…

我们应该提供一个异常处理器 - 会监控软件程序在整个项目运行的过程中发生的一切异常.

一旦它发现了某个地方产生了异常,那么它就会对这些异常进行一个日志记录,然后再让程序跳转到一个友好的界面.

SpringMVC/SpringBoot - 异常处理器 - 只认识异常.

复习

  1. 重点围绕OO - 面向对象
  2. 三大特性 - 封装,继承,多态
  3. 抽象类和接口区别
  4. 四种访问修饰符的作用权限
  5. 方法的重载和方法的重写
  6. 单例 - 双重检测锁
  7. 简单工厂
  8. static关键字的作用 - static练习

预习

  1. 泛型

  2. IO流 - 大头

  3. 并发编程 - 多线程 - 大头中的大头 - 最难的最难的最难的

  4. 反射技术 - 看懂框架的源码[反射技术 + 设计模式]

  5. 动态代理 - [jdk动态代理 + cglib动态代理]

  6. 枚举类型


文章作者: 码农耕地人
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 码农耕地人 !
  目录