美文网首页
Java 异常体系

Java 异常体系

作者: bowen_wu | 来源:发表于2022-05-19 15:45 被阅读0次

    Java 异常体系

    Exception

    Exception 异常体系就是在 return 语句之外为方法提供另外一种出口

    Throwable
    • Throwable => checked exception => 可以被抛出的东西 => 有毒
    • Exception => checked exception => 受检异常 => 有毒 => 预料之内的异常 => 需要对预料之内的异常进行处理 => IOException => 可以恢复
    • RuntimeException => unchecked exception => 运行时异常,无毒 => 意料之外的 => Bug => 不需要声明
    • Error => unchecked exception => 错误,无毒 => 不能恢复的异常

    try catch finally

    • 在栈帧中一旦碰到 throw 它会结束当前栈帧,如果没有 try,异常将击穿所有栈帧,直到遇到 try catch
    • try catch finally 中的 finally 无论什么情况都会被执行,即使 try | catch 中有 return
    • finally 块中不建议写 return 语句,finally 块中最好的实践是执行资源的清理工作
    • catch 中做的事情
      1. 处理异常
      2. 在日志里打印异常
      3. 返回对应的对异常的处理
    • try-with-resources => JDK 7+ => try(content) {} => content 会在 finally 中自动的 close => 隐式的 finally =>
      content 必须实现 AutoCloseable interface

    throw vs throws

    • throw => 抛出一个 Throwable,终止方法当前的操作
    • throws => 只是一个声明 => 表示一个方法可能会抛出一个异常 => 后果:任何调用了它的方法都有被迫在自己的方法签名上丢一个 throws 语句或者加 try catch

    catch 的级联与合并

    级联

    public static void main(String[] args) {
        try{
            throwCheckedException();
        } catch (FileNotFoundException e) {
            System.out.println("文件没找到");
        } catch (EOFException e) {
            System.out.println("文件已到达末尾");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    catch 错误的顺序按照从小到大的顺序排列

    合并

    Java 7+ 才有合并

    public static void main(String[] args) {
        try{
            throwCheckedException();
        } catch (NullPointerException | IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalStateException | IllegalArgumentException e) {
            // 做点别的事情
        }
    }
    

    栈轨迹 & 异常链

    • StackTrace => 栈轨迹
    • Caused by => 异常链

    排查问题最重要的信息,没有之一

    class TestException {
        public static void main(String[] args) {
            try {
                processUserData();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        private static void processUserData() {
            int userId = 1;
            try {
                insetIntoDatabase();
            } catch (SQLException e) {
                throw new UserAlreadyExistException("插入 id 为" + userId + "的数据的时候发生了异常", e);
            }
        }
    
        private static void insetIntoDatabase() throws SQLException {
            throw new SQLException("重复的键值");
        }
    }
    
    class UserAlreadyExistException extends RuntimeException {
        public UserAlreadyExistException(String message, Throwable cause) {
            super(message, cause);
        }
    }
    
    Stack Trace & Caused by

    异常抛出原则

    • 能用 if else 处理的,不要使用异常(try catch)
      • 无法保证 catch 到的异常一定是想抓到的,可能错误的 catch 到了更深层次的异常
      • 相比于正常的 if 判断,异常的创建是非常,非常昂贵的操作
    • 尽早抛出异常 => 如果可以处理异常,则处理,如果处理不了,要立刻抛出这个异常
    • 异常要准确,带有详细信息
    • 抛出异常也比悄悄的执行错误的逻辑强的多

    异常的处理原则

    1. 本方法是否有责任处理这个异常? => 不要处理不归自己管的异常
    2. 本方法是否有能力处理这个异常? => 如果自己无法处理,就抛出
    3. 如非万分必要,不要忽略异常
      try {
          URLDecoder.decode("", "UTF-8");
      } catch (UnsupportedEncodingException ignored) {
          // 忽略异常
      }
      

    JDK 内置异常

    • NullPointerException
    • ClassNotFoundException | NoClassDefFoundError
    • IllegalStateException | IllegalArgumentException | IllegalAccessException
    • ClassCastException

    知识点

    1. IOException 通常代表预期之内的异常

    相关文章

      网友评论

          本文标题:Java 异常体系

          本文链接:https://www.haomeiwen.com/subject/nsytprtx.html