Java 语言-7 Java 基础语法 3.0

7.1 异常机制

7.1.1 认识异常

  • 异常(exception)又称例外、差错、违例

    • 对应 Java 运行错误处理机制
  • 简单分类

    • 检查性异常:这是程序员不可预知的异常,最具代表性的检查性错误是用户错误或问题引起的异常,这些异常在编译时不能被简单的忽略
    • 运行时异常:这是程序员可以避免的异常
    • 错误(Error):错误并不是异常,而脱离程序员控制的问题。在代码中通常被忽略
  • 传统语言(例如:C 语言)处理异常

    • 方式:
      • if 语句判断是否出现异常
      • 全程使用变量 ErroNo 记录异常
    • 缺点:
      1. 可读性差。正常处理与异常处理的代码进行同样的处理
      2. 可维护性差。每次调用一个方法时都进行错误检查
      3. 职责不清。错误由谁处理分辨不清
  • Java 的异常处理

    • 抛出(throw)异常
    • 运行时系统在调用栈中查找
      • 从生成异常的方法开始回溯直到找到
    • 捕获(catch)异常代码
  • Java 异常体系结构

    • Java 将异常当作对象处理,定义了一个基类 java.lang.Throwable 作为所有异常的超类
    • 在 Java API 中将定义的许多异常类通常分为两大类,错误(Error)和异常(Exception),一般说的异常是指 Exception 及其子类
      image-20220215134947288
  • Error & Exception

    • Error 类对象由 Java 虚拟机(JVM)生成并抛出,大多数错误与代码编写者所执行的操作无关
      • 大多数时 Java 虚拟机运行错误(Virtual MachineError),还有虚拟机企图执行应用时
      • 这些错误是不可查的,因为这些错误是在应用程序的控制和处理之外,而且绝大数是程序运行时不允许出现的状况
    • Exception
      • 在 Exception 中有一个重要的子类 RuntimeException(运行时异常),这些异常一般是由程序逻辑错误引起。程序应该从逻辑角度尽可能避免这类异常的发生
    • 二者区别:
      • Error 通常是灾难级的致命错误,是程序无法控制和处理的当出现这些异常,Java 虚拟机一般会选择终止线程
      • Exception 通常情况下可以被程序处理,并且在程序中应该尽可能的去处理这些异常
  • Exception 类

    • 构造方法的三种形式:

      public Exception();
      public Exception(String message);
      public Exception(String message,Throwable cause);
      
    • 常见读取方式:

      • getMessage():获取异常信息
      • getCause():获取内部原因
      • printStackTrace():输出调用栈的跟踪信息,即 IDEA 输出的异常信息

7.1.2 处理异常

  • 处理异常的五个关键字

    • try、catch、finally、throw、throws

      try-catch:捕获异常。try:监控区域;catch:捕获异常。

      finally:处理善后工作。无论是否经过 try-catch 都会执行 finally 语句。多用于 IO 的资源关闭

      throw 和 throws:抛出异常对象。throw 在方法中使用;throws 在声明方法时使用

  • 基本写法:try-catch

    try{
        ……
    }catch(Exception e){
        ……
    }finally{
        ……
    }
    

    catch 语句可以有 0 到多个

    finally 语句可以有 0 到 1 个

    • 多异常的处理:子类异常要排在父类异常前
  • 快捷键(IDEA):Crtl+Alt+T

  • 主动抛出异常:当已知代码有问题,用 throw 主动抛出异常,主动结束代码

    • 一般在方法中使用

    • 例如:

      public void test(int a;int b){
          if (b==0){
              throw new ArithmeticException();
          }
      }
      
  • 在方法上抛出异常使用 throws

    • 例如:

      public void test(int a;int b) throws ArithmeticException{
          if (b==0){
              throw new ArithmeticException();
          }
      }
      
  • 重抛异常:其中对于异常,不仅需要进行捕获处理,有时候还需要将异常进一步传递给调用者

  • 方法:

    1. 将当前捕获的异常再次抛出,如:throw e;
    2. 重新生成异常并抛出,如:throw new Exception("some message");
    3. 重新生成并抛出一个新异常,该异常包含了当前异常的信息,如:throw new Exxception("some message",e);
      • 这种方式可用 e.getCause() 来得到内部异常

