您的位置:首页 > 编程语言 > Java开发

java异常

2015-09-20 20:21 555 查看
     

异常是程序运行过程中出现的错误。

    Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。Java异常体系结构呈树状,其层次结构图如图 1所示:

      Java异常类层次结构图:

        


      在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性。
Throwable: 有两个重要的子类:Exception(异常)和
Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。

       Error(错误)  Error是程序无法处理的错误。

     比如OutOfMemoryError、ThreadDeath等。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。 例如,Java虚拟机运行错误(Virtual
MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。

      Exception(异常):是程序本身可以处理的异常。
      Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。

例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和
ArrayIndexOutOfBoundException。

运行时异常和非运行时异常

    运行时异常都是RuntimeException类及其子类异常,如NullPointerException、 IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

    非运行时异常(编译时异常)是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不 处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。


捕获异常:try、catch 和 finally

Java异常处理涉及到五个关键字,分别是:try、catch、finally、throw、throws。下面将骤一介绍,通过认识这五个关键字,掌握基本异常处理知识。

    1、 异常处理的基本语法    

    在java中,异常处理的完整语法是:     

    try{       

         //(尝试运行的)程序代码     

        }catch(异常类型 异常的变量名){ 

          //异常处理代码     

        }finally{     

         //异常发生,方法返回之前,总是要执行的代码 

    }
    catch语句块会捕获try代码块中发生的异常并在其代码块中做异常处理,catch语句带一个Throwable类型的参数,表示可捕获异常类型。当 try中出现异常时,catch会捕获到发生的异常,并和自己的异常类型匹配,若匹配,则执行catch块中代码,并将catch块参数指向所抛的异常对 象。catch语句可以有多个,用来匹配多个中的一个异常,一旦匹配上后,就不再尝试匹配别的catch块了。通过异常对象可以获取异常发生时完整的
JVM堆栈信息,以及异常信息和异常发生的原因等。

   1、 finally语句块是紧跟catch语句后的语句块,这个语句块总是会在方法返回前执行,而不管是否try语句块是否发生异常。并且这个语句块总是在方
法返回前执行。目的是给程序一个补救的机会。这样做也体现了Java语言的健壮性。     

   2、 try、catch、finally三个语句块应注意的问题
   

        第一、try、catch、finally三个语句块均不能单独使用,三者可以组成
try...catch...finally、try...catch、try...finally三种结构,catch语句可以有一个或多个,finally语句最多一个。   

        第二、try、catch、finally三个代码块中变量的作用域为代码块内部,分别独立而不能相互访问。如果要在三个块中都可以访问,则需要将变量定义到这些块的外面。
 

       第三、多个catch块时候,只会匹配其中一个异常类并执行catch块代码,而不会再执行别的catch块,并且匹配catch语句的顺序是由上到下。

 捕捉throw语句抛出的“除数为0”异常。

public class TestException {  

    public static void main(String[] args) {  

        int a = 6;  

        int b = 0;  

        try { // try监控区域  

              

            if (b == 0) throw new ArithmeticException(); // 通过throw语句抛出异常  

            System.out.println("a/b的值是:" + a / b);  

        }  

        catch (ArithmeticException e) { // catch捕捉异常  

            System.out.println("程序出现异常,变量b不能为0。");  

        }  

        System.out.println("程序正常结束。");  

    }  

}  

运行结果:程序出现异常,变量b不能为0。

带finally子句的异常处理程序。

public class TestException {  

    public static void main(String args[]) {  

        int i = 0;  

        String greetings[] = { " Hello world !", " Hello World !! ",  

                " HELLO WORLD !!!" };  

        while (i < 4) {  

            try {  

                // 特别注意循环控制变量i的设计,避免造成无限循环  

                System.out.println(greetings[i++]);  

            } catch (ArrayIndexOutOfBoundsException e) {  

                System.out.println("数组下标越界异常");  

            } finally {  

                System.out.println("--------------------------");  

            }  

        }  

    }  

}  

运行结果:

Hello world !

--------------------------

Hello World !!

--------------------------

HELLO WORLD !!!

--------------------------

数组下标越界异常

--------------------------

 捕捉throw语句抛出的“除数为0”异常。

public class TestException {  

    public static void main(String[] args) {  

        int a = 6;  

        int b = 0;  

        try { // try监控区域  

              

            if (b == 0) throw new ArithmeticException(); // 通过throw语句抛出异常  

            System.out.println("a/b的值是:" + a / b);  

        }  

        catch (ArithmeticException e) { // catch捕捉异常  

            System.out.println("程序出现异常,变量b不能为0。");  

        }  

        System.out.println("程序正常结束。");  

    }  

}  

运行结果:程序出现异常,变量b不能为0。

 捕捉throw语句抛出的“除数为0”异常。

public class TestException {  

    public static void main(String[] args) {  

        int a = 6;  

        int b = 0;  

        try { // try监控区域  

              

            if (b == 0) throw new ArithmeticException(); // 通过throw语句抛出异常  

            System.out.println("a/b的值是:" + a / b);  

        }  

        catch (ArithmeticException e) { // catch捕捉异常  

            System.out.println("程序出现异常,变量b不能为0。");  

        }  

        System.out.println("程序正常结束。");  

    }  

}  

运行结果:程序出现异常,变量b不能为0。


抛出异常

throw总是出现在函数体中,用来抛出一个Throwable类型的异常。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块。
  我们知道,异常是异常类的实例对象,我们可以创建异常类的实例对象通过throw语句抛出。该语句的语法格式为:
    throw new exceptionname;
    例如抛出一个IOException类的异常对象:
    throw new IOException;
    要注意的是,throw 抛出的只能够是可抛出类Throwable 或者其子类的实例对象。下面的操作是错误的:
    throw new String("exception");

    这是因为String 不是Throwable 类的子类。

     如果抛出了检查异常,则还应该在方法头部声明方法可能抛出的异常类型。该方法的调用者也必须检查处理抛出的异常。

       如果所有方法都层层上抛获取的异常,最终JVM会进行处理,处理也很简单,就是打印异常消息和堆栈信息。如果抛出的是Error或RuntimeException,则该方法的调用者可选择处理该异常。

package Test;  

import java.lang.Exception;  

public class TestException {  

    static int quotient(int x, int y) throws MyException { // 定义方法抛出异常  

        if (y < 0) { // 判断参数是否小于0  

            throw new MyException("除数不能是负数"); // 异常信息  

        }  

        return x/y; // 返回值  

    }  

    public static void main(String args[]) { // 主方法  

        int  a =3;  

        int  b =0;   

        try { // try语句包含可能发生异常的语句  

            int result = quotient(a, b); // 调用方法quotient()  

        } catch (MyException e) { // 处理自定义异常  

            System.out.println(e.getMessage()); // 输出异常信息  

        } catch (ArithmeticException e) { // 处理ArithmeticException异常  

            System.out.println("除数不能为0"); // 输出提示信息  

        } catch (Exception e) { // 处理其他异常  

            System.out.println("程序发生了其他的异常"); // 输出提示信息  

        }  

    }  

  

}  

class MyException extends Exception { // 创建自定义异常类  

    String message; // 定义String类型变量  

    public MyException(String ErrorMessagr) { // 父类方法  

        message = ErrorMessagr;  

    }  

  

    public String getMessage() { // 覆盖getMessage()方法  

        return message;  

    }  

}  


Throwable类中的常用方法

注意:catch关键字后面括号中的Exception类型的参数e。Exception就是try代码块传递给catch代码块的变量类型,e就是变量名。catch代码块中语句"e.getMessage();"用于输出错误性质。通常异常处理常用3个函数来获取异常的有关信息:

     getCause():返回抛出异常的原因。如果 cause 不存在或未知,则返回 null。
  getMeage():返回异常的消息信息。

  printStackTrace():对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。

     有时为了简单会忽略掉catch语句后的代码,这样try-catch语句就成了一种摆设,一旦程序在运行过程中出现了异常,就会忽略处理异常,而错误发生的原因很难查找。


Java常见异常

  

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


1. runtimeException子类:

    1、 java.lang.ArrayIndexOutOfBoundsException
    数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
    2、java.lang.ArithmeticException
    算术条件异常。譬如:整数除零等。
    3、java.lang.NullPointerException
    空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
    4、java.lang.ClassNotFoundException
    找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。

   5、java.lang.NegativeArraySizeException  数组长度为负异常

   6、java.lang.ArrayStoreException 数组中包含不兼容的值抛出的异常

   7、java.lang.SecurityException 安全性异常

   8、java.lang.IllegalArgumentException 非法参数异常


2.IOException

IOException:操作输入流和输出流时可能出现的异常。

EOFException   文件已结束异常

FileNotFoundException   文件未找到异常


3. 其他

ClassCastException    类型转换异常类

ArrayStoreException  数组中包含不兼容的值抛出的异常

SQLException   操作数据库异常类

NoSuchFieldException   字段未找到异常

NoSuchMethodException   方法未找到抛出的异常

NumberFormatException    字符串转换为数字抛出的异常

StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常

IllegalAccessException  不允许访问某类异常

InstantiationException  当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常

    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: