• Java 基础-异常处理


    在 Java 中声明了很多异常类,每个异常类都表示一种运行错误。程序运行过程中发生一个可识别的运行错误时(可以找到与错误匹配的异常类,例如被除数为 0 时会触发 java.lang.ArithmeticException),系统会抛出对应异常类的对象。

    参考:Java 异常处理

    Java 异常处理机制的优点

    • 分离错误处理代码,使业务代码更专注
    • 按照类型对错误分组
    • 可以捕获处理无法预测的错误
    • 异常类的对象包含了异常的充分信息
    • 可以按照调用栈传播错误,直到有处理错误的代码

    错误分类

    根据错误的严重程度不同,可以分为两类:

    • 错误:致命的,无法处理的。最上层父类是 Error 类
    • 异常:非致命,可以捕获并处理。最上层父类是 Exception 类

    Throwable 是 Error 和 Exception 的父类。

    Java 中有3种方式生成异常对象:

    • 由 Java 虚拟机生成
    • 由 Java 类库中的某些类生成
    • 在自己写的程序中生成和抛出异常对象

    必须通过 throw 语句抛异常对象,异常对象必须是 Throwable 或其子类的实例。

    throw new XXException();
    
    XXException e = new XXException();
    throw e;
    

    Throwable 类的主要方法

    方法 描述
    public String getMessage() 获取异常的详细信息
    public Throwable getCause() 返回 Throwable 对象,代表异常的原因
    public void printStackTrace() 打印toString()结果和栈层次到 System.err 错误输出流。
    public StackTraceElement [] getStackTrace() 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。

    异常的分类

    根据是否必须捕获异常,可以将异常分为两类:

    非检查型异常(也叫运行时异常)

    非检查型异常继承自 RuntimeException,不需要在程序中进行捕获,编译器也不会检查。之所以可以不捕获,有两个原因:

    • 引发这类异常的操作经常出现(例如使用对象时如果对象为 null 则抛异常)
    • 要抛的异常可以用其他方式解决(例如被除数为0会抛出异常,但可以提前判断被除数来防止这种异常)
    public class Excep {
        public static void main(String[] args) {
            String[] arr = {"hello", "world"};
            int i = 0;
            while(i < 10) {
                System.out.println(arr[i++]);
            }
        }
    }
    

    上面这段代码并没有捕获异常,编译通过,执行时会因为数组下标越界而报错:

    [root@VM_139_38_centos java]# java Excep
    hello
    world
    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
    	at Excep.main(Excep.java:6)
    

    检查型异常

    对于检查型异常,调用者必须捕获并处理(try{...}catch(...){...})或也声明抛出(`throws XXException``)。如果所有方法都没有处理这种异常,最终异常会交给 Java 虚拟机来处理。编译器会检查这种异常。

    public class T {
        public static void main(String[] args) {
            He h = new He();
            h.fun();
        }
    }
    class He {
        public void fun() throws Exception {
            throw new RuntimeException();
        }
    }
    

    上面这段代码中,类 He 中的 fun 方法会抛出异常,当时调用者并没有捕获也没有继续抛出,所以执行时会报错:

    T.java:4: unreported exception java.lang.Exception; must be caught or declared to be thrown
            h.fun();
                 ^
    1 error
    

    如果异常一路都在抛,没有方法处理,最后到了 main 方法还在抛异常public static void main(String[] args) throws Exception{...},那最后 Java 虚拟机会接收到这个异常,程序会停止执行并报错,例如:

    public class T {
        public static void main(String[] args) throws Exception{
            He h = new He();
            h.fun();
            System.out.println("end of program");
        }
    }
    class He {
        public void fun() throws Exception {
            throw new RuntimeException();
        }
    }
    
    [root@VM_139_38_centos java]# java T
    Exception in thread "main" java.lang.RuntimeException
    	at He.fun(T.java:10)
    	at T.main(T.java:4)
    

    捕获并处理异常

    Java 中用 try{...}catch(...){...}finally{...} 语句捕获异常。其中,try 代码段中是可能抛出异常的代码,catch 代码段在匹配异常时执行,finally 代码段则是无论是否发生异常都会执行的代码段。语法为:

    try {
       // 程序代码
    } catch(ExceptionName1 e1) {
       //Catch 块
    } catch(ExceptionName2 e2) {
       //可以有多个 Catch 块
    } finally {
    	//finally 块
    }
    

    例如,对于数组越界异常的捕获处理:

    public class ExcepTest{
       public static void main(String args[]){
          try{
             int a[] = new int[2];
             System.out.println("Access element three :" + a[3]);
          }catch(ArrayIndexOutOfBoundsException e){
             System.out.println("Exception thrown  :" + e);
          }finally{
              System.out.println("finally run");
          }
          System.out.println("Out of the block");
       }
    }
    

    结果为:

    Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
    finally run
    Out of the block
    

    throws/throw 关键字

    对于检查性异常,如果方法不想捕获,那么该方法必须使用 throws 关键字来抛出这个异常(如果有多个可能的异常,需要用逗号分隔),交给调用者来处理。throws 关键字放在方法签名的尾部。

    public void fun() throws RemoteException, InsufficientFundsException
    {
        // Method implementation
    }
    

    throw 关键字用于抛出异常给方法的调用者,注意需要在方法签名尾部用 throws 抛出这个异常。

    public void fun() throws RemoteException
    {
    	throw new RemoteException();
    }
    

    自定义异常

    Java 中的异常类跟普通的类一样,有属性和方法。根据自定义的异常是否需要检查,可以分为两类:

    • 检查型异常类,需要继承 Exception 类。
    • 运行时异常类,需要继承 RuntimeException 类。

    语法示例:

    class MyException extends Exception{
    }
    

    代码示例:

    public class T {
        public static void main(String[] args) {
            try {
                throw new MyException(666);
            } catch (MyException e) {
                System.out.println(e);
            }
        }
    }
    class MyException extends Exception {
        private int amount;
        public MyException(int amount) {
            this.amount = amount;
        }
        public String getMessage() {
            return "amount not enough" + this.amount;
        }
    }
    

    运行结果:

    MyException: amount not enough666
    
  • 相关阅读:
    动态投影
    我的比较差的初级的研究成果
    我最近的研究成果(IGeometry.Project and IGeometry.SpatialReference)
    mysql中的数据类型以及常见约束
    面向对象——多态
    java基础
    java中的异常(3)
    mysql中的数据类型
    面向对象——继承
    java中的异常(2)
  • 原文地址:https://www.cnblogs.com/kika/p/10851525.html
Copyright © 2020-2023  润新知