Java 中的异常(Exception)又称为例外,是一个在程序执行期间发生的事件,它中断正在执行的程序的正常指令流。为了能够及时有效地处理程序中的运行错误,必须使用异常类。
1. 异常类型
Throwable是Java中异常的根类,它有两个子类:
Exception:是程序本身可以处理的异常。异常处理通常就是针对这种类型异常的处理。它也可以细分为两个方向:
非检查异常(运行时异常):编译器不要求强制处理的异常,程序员可以不管也可以捕获。
例:空指针异常、数组下标越界、算数异常、类型转换异常等等
检查异常:编译器要求必须处理的异常,否则通不过变异
例:IO异常、SQL异常
Error:是程序无法处理的错误,表示运行应用程序中较严重的问题。常见的有:虚拟机错误、内存溢出、线程死锁。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 异常类型 2 Throwable 3 错误Error 4 错误不是异常,程序无法处理的错误,表示运行应用程序中较严重的问题。 5 常见的有:虚拟机错误、内存溢出(堆栈溢出)、线程死锁。 6 错误类 7 VirtualMachineError 虚拟机错误 8 OutOfMemoryError 内存溢出错误类 9 StackOverflowError 栈溢出错误类 10 LinkageError 链接错误类 11 NoClassDefFoundError 类定义未找到错误类 12 AWTError 图形用户界面错误类 13 异常Exception 14 是程序本身可以处理的异常。异常处理通常就是针对这种类型异常的处理。 15 检查性异常 16 用户错误或问题引起的异常,这是程序员无法预见的,是必须进行处理的异常,如果不处理,程序就不能编译通过。 17 java内置的非运行时异常 18 ClassNotFoundException 应用程序试图加载类时,找不到相应的类,抛出该异常。 19 InterruptedException 一个线程被另一个线程中断,抛出该异常。 20 IOException I/O 异常的根类 21 EOFException 文件结束 22 FileNotFoundException 找不到文件 23 SQLException 操作数据库异常 24 NoSuchFieldException 请求的变量不存在 25 NoSuchMethodException 请求的方法不存在 26 CloneNotSupportedException 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。 27 IllegalAccessException 拒绝访问一个类的时候,抛出该异常。 28 InstantiationException 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 29 运行时异常 30 一般由程序逻辑错误引起,是可能被程序员避免的异常。在编译时被忽略,程序中可以选择捕获处理,也可以不处理。 31 RuntimeException 32 NullPointerException 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 33 ArithmeticException 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。 34 ClassCastException 当试图将对象强制转换为不是实例的子类时,抛出该异常。 35 NumberFormatException 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 36 IllegalMonitorStateException 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 37 IndexOutOfBoundsException 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 38 StringIndexOutOfBoundsException 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 39 ArrayIndexOutOfBoundsException 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 40 IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。 41 UnsupportedOperationException 当不支持请求的操作时,抛出该异常。 42 ArrayStoreException 试图将错误类型的对象存储到一个对象数组时抛出的异常。 43 IllegalStateException 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 44 IllegalThreadStateException 线程没有处于请求操作所要求的适当状态时抛出的异常。 45 NegativeArraySizeException 如果应用程序试图创建大小为负的数组,则抛出该异常。 46 SecurityException 由安全管理器抛出的异常,指示存在安全侵犯。 47 用户自定义的Exception异常 48 所有异常都必须是 Throwable 的子类。 49 如果希望写一个检查性异常类,则需要继承 Exception 类。 50 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
2. 异常处理
异常处理方法:
捕获异常
声明异常
抛出异常
Java 的异常处理通过 5 个关键字来实现:try、catch、throw、throws 和 finally。
try catch 语句用于捕获并处理异常,finally 语句用于在任何情况下(除特殊情况外)都必须执行的代码,
throw 语句用于拋出异常,
throws 语句用于声明可能会出现的异常。
throws 在方法(类)的声明处声明可能要抛出的异常,通常不用显示地捕获异常,可由系统自动将所有捕获的异常信息抛给上级方法;
当一个方法产生一个它不处理的异常时,那么就需要在该方法的头部声明这个异常,以便将该异常传递到方法的外部进行处理。
子类方法拋出的异常不会超过父类定义的范围。子类在覆盖父类带 throws 子句的方法时,子类的方法声明中的 throws 子句不能出现父类对应方法的 throws 子句中没有的异常类型,
也可以申明未检查的异常,但这不是编译器强制的。如果方法抛出了异常那么调用这个方法的时候就需要将这个异常处理或者继续抛出。
throw 在方法(类)内部手动抛出一个具体的异常类型。需要用户自己捕获相关的异常,而后再对其进行相关包装,最后将包装后的异常信息抛出。
按照语法你可以抛出任意 Throwable (i.e. Throwable或任何Throwable的衍生类) , throw可以中断程序运行,因此可以用来代替return。
最常见的例子是用 throw 在一个空方法中需要return的地方抛出 UnSupportedOperationException
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 异常处理 2 捕获异常 3 try 执行可能产生异常的代码 4 catch 捕获异常 5 finally 6 finally 用于和try{}catch(){}finally{}组合进行异常处理。用于释放资源,在IO流操作、数据库操作、保证unlock锁 中会见到。 7 特点: 8 1) 不管有没有出现异常,被finally控制的语句体一定会执行。 9 特殊情况 10 1. 在执行到finally之前jvm退出了(比如System.exit(0)) 11 2. try语句中无限循环; 12 3. 线程被杀死; 13 2) 当try和catch中有return时,finally仍然会执行; 14 3) finally是在retrun后面的表达式运算后执行的,不会影响返回值。 15 (此时并没有真的return,而是先把要return的值保存起来,不管最后中的代码怎么样,返回的值都不会改变,仍然是之前保存的值) 16 4) finally中间好不要包含返回,否则程序会提前退出,返回值不是try和catch中保存的返回值 17 return 18 1) 当try或者catch中有返回值,但是finaly中也有返回语句时,最终返回的是finally中的返回值。 19 2) 当try或者catch进行了return,但是finally中对返回值进行了修改,返回值在try中被缓存了,后面的更改并不能修改到缓存了的返回值。但是在finally中写return是可以返回成功的。 20 try-with-resource只是JDK实现了一个语法糖,本质上还是try-catch-finally 21 声明异常 22 throws 在方法(类)的声明处声明可能要抛出的异常 23 当一个方法产生一个它不处理的异常时,那么就需要在该方法的头部声明这个异常,以便将该异常传递到方法的外部进行处理。 24 子类在覆盖父类带 throws 子句的方法时,子类的方法声明中的 throws 子句不能出现父类对应方法的 throws 子句中没有的异常类型, 25 子类方法拋出的异常不会超过父类定义的范围。 26 抛出异常 27 throw 在方法(类)内部手动抛出一个具体的异常类型。 28 throw 需要用户自己捕获相关的异常,而后再对其进行相关包装,最后将包装后的异常信息抛出。 29 throws vs throw 30 throws 用来声明一个方法可能抛出的所有异常信息 31 throw 则是指拋出的一个具体的异常类型。 32 方法(类)声明处 通过 throws 声明方法(类)可能拋出的异常信息, 33 方法(类)内部 通过 throw 抛出一个具体的异常信息。 34 throws 通常不用显示地捕获异常,可由系统自动将所有捕获的异常信息抛给上级方法; 35 throw 则需要用户自己捕获相关的异常,而后再对其进行相关包装,最后将包装后的异常信息抛出。
3. 补充
出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果没有处理块,到最上层,如果是多线程就由 Thread.run()抛出 ,如果是单线程就被 main() 抛出 。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。运行时异常是 Exception 的子类,也有一般异常的特点,是可以被 Catch 块处理的。只不过往往我们不对他处理罢了。也就是说,你如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。
如果不想终止,则必须扑捉所有的运行时异常,决不让这个处理线程退出。队列里面出现异常数据了,正常的处理应该是把异常数据舍弃,然后记录日志。不应该由于异常数据而影响下面对正常数据的处理。 在这个场景这样处理可能是一个比较好的应用,但并不代表在所有的场景你都应该如此。如果在其它场景,遇到了一些错误,如果退出程序比较好,这时你就可以不太理会运行时异常 ,或者是通过对异常的处理显式的控制程序退出。