美文网首页
异常处理

异常处理

作者: 予别她 | 来源:发表于2017-05-06 15:38 被阅读0次

    Java异常类型

    所有异常类型都是Throwable的子类,Throwable把异常分成两个不同分支的子类Error和Exception。

    Error类型的异常表示运行应用程序中较严重问题。大多数错误表示代码运行时 JVM(Java 虚拟机)出现的问题。

    Exception类型是程序本身可以处理的异常,它又分为非运行时异常和运行时异常(RuntimeException即运行期问题)。非运行时异常需要手动添加捕获及处理语句,如果不处理,编译则不通过;运行时异常是jvm正常运行期间抛出的错误,这些异常是不检查异常(编译器不会去检查它),一般由程序逻辑错误所引起,是代码本身有问题,这种问题我们不处理。

    如果程序出了问题,并且我们没有做任何处理,最终会被默认处理程序处理,默认处理程序会把异常的信息打印在控制台,同时程序停止运行。

    对于所有的可查异常,java规定:方法必须捕捉,如果不捕捉,则必须声明抛出异常

    java内置异常类

    非检查性异常


    ArithmeticException:算数错误。如,一个整数"除以零"

    ArrayIndexOutOfBoundsException:数组下标出界。

    ArrayStoreException:数组元素赋值类型不兼容

    ClassCastException:非法强制转换类型

    IllegalArgumentException:向方法传递了一个不合法或不正确的参数

    IllegalMonitorStateException:非法监控操作,如等待一个未锁定线程

    IllegalStateException:环境应用状态不正确

    IllegalThreadStateException:请求操作与当前线程状态不兼容

    IndexOutOfBoundsException:某些类型索引超出范围

    NegativeArraySizeException:应用程序试图创建大小为负的数组

    NullPointerException:当应用程序试图在需要对象的地方使用 null 时,抛出该异常

    NumberFormatException:字符串到数字格式的非法转换

    SecurityException:由安全管理器抛出的异常,指示存在安全侵犯

    StringIndexOutOfBoundsException:索引为负,或者超出字符串的大小

    UnsupportedOperationException:遇到不支持请求的操作

    检查行异常


    ClassNotFoundException:找不到相应的类

    CloneNotSupportedException:试图克隆一个无法实现 Cloneable 接口的对象

    IllegalAccessException:对一个类的访问被拒绝

    InstantiationException:试图创建一个抽象接口或抽象类的对象

    InterruptedException:一个线程被另一个线程中断

    NoSuchFieldException:请求的变量不存在

    NoSuchMethodException:请求的方法不存在

    try...catch

    try/catch关键字可以捕获异常

    try{

    可能出现问题的代码

    }catch(异常名 变量){

    针对问题的处理

    }

    一旦异常被引发,程序控制转到catch块,执行了catch语句后,程序控制从整个try/catch机制的下面一行继续。一个catch语句不能捕获另一个try声明所引发的异常(除非是嵌套的try语句情况)。不能单独使用try。构造catch语句的目的是不中断程序的运行。

    try里面定义的属性只能在try块中使用

    class Demo{

    public static void main(String[] args){

    int a,b;

    try{

    a=5;

    b=0;

    System.out.println(a/b);

    }catch(ArithmeticException e){

    System.out.println("Division by zero");

    }

    System.out.println("After catch exception");

    }

    }

    结果为:Division by zero

    After catch exception

    某些情况下单个代码可能引起多个异常,处理这种情况可以定义更多的catch子句,每个子句捕获一种类型的异常。

    当异常被引发,每一个catch子句被依次检查,匹配上异常类型的子句执行,然后代码从try/catch块后面开始继续。

    注意:异常子类必须在它们父类前面(如果不这样,编译器会报错),这是因为运用父类的catch语句将捕获该类型及其所有子类类型的异常。

    class Demo{

    public static void main(String[] args){

    int[] a={1,2};

    try{

    a[34]=5;

    }catch(ArrayIndexOutOfBoundsException e){

         System.out.println("ArrayIndexOutOfBoundsException catch");

    }catch(Exception e){

         System.out.println("Exception catch");

    }

    System.out.println("After catch exception");

    }

    }

    结果为:ArrayIndexOutOfBoundsException catch

    After catch exception

    try语句可以被嵌套,也就是说一个try语句可以在另一个try语句内部。

    建议最好不要嵌套

    public class Demo {

     public static void main(String[] args) {

       try{

         int a=args.length;

         int b=42/a;

         System.out.println("a="+a);

        try{

           if(a==1)

           a=a/(a-a);

           if(a==2){

             int c[]={1};

             c[43]=9;

           }

         }catch(ArrayIndexOutOfBoundsException e){

           System.out.println("ArrayIndexOutOfBounds:"+e);

         }

       }catch(ArithmeticException e){

         System.out.println("Divide by:"+e);

       }

     }

    }

    结果:Divide by:java.lang.ArithmeticException: / by zero

    如果a=1,则结果为:a=1 Divide by:java.lang.ArithmeticException: / by zero 如果a=2,则结果为:a=2 ArrayIndexOutOfBounds:java.lang.ArrayIndexOutOfBoundsException: 43 粗体的try语句嵌套在了外面这个大的try块中,内部的try块不含有处理这个异常的catch语句,它将把异常传给外面的try块,在那里异常被检查是否与之匹配,这个过程将继续直到匹配成功。如果没有catch语句与之匹配,java运行时系统将自动处理这个异常。

    finally

    finally块无论有没有异常抛出都会执行,所以finally一般用来关闭资源。每个try语句至少,需要一个catch或finally字句。finally块可有可无,不作强制要求。

    当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。如果finally语句块中也有return语句,那么直接从finally中返回了,而且finally中的return会使抛出的异常丢失,所以不建议在finally中ruturn.。finally中抛出的异常会覆盖catch中抛出的异常。

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

    1)在finally语句块中发生了异常。

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

    3)程序所在的线程死亡。

    4)关闭CPU。

    public class Demo {

    public static void main(String[] args) {

    int[] a={1,2};

    try{

    a[34]=5;

    }catch(ArrayIndexOutOfBoundsException e){

    System.out.println("Exception catch");

    }finally{

    System.out.println("finally");

    }

    }

    }

    结果为:Exception catch

    finally

    throw

    有时候有些错误在jvm看来不是错误,系统就不会抛出异常(如输入的年龄小于0),这时候我们需要手动引发异常。程序可以用throw语句抛出一个明确的异常。程序在throw语句之后立即停止,后面的任何语句不被执行,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块

    异常是异常类的实例对象,我们可以创建异常类的实例对象通过throw语句抛出

    用法:throw 异常对象;

    有两种获得异常对象的方法:在catch子句中捕获到的异常对象或者用new操作符创建

    public class Demo { static void demo(){ try{
    throw new ArithmeticException("demo");//新实例化的异常对象
    }catch(ArithmeticException e){
    System.out.println("Caught inside demo");
    throw e; //捕获到的异常对象e
    }
    }

    public static void main(String[] args) {
    try{
    demo();
     }catch(ArithmeticException e){
    System.out.println("Caught"+e);
    }
    }
    } 结果为:Caught inside demo Caughtjava.lang.ArithmeticException:demo 注意:throw new ArithmeticException();中new用来构造ArithmeticException实例。所有java内置的运行异常有两个构造方法:一个没有参数,一个带有一个字符串参数。当用第二种形式时,参数描述指定异常的字符串(抛出异常的原因),如果对象用作print()或println()输出时,该字符串被显示(打印异常原因)。

    throw是语句抛出异常。它不可以单独使用,要么与try…catch配套使用,要么与throws配套使用。

    throws

    throws 是方法抛出异常,在一个方法中可能出现了某些异常,我们没法去处理它,然后就将这个异常向上抛出。如果一个方法中没有捕获某个检查性异常的语句,则该方法必须使用 throws 关键字来声明,异常的处理则交由它的调用者。throws 关键字放在方法声明的尾部。例如汽车出现了故障时,汽车不会自己去处理这个异常,而是交给开车的人来处理。

    如果一个方法声明了throws,然后方法里面有try...catch块,直接catch异常的引用不再throws(即上层调用者不会去处理这个异常)。

    Throws抛出异常的规则:

    1) 如果是不可查异常(unchecked exception),即Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。

    2)必须声明方法可抛出的任何可查异常(checked exception)。即如果一个方法可能出现可查异常,要么用try-catch语句捕获,要么用throws子句声明将它抛出,否则会导致编译错误

    3)当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出。

    4)调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。

    一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。

    public class Demo {

    public static void test() throws ArithmeticException {

       throw new ArithmeticException();

    }

    public static void main(String[] args) {

    try{

    test();

    }catch(ArithmeticException e){

    System.out.println("Caught:"+e);

    }

    }

    }

    结果为:Caught:java.lang.ArithmeticException: / by zero

    在test()后面声明throws来引发ArithmeticException异常,在main方法中必须定义一个try/catch语句来捕获该异常

    通过throw抛出异常后,如果想在上一级代码中捕获并处理异常,需要在抛出异常方法中使用throws关键字在方法声明中指明要跑出的异常。如果要捕获throw抛出的异常,必须使用try/catch语句

    自定义异常

    系统中有些错误是符合Java语法的,但不符合逻辑,此时就可以自定义异常。如果异常中没有我们想要的异常,也剋有自定义一个异常。比如人的性别是中性时需要抛出异常,但是一直异常中没有这个异常,这时候我们可以自定义一个异常抛出。

    在 Java 中可以自定义异常。所有异常都必须是 Throwable 的子类。如果希望写一个检查性异常类,则需要继承 Exception 类。如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。

    一般情况下我们都会直接继承Exception类

    Exception类没有定义任何方法,它继承了Throwable提供的一些方法。

    Throwable 类的主要方法:


    String getMessage():返回关于发生的异常的详细信息

    Throwable getCause():返回一个Throwable 对象代表异常原因

    String toString():使用getMessage()的结果返回类的串级名字

    void printStackTrace():打印toString()结果和栈层次到System.err,即错误输出流。

    StackTraceElement [] getStackTrace():返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。

    Throwable fillInStackTrace():用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。

    Java自定义异常的使用要经历如下四个步骤:

    1、定义一个类继承Throwable或其子类。

    2、添加构造方法(当然也可以不用添加,使用默认构造方法)。

    3、在某个方法类抛出该异常。

    4、捕捉该异常。

    public class MyException extends Exception { //自定义的MyException异常

    }

    public class Demo {

    static void compute(int a) throws MyException{

    System.out.println("Called compute("+a+")");

    if(a>10)

    throw new MyException();

    System.out.println("Normal exit");

    }

    public static void main(String[] args) {

    try{

    compute(1);

    compute(20);

    }catch(MyException e){

    System.out.println("Caught:"+e);

    }

    }

    }

    结果为:Called compute(1)

    Normal exit

    Called compute(20)

    Caught:com.DE.MyException

    相关文章

      网友评论

          本文标题:异常处理

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