Java把异常当作对象来处理,并定义一个基类 java.lang.Throwable 作为所有异常的超类。 在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。 Java异常层次结构图: 从图中可以看出所有异常类型都是内置类 Throwable 的子类,因而 Throwable 在异常类的层次结 构的顶层。 接下来Throwable 分成了两个不同的分支,一个分支是Error,它表示不希望被程序捕获或者是程序 无法处理的错误。另一个分支是Exception,它表示用户程序可能捕捉的异常情况或者说是程序可以处理的异常。 其中异常类 Exception 又分为运行时异常( RuntimeException )和非运行时异常。Java异常又可以分为不受检查异常( Unchecked Exception )和检查异常( Checked Exception )。
Error 类对象由 Java 虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。 比如说: Java虚拟机运行错误( Virtual MachineError ), 当JVM不再有继续执行操作所需的内存资源时, 将出现 OutOfMemoryError(内存异常) 。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止; 对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状 况。在Java中,错误通常是使用 Error 的子类描述。 (本质上error错误发生的时候,交给虚拟机去处理终止线程即可).
在 Exception 分支中有一个重要的子类 RuntimeException (运行时异常),该类型的异常自动为你所编写的程序定义 ArrayIndexOutOfBoundsException (数组下标越界)、 NullPointerException (空指针异常)、ArithmeticException (算术异常)、 MissingResourceException (丢失资源)、 ClassNotFoundException (找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处 理,也可以不处理。 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;而 RuntimeException 之外的异常我们统称为非运行时异常,类型上属于 Exception 类及其子类.
Error 和 Exception 的区别: Error 通常是灾难性的致命的错误,是程序无法控制和 处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程; Exception 通常情况下是可 以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
检查异常:在正确的程序运行过程中,很容易出现的、情理可容的异常状况,在一定程度上这种异常的 发生是可以预测的,并且一旦发生该种异常,就必须采取某种方式进行处理。
解析:除了RuntimeException及其子类以外,其他的Exception类及其子类都属于检查异常,当程序 中可能出现这类异常,要么使用try-catch语句进行捕获,要么用throws子句抛出,否则编译无法通 过。 不受检查异常:包括RuntimeException及其子类和Error。 检查异常:除了RuntimeException及其子类以外,其他的Exception类及其子类都属于检查异常 分析: 不受检查异常为编译器不要求强制处理的异常, 检查异常则是编译器要求必须处置的异常。
异常处理五个关键字 分别是: try 、 catch 、 finally 、 throw 、 throws try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常 时,异常就被抛出。 catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。 finally – finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络 连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语 句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。 throw – 用于抛出异常。 throws – 用在方法签名中,用于声明该方法可能抛出的异常。
异常处理:try-catch-finally finally语句不是必要的
public static void main(String[] args) { int a=0; int b=1; // System.out.println(b/a);//出现ArithmeticException异常 //可以采用try-catch处理异常来处理 try{ //try监控 System.out.println(b/a); }catch(ArithmeticException e){ //异常捕获,catch(想要捕获的异常类型) //这里是捕获(1/0)出现的ArithmeticException异常,所以catch(ArithmeticException e) //如果是更高一层的错误,就不行了,要换成更高的错误类型,也就是说抛到更高级的异常去处理 System.out.println("程序出现异常,a不能为0"); }finally{ System.out.println("finally"); } }异常处理:try-catch(多个catch语句块匹配不同的异常类型)-finally 下述的语句块因为无限递归而导致栈溢出的错误。我们可以
public class test2 { public static void main(String[] args) { new test2().a(); } public void a(){ b(); } private void b() { a(); } }catch里面异常捕获类型应该上升到error,y栈溢出属于error错误,然后多个catch的时候,应该按照异常类型从小到大写。
public class test2 { public static void main(String[] args) { try { new test2().a(); } catch (ArithmeticException e) { System.out.println("不能这样的除法"); //e.printStackTrace();//打印错误信息 } catch (Error e) { System.out.println("不能这样递归"); //e.printStackTrace();//打印错误信息 } catch (Throwable e) { System.out.println("不能这样错误"); //e.printStackTrace();//打印错误信息 } finally { System.out.println("finally"); } } public void a() { b(); } private void b() { a(); } }主动的抛出异常
public class test2 { public static void main(String[] args) { int a = 0; int b = 1; new test2().test(b,a); } public void test(int a, int b) { if (b == 0) { throw new ArithmeticException(); //主动抛出异常,在方法中使用 } } } public class test2 { public static void main(String[] args) { int a = 0; int b = 1; try { new test2().test(b,a); } catch (ArithmeticException e) { // e.printStackTrace();//打印异常的信息 System.out.println("出现了异常"); } finally { System.out.println("finally"); } } //假设在这个方法中,处理不了这个异常的时候,或在方法上抛出异常 public void test(int a, int b) throws ArithmeticException { if (b == 0) { throw new ArithmeticException();//主动抛出异常,在方法体里写 } } } 输出: 出现了异常 finallytry, catch,finally ,return 执行顺序 1.执行try,catch , 给返回值赋值 2.执行finally 3.return