版权声明:本文为博主原创文章,转载请注明出处。
1.以下是异常的基本介绍:Java异常层次结构图 如下
Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类,结构如上图(以上结构图中的子类异常并不是所有的,只是标注了一些重要的常见的异常)。
Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。
大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(VirtualMachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。
Exception(异常):是程序本身可以处理的异常。
Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。
Exception 和 RuntimeException 的区别:
1.Exception 表示程序运行过程中可能出现的非正常状态,RuntimeException表示虚拟机非通常操作中可能遇到的异常,是一种常见运行错误。Java编译器要求方法必须声明抛出可能发生的非运行时异常,但并不要求必须声明抛出未被捕获的运行时异常,即 Exception 定义了必须处理的异常,而 RuntimeException 定义的异常可以选择性的进行处理。
2.RuntimeException 是 Exception 的子类。
2.异常的处理
在Java中,如果某个方法抛出异常,既可以在当前方法中进行捕捉,然后处理该异常,也可以将该异常向上抛出,由方法调用者来处理。
a>.Java的异常捕获结构由try、cache和finally3个部分组成,例如:
1 try { 2 // 可能会抛出异常的代码块 3 int result = 2 / 0; 4 System.out.print("运算结果:" + result); 5 } catch (ArithmeticException e) { 6 // 对异常1的处理 7 System.out.print("出现了算术异常"); 8 } catch (Exception e) { 9 // 对异常2的处理 10 // 以此类推还可以加各种异常的处理,由上图结构可知,Exception是运行时异常的父类,所以所有异常都能被exception接收,一般情况下如果没有对特定异常的特殊处理catch写exception就可以了 11 e.printStackTrace();// 打印异常的堆栈信息 12 } finally { 13 // 程序代码块 -- 异常处理结构最后处理的部分 14 }
try 语句块:用于执行可能有异常的代码块。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
catch语句块:一个try catch结构中可以有多个catch,捕获不同的异常做不同的异常处理,没有特殊需求,一般用一个Exception就可以了
异常捕获范围问题:多个catch的时候,所有捕获范围小的异常必须放在捕获范围大的异常之前,否则程序在编译时就会出现错误提示。参考异常结构图,例如上面的代码段,把 Exception 和 ArithmeticException 交换位置,Exception在前, 由异常结构图可知,Exception是ArithmeticException 的父类,所以有算术异常的时候,Exception也可以捕获该异常,后面添加 ArithmeticException 已经没有用了,故而会直接编译报错。
finally语句块:一个try catch结构中finally可写可不写,有finally语句块的时候,表示不管是否有异常该代码块一定会被执行,一般常用于输入流、输出流关闭。
注意:面试常被问的地方:如果在try里面有return,finally是否执行。答:finally语句块依旧会被执行,在try语句块中的return之前执行
以下4中特殊情况finally不会执行:
-
- 在finally语句块中发生了异常
- 在前面的代码中使用了System.exit()退出程序
- 程序所在线程死亡
- 关闭CPU
b>.throws,throw
某个方法可能会发生异常,但不想在当前方法中处理这个异常,则可以使用 throws,throw 关键字在方法中抛出异常。
throws关键字通常被应用在声明方法时,用来指定方法可能抛出的异常(多个异常可用逗号分隔 ),语法如下:
1 public static void main(String[] args) { 2 try{ 3 test(); 4 }catch(ArithmeticException e){ 5 System.out.print("test()方法抛出算术异常"); 6 } 7 } 8 9 public static void test() throws ArithmeticException{ 10 int result = 3/0; 11 }
使用throws 关键字将异常抛给上一级以后,如果不想处理该异常,可以继续向上抛出,如果main() throws Exception 就相当于交给JVM进行异常处理。
throw 关键字通常用于方法体中,并且抛出一个异常对象。程序执行到throw语句时立即终止,它后面的语句都不执行。
1 public static void main(String[] args) { 2 try { 3 throw new Exception("抛着玩的"); 4 } catch (Exception e) { 5 e.printStackTrace(); 6 } 7 }
程序运行结果:
java.lang.Exception: 抛着玩的
at test.TestException2.main(TestException2.java:11)
由于存在了throw关键字,本程序会手工抛出一个异常类的实例化对象,而此时程序必须使用 try...catch 语句进行处理,或者在方法上增加一个throws声明,否则程序会编译出错。
throw 和 throws 的区别:
throw:用户手工抛出异常类的实例化对象;
throws:用于方法的声明上,表示此方法不处理异常,而将异常
c>.自定义异常
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户只需继承Exception类即可自定义异常类。
在程序中使用自定义异常类,大体可分为以下几个步骤。
(1)创建自定义异常类。
(2)在方法中通过throw关键字抛出异常对象。
(3)如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
(4)在出现异常方法的调用者中捕获并处理异常。
1 public class MyException extends Exception { // 定义异常类 2 public MyException(String errMessage){ 3 super(errMessage); 4 } 5 } 6 7 public static int avg(int num1, int num2) throws MyException { 8 if (num1 < 0 || num2 < 0) { 9 throw new MyException("不可以使用负数"); 10 } 11 if (num1 > 100 || num2 > 100) { 12 throw new MyException("数值太大了"); 13 } 14 return (num1 + num2) / 2; 15 } 16 17 public static void main(String[] args) { 18 try { 19 int result = avg(103, 150); 20 System.out.print(result); 21 } catch (MyException e) { 22 System.out.print(e); 23 } 24 }
运行结果:
test.MyException: 数值太大了
3.常见异常类
- NullPointerException 空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等。
- ClassCastException 类型转换异常
- ClassNotFoundException 未找到相应的类异常
- ArithmeticException 算术异常
- ArrayIndexOutOfBoundsException 数组索引越界异常
- ArrayStoreException 数组中包含不兼容的值抛出的异常
- SQLException 操作数据库异常类
- NoSuchFieldException 字段未找到异常
-
NoSuchMethodException 方法未找到抛出的异常
- NumberFormatException 字符串转换为数字抛出的异常
- NegativeArraySizeException 数组长度为负异常
- StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
- IOException 操作输入流和输出流时可能出现的异常
- IllegalArgumentException 非法参数异常
- InstantiationException 当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常
- ArrayStoreException 数组中包含不兼容的值抛出的异常
- SecurityException 安全性异常
- EOFException 文件已结束异常
- FileNotFoundException 文件未找到异常
- NumberFormatException 字符串转换为数字抛出的异常
- IllegalAccessException 不允许访问某类异常