7.1.3 自定义异常

  • 用的不多,Java 自带的异常就非常多了,而且还有很多开源的异常在网上,所有一般都不需要自定义异常

  • 大体方法:自定义异常类只需要继承 Exception 类即可

  • 大体步骤:

    1. 创建自定义异常类
    2. 在方法体中通过 throw 关键字抛出异常对象
      • 如果在当前抛出异常的方法中处理异常,可以使用 try-catch 捕获异常并处理
      • 如果不在当前方法中处理,则需要在方法的声明处使用 throws 关键字指明需要抛出给方法调用者的异常
    3. 在出现异常方法的调用者中捕获处理异常
  • 如果仍然不知道怎样写,可以查看 Java 自带的异常方法,作为案例

  • 示例:定义一个输入大于10的数就抛出异常的自定义异常类

    定义自定义异常类 MyException

    package exercise.DivMyException;
    
    public class MyException extends Exception{
        //传递数字>10
        private int detail;
    
        public MyException(int a) {
            this.detail =a;
        }
    
        //toString:异常的打印信息
        @Override
        public String toString() {
            return "MyException{" +
                    "detail=" + detail +
                    '}';
        }
    }
    

    定义测试自定义异常类 Test

    package exercise.DivMyException;
    
    import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
    
    public class Test {
        //可能存在异常的方法
        static void test(int a) {
    
            System.out.println("传递参数为:"+a);
    
            if(a>10){
                try {
                    throw new MyException(a);
                } catch (MyException e) {
                    System.out.println("MyException:"+e);
                }
    
            }else {
                System.out.println("OK");
            }
    
        }
        public static void main(String[] args) {
            test(1);
        }
    }
    

    测试结果:

    传递参数为:1
    OK
    
    传递参数为:10
    OK
    
    传递参数为:11
    MyException:MyException{detail=11}
    
  • 实际经验总结

    • 处理运行时异常时,采用逻辑去合理规避同时采用 try-catch 辅助处理
    • 在多重 catch 块后面,可以加入 catch(Exception) 来处理可能会被遗漏的的异常
    • 对于不确定的代码,也可以使用 try-catch 处理潜在的异常
      • 在 IDEA 中潜藏的异常会以波浪线标红,可以使用alt+Enter查看提示信息
    • 处理异常时,尽量细致的去处理异常,切忌只是简单调用 printStackTrace() 去打印输出
    • 具体如何处理异常,需要根据不同的业务需求和异常类型去决定
    • 处理过程中,尽量添加 finally 语句去释放占用的资源
      • 特别是 IO、Scanner

7.2 类、接口等完整定义

  • 如果看不懂个别意思,可能是因为没学习到;如果基本都没看懂,就是前面没有学习扎实

  • 完整类定义

    //类声明
    [public][abstract | final] class className [extends superclassName][implements InterfaceName]{
        //成员变量声明,可为多个
        [public | protected | private][static][final][transient][volatile] type variableName;
        //方法定义,可为多个
        [public | protected | private][static][final | abstract][native][synchronized] returnType methodName ([paramList])
            //方法实现,可为多个
            [throws exceptionList]{
            statements
        } 
    }
    
  • 完整接口定义

    //接口声明
    [public] interface InterfaceName [extends superInterfaceList]{
        //常量声明,可为多个
        type constantName = Value;
        //方法声明,可为多个
        returnType methodName([paramList]);
    }
    

    未加入 jdk 8 以后新加的定义方法

  • 三种方法固定的声明方式

    1. 构造方法:

      calssName([paramList]){
          ……
      }
      
    2. main() 方法:

      public static void main(String[] args){
          ……
      }
      
    3. finalize() 方法:

      protected void finalize() throws throwable{
          ……
      }
      

      几乎不用的

  • 完整 Java 源文件

    //指定文件中类所在包
    package packageName;
    //指定引入的类
    import packageName.[className | *];
    //属性为 public 的类定义
    public classDefinition
    //接口或者类的定义
    interfaceDefinition and classDefinition
    

    源文件名字必须与属性为 public 的类的类名一致

posted @ 2022-02-17 19:59  你是我的生命之源  阅读(56)  评论(0)    收藏  举报
页脚