异常处理
知识框架:
异常的概念
什么是异常:在程序运行过程中出现了不正常的情况,称为异常。
java语言提供了异常的处理方式,将异常信息打印输出到控制台,供程序员参考。
异常的作用:增加程序的健壮性。
例如:
public class ExceptionTest01 {
public static void main(String[] args) {
int i1 = 100;
int i2 = 0;
int i3 = i1/i2;
System.out.println(i3);
}
结果:
异常的分类
异常可以分为:错误、编译时异常(受控异常)和运行时异常(非受控异常),都是发生在运行阶段的,编译阶段异常是不会发生的。因为程序只有在运行阶段才可以new对象。异常的发生就是new异常对象。
错误、编译时异常和运行时异常的区别:
错误:如果应用程序出现了 Error,那么将无法恢复,只能重新启动应用程序,最典型的Error 的异常是:OutOfMemoryError。
编译时异常一般发生的概率比较大。对于一些发生概率较高的异常,需要在运行之前对其进行预处理。
运行时异常一般发生的概率比较低。可以不用预处理。
异常的捕获和处理
try、catch 和 finally
异常的捕获和处理需要采用try 和catch 来处理,具体格式如下:
try {
}catch(OneException e) {
}catch(TwoException e) {
}finally {
}
try 中包含了可能产生异常的代码。
try 后面是catch,catch 可以有一个或多个,catch 中是需要捕获的异常。
当try 中的代码出现异常时,出现异常下面的代码不会执行,马上会跳转到相应的catch 语句块中,如果没有异常不会跳转到catch 中。
finally 表示,不管是出现异常,还是没有出现异常,finally 里的代码都会执行,通常在finally 里关闭资源。finally 和catch可以分开使用,但finally 必须和try 一块使用,例如如下格式使用finally 。
try {
}finally {
}
例如:
public class ExceptionTest02 {
public static void main(String[] args) {
int i1 = 100;
int i2 = 0;
//try 里面是出现异常的代码
try {
//被 0 除表达式以下的语句永远不会执行
int i3 = i1/i2;
//永远不会执行
System.out.println(i3);
//采用catch 可以拦截异常
//e 代表了一个ArithmeticException 类型的局部变量
//采用 e 可以拿到更详细的异常信息
}catch(ArithmeticException e)
{ System.out.println("被 0 除了");
}
}
final、finalize 和 finally的区别
区别:
final 关键字:
final修饰的类无法继承。
final修饰的方法无法覆盖。
final修饰的变量不能重新复制。
finally 关键字:
和try 一起联合使用。
finally语句块中的代码是必定会执行的。
finalize 标识符:
是一个Object类中的方法名。
这个方法是由垃圾回收器GC负责调用的。
getMessage 和 printStackTrace()
如何取得异常对象的具体信息,常用的方法主要有两种:
取得异常描述信息:getMessage()
取得异常的堆栈信息(比较适合于程序调试阶段):printStackTrace();
例如:
public class ExceptionTest03 {
public static void main(String[] args) {
int i1 = 100;
int i2 = 0;
try {
int i3=i1/i2;
System.out.println(i3);
}catch(ArithmeticException e) {
//e 是一个引用,它指向了堆中的ArithmeticException
//通过getMessage 可以得到异常的描述信息
System.out.println(e.getMessage());
//通过printStackTrace 可以打印栈结构
e.printStackTrace();
}
}
}
如何声明异常
在方法定义处采用 throws 声明异常,如果声明的异常为受控异常,那么调用方法必须处理此异常。
throws 和throw 的区别?thorws 是声明异常,throw 是抛出异常。
异常的捕获顺序应该是:从小到大。
自定义异常
自定义异常通常继承于 Exception 或 RuntimeException,继承哪个应该看具体情况。
Java中怎么自定义异常呢?
有两步:
第一步:编写一个类继承Exception或者RuntimeException。
第二步:提供两个构造方法,一个无参数的,一个带有String参数的。
例如,自定义受控异常:
import java.io.*;
public class ExceptionTest04 {
public static void main(String[] args) {
try {method1(10, 0);
}catch(MyException e) {
System.out.println(e.getMessage());
}
}
private static void method1(int value1, int value2) throws MyException { //如果是受控异常必须声明
if (value2 == 0) {
throw new MyException("除数为 0");
}
int value3 = value1 / value2; System.out.println(value3);
}
}
//自定义受控异常
class MyException extends Exception {
public MyException() {
//调用父类的默认构造函数
super();
}
public MyException(String message) {
//手动调用父类的构造方法
super(message);
}
}
方法覆盖和异常
方法覆盖的条件:
子类方法不能抛出比父类方法更多的异常,但可以抛出父类方法异常的子异常。