java之异常处理

时间:2022-10-05 00:42:47

1.异常简介

 java的异常处理可以让程序具有更好的容错性,提高程序健壮性

2.异常继承体系

首先看下结构图:

java之异常处理

①Throwable:是所有异常的根,java.lang.Throwable
②Error:表示错误 一般指JVM相关的不可修复的错误,如,系统崩溃,内存溢出,JVM错误等,由JVM抛出,我们不需要处理
③Exception:表示异常,指程序中出现不正常的情况,该问题可以修复(处理异常).

  异常Exception分为两大类型:检查异常(编译异常)与运行时异常(Runtime异常)。

  检查异常:checked异常.在编译时期,就会检查,如果没有处理异常,则编译失败.

  运行时异常:在运行时期检查是否有异常;在编译时期,可处理,可不处理(包括错误的编译).

 

3.try...catch...finally 语句

  •  try   -- 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
  • catch   -- 用于捕获异常。catch用来捕获try语句块中发生的异常。
  •  finally  -- finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
try{
   业务实现代码
   ...        
}catch(ArithmeticException e){
   异常捕获
  ...
}catch(Exception e){
   异常捕获
  ...
}finally{
  资源回收
  ...
}

如果执行try块的业务代码时出现异常,系统自动生成一个异常对象,该异常对象被提交给java运行时环境,这个过程被称为抛出异常。

当java运行时环境收到异常对象时,会寻找能处理该异常对象的catch块,如果找到合适的catch块并把该异常对象交给该catch块处理,这个过程被称为捕获异常,

如果没有找到异常的catch块,则运行时环境终止,java程序也将退出。

 

捕获异常注意事项:

  • try后可接零个或多个catch块,(多个catch块遵循先捕获小的异常,再捕获大的异常)如果没有catch块,则必须跟一个finally块。
  • 代码在一瞬间只能出现一种类型的异常,只需要一个catch捕获,不可能同时出现多个异常.

  • 当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。

    在以下4种特殊情况下,finally块不会被执行:

    ①:在finally语句块中发生了异常。

    ②:在前面的代码中用了System.exit()退出程序。

    ③:程序所在的线程死亡。

    ④:关闭CPU。

  • finally块中有return语句,永远返回finally中的结果
  • 可嵌套 try-catch-finally 结构。

  • 在 try-catch-finally 结构中,可重新抛出异常。

4.throw 与 throws

  •  throw   -- 用在方法内部,给调用者返回一个异常对象,和return一样会结束当前方法.
  •  throws -- 用在方法签名中,用于声明该方法可能抛出的异常。

throw语句:

       throw  new  ExceptionInstance 要注意的是,throw 抛出的只能够是可抛出类Throwable 或者其子类的实例对象.

  throw 每次只能抛出一个异常实例

  程序会在throw语句后立即终止,它后面的语句执行不到,

 注意:

  • 如果throw语句抛出的异常是Checked异常,必须  
    • 该throw语句要么处于try块里,显示捕获该异常
    • 放在一个带throws声明抛出的方法中,即把该异常交给该方法调用者处理    
  • throw语句 抛出Runtime异常
    • 无须放在try块里 也无须放在throws声明抛出的方法中
    • 也可以捕获该异常或者不处理交给该方法调用者

throws语句:

  throws ExceptionA,ExceptionB... 声明抛出多个异常类 

  如果每一个方法都放弃处理异常都直接通过throws声明抛出,最后异常会抛到main方法,如果此时main方法不处理,继续抛出给JVM,底层的处理机制就是打印异常的跟踪栈信息.

  runtime异常,默认就是这种处理方式.

  子类方法声明抛出的异常类型是父类方法抛出的异常类型的子类或相同

  子类方法中不允许比父类方法声明抛出更多异常

 

5.自定义异常

一种自定义异常都应该继承Exception基类,二种继承RuntimeException基类。

  

class CheckedAgeExceprion extends Exception{
    private int value;
    public CheckedAgeExceprion (){
        super();
    }
    public CheckedAgeExceprion(String msg,int value){
        super(msg);
        this.value = value;
    }
    public int getValue(){
        return value;
    }

}
public class Test02 {
    public static void main(String[] args) {
        try{
            int age = -20;
            if(age <0){
                throw new CheckedAgeExceprion("年龄不能是负数",age);
            }else {
                System.out.println("age = "+ age);
            }
            System.out.println("此处代码会执行吗");
        }catch (CheckedAgeExceprion e){
            e.printStackTrace();
            System.out.println("我的值是:"+e.getValue());
        }
        System.out.println("异常捕获成功后,try块和catch块之外的代码将会执行");
    }
}

运行结果:

java之异常处理

6.Throwable类常用方法

  • getMessage():获取异常的描述信息,原因(提示给用户的时候,就提示错误原因).
  • printStackTrace():打印异常的跟踪栈信息并输出到控制台.  包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace. 记住:现在在catch语句块中,必须写:e.printStackTrace();目的:查看异常的具体信息,方便调试和修改.
  • printStackTrace(PrintStream s):异常的跟踪栈信息输出到指定输出流。

 

 

7.try-catch-finally-return的执行顺序

案例一:try块中没有抛出异常try和finally块中都有return语句

public static int NoException(){  
 int i=10;  
 try{  
  System.out.println("i in try block is"+i);  
  return --i;  
 }catch(Exception e){  
  --i;  
  System.out.println("i in catch - form try block is"+i);  
  return --i;  
 }finally{   
  System.out.println("i in finally - from try or catch block is"+i);  
  return --i;  
 }  
}  

执行结果:

i in try block is10
i in finally - from try or catch block is9
the method value is8

执行顺序执行try块,执行到return语句时,先执行return的语句,--i,

但是不返回到main 方法,执行finally块,遇到finally块中的return语句,

执行--i,并将值返回到main方法,这里就不会再回去返回try块中计算得到的值

 

 案例二:try块中没有抛出异常,仅try中有return语句

public static int NoException(){  
    int i=10;  
    try{  
        System.out.println("i in try block is--"+i);  
        return --i;  
    }catch(Exception e){  
        --i;  
        System.out.println("i in catch - form try block is--"+i);  
        return --i;  
    }finally{  
          
        System.out.println("i in finally - from try or catch block is--"+i);  
        --i;  
        System.out.println("i in finally block is--"+i);  
        //return --i;  
    }  
}  

执行结果:

i in try block is--10
i in finally - from try or catch block is--9
i in finally block is--8
the method value is--9

执行顺序:try中执行完return的语句后,不返回,执行finally块,finally块执行结束后,返回到try块中,返回i在try块中最后的值

 案例三:try块中抛出异常try,catch,finally中都有return语句

public static int WithException(){  
    int i=10;  
    try{  
        System.out.println("i in try block is--"+i);  
        i = i/0;  
        return --i;  
    }catch(Exception e){  
        System.out.println("i in catch - form try block is--"+i);  
        --i;  
        System.out.println("i in catch block is--"+i);  
        return --i;  
    }finally{  
          
        System.out.println("i in finally - from try or catch block is--"+i);  
        --i;  
        System.out.println("i in finally block is--"+i);  
        return --i;  
    }  
}  

执行结果:

i in try block is--10
i in catch - form try block is--10
i in catch block is--9
i in finally - from try or catch block is--8
i in finally block is--7
the method value is--6

 执行顺序:顺序,抛出异常后,执行catch块,在catch块的return的--i执行完后,并不直接返回而是执行finally,因finally中有return语句,所以,执行,返回结果6

 案例四:catch中有return,finally中没有,同上,执行完finally语句后,依旧返回catch中的执行return语句后的值,而不是finally中修改的值

 

 案例五:try和catch中都有异常,finally中无return语句

public static int CatchException(){  
    int i=10;  
    try{  
        System.out.println("i in try block is--"+i);  
        i=i/0;  
        return --i;  
    }catch(Exception e){  
        System.out.println("i in catch - form try block is--"+i);  
        int j = i/0;  
        return --i;  
    }finally{  
          
        System.out.println("i in finally - from try or catch block is--"+i);  
        --i;  
        System.out.println("i in finally block is--"+i);  
        //return --i;  
    }  
}  

结果:

i in try block is--10
i in catch - form try block is--10
i in finally - from try or catch block is--10
i in finally block is--9
Exception in thread "main" Java.lang.ArithmeticException: / by zero
 at exception.ExceptionTest0123.CatchException(ExceptionTest0123.java:29)
 at exception.ExceptionTest0123.main(ExceptionTest0123.java:17)

执行顺序:在try块中出现异常,到catch中,执行到异常,到finally中执行,finally执行结束后判断发现异常,抛出

 

案例六:try,catch中都出现异常,在finally中有返回

 

public static int CatchException(){  
    int i=10;  
    try{  
        System.out.println("i in try block is--"+i);  
        i=i/0;  
        return --i;  
    }catch(Exception e){  
        System.out.println("i in catch - form try block is--"+i);  
        int j = i/0;  
        return --i;  
    }finally{  
          
        System.out.println("i in finally - from try or catch block is--"+i);  
        --i;  
        System.out.println("i in finally block is--"+i);  
        return --i;  
    }  
}  

运行结果:

i in try block is--10
i in catch - form try block is--10
i in finally - from try or catch block is--10
i in finally block is--9
the method value is--8

执行顺序:try块中出现异常到catch,catch中出现异常到finally,finally中执行到return语句返回,不检查异常

8.java 常见异常

在Java中提供了一些异常用来描述经常发生的错误,对于这些异常,有的需要程序员进行捕获处理或声明抛出,有的是由Java虚拟机自动进行捕获处理。Java中常见的异常类:

  • runtimeException子类:

    • ArrayIndexOutOfBoundsException   数组索引越界异常
    • ArithmeticException  算数条件异常
    • NullPointException 空指针异常
    • ClassNotFoundException 找不到类异常
    • NegativeSizeException 数组长度为负异常
    • ArrayStoreException 数组中包含不兼容的值抛出的异常
    • SecurityException 安全性异常
    • IllegalArgumentException 非法参数异常
  • IOException(操作输入流和输出流时可能出现的异常)

    • EOFException   文件已结束异常
    • FileNotFoundException   文件未找到异常
  • 其他
    • ClassCastException    类型转换异常类
    • ArrayStoreException  数组中包含不兼容的值抛出的异常
    • SQLException   操作数据库异常类
    • NoSuchFieldException   字段未找到异常
    • NoSuchMethodException   方法未找到抛出的异常
    • NumberFormatException    字符串转换为数字抛出的异常
    • StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
    • IllegalAccessException  不允许访问某类异常
    • InstantiationException  当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常 

9小结

1.异常体系 :

  Throwable类有两个子类(Error和Exception)

  Exception 有一个子类RuntimeException,该类及其该类的子类称为runtime异常

  在Exceprion类和子类除了(runtime体系):Checked异常也就是编译时异常

2.try、cathc、finllay、throw、throws 关键字使用

3.定义异常类