概述
异常
程序在执行时出现的不正常情况,是对问题的描写叙述。将问题进行对象的封装。
Java中的异常,就是对不正常情况进行描写叙述后的对象体现。
异常体系
Throwable
|--Error
|--Exception
|--RuntimeException
- 当中Error类处理严重异常,一般不编写针对性的代码对其进行处理。
- Exception类处理非严重异常,能够使用针对性的处理方式进行处理。
不管Error或者Excption都具有一些共同的属性和方法,比方不正常情况的信息和引发原因等。
异常类方法
- getMessage()
获取异常信息,返回字符串。 - toString()
获取异常类名和异常信息,返回字符串。 - printStackTrace()
获取异常类名和异常信息,以及异常出如今程序中的位置。直接打印,返回值void。 - printStackTrace(PrintStream s)
通经常使用该方法将异常内容保存在日志文件里,以便查阅。
特点
异常体系中全部的类以及建立的对象都具有可抛性,也就是说能够被throw和throwskeyword操作,仅仅有异常体系具备这个特点。
throw和throws的使用方法
- throw定义在方法内,用于产生异常对象。
- throws定义在方法上,用于抛出方法内产生的异常类,抛出多个异经常使用逗号隔开。
演示样例
class Div {int div(int a, int b) throws Exception // 必须对其的调用进行捕获或声明以便抛出{return a / b;}int MultiEx(int a, int b) throws ArithmeticException, ArrayIndexOutOfBoundsException {int c = a / b;int[] arr = new int[a];System.out.println(arr[a]);return c;}}public class ExceptionDemo {public static void main(String[] args) // throws Exception{Div d = new Div();try {int x = d.div(2, 0);System.out.println("x = " + x);} catch (Exception e) {System.out.println("异常!
");System.out.println(e.getMessage()); // 异常信息System.out.println(e.toString()); // 异常名称:异常信息e.printStackTrace(); // 异常名称:异常信息// 异常出现的位置}System.out.println("----------------");try {int x = d.MultiEx(4, 1);System.out.println("x = " + x);} catch (ArithmeticException e) {System.out.println("除数不能为0!");System.out.println(e.toString());} catch (ArrayIndexOutOfBoundsException e) {System.out.println("数组下标越界!
");System.out.println(e.toString());} catch (Exception e) {System.out.println(e.toString());}System.out.println("----------------");}}
执行结果
异常!
/ by zero
java.lang.ArithmeticException : / by zero
java.lang.ArithmeticException : / by zero
at Div.div(ExceptionDemo.java:4)
at ExceptionDemo.main(ExceptionDemo.java:21)
----------------
数组下标越界。
java.lang.ArrayIndexOutOfBoundsException : 4
----------------
分层思想
当捕获到异常,本功能处理不了时。能够继续在catch中抛出。
try{throw new AException();}catch(AException e){throw e;}
假设该异常处理不了。但并不属于该功能出现的异常。为了进行模块式开发,减少耦合性,能够将异常转换后,再抛出和该功能相关的异常。
或者异常能够处理,但须要将异常产生后和本功能相关的问题提供出去,抛出让调用者能够处理的异常和信息,也能够将捕获异常处理后转换新的异常抛出。
所以异常发生不一定抛出原来的异常,也能够在本层处理后抛出上一层能够接受的异常。
try{throw new AException();}catch(AException e){//对AException处理。throw new BException;}
异常处理方式
1. 捕捉
格式
try{
须要被检測的代码
}
catch(异常类 变量){
对捕获到的异常进行处理。异常对象的常见操作:String getMessage()获取异常信息等。
一定要定义详细的处理方法,不要简单一句e.printStackTrace(),也不要简单一句输出语句。一般使用错误日志进行保存。
}
finally{
定义一定运行的代码。通经常使用于关闭资源。
}
有三种结合方式
- try{}catch(){}
- try{}catch(){}finally{}
- try{}finally{}
注意
- finally中定义的一般是关闭资源码,由于资源必须释放。
- 仅仅有在catch中使用了System.exit(0)方法时,不运行finally中的代码。
2. 抛出
使用throwskeyword将产生的异常抛出。交由调用者处理。
3. 演示样例
class Demo1 {void func() throws Exception {// 异常处理:抛出throw new Exception();}}class Demo2 {void func() {// 异常处理:捕捉try {throw new Exception();} catch (Exception e) {}}}class Demo3 {void func() throws Exception {try {throw new Exception();} catch (Exception e) {// 捕捉异常。假设无法处理,能够继续抛出ethrow e;}}}class Demo4 {void func() {try {throw new Exception();} catch (Exception e1) {// 捕捉异常,假设无法处理。能够将异常e1转化成调用者可接受异常后抛出try {throw e1;} catch (Exception e2) {// 异常转换}}}}class Demo5 {void func() throws Exception {try {throw new Exception();} finally {// 关闭资源}}}
4. 多异常的处理
1. 声明异常时。建议声明更为详细的异常。这样处理能够做到更详细。
2. 声明几个异常。就相应有几个catch块,不要定义多余的catch块。
假设多个catch块中的异常出现继承关系,父类异常catch块放最后。
5. 异常分类
1. 编译时被检測异常(Exception类)
- 该异常在编译时,假设没有处理(没抛出也没捕捉)。编译失败。该异常被标识。表示能够被处理。
- 该异常必须进行异常处理(抛出或者捕捉)。
2. 执行时异常(编译时不检測。RuntimeException类)
- 编译时,不须要处理,编译器不检查。
- 假设在函数内抛出该异常或其子类异常。函数上不须要声明。
假设在函数上抛出该异常或其子类异常,调用者也不须要处理。
由于这类异常一般无法正确继续程序。一旦出现,希望终止程序并由程序猿改动代码以解决该类异常。 - 自己定义异常发生时,假设该异常无法继续程序执行,就让其继承RuntimeException。
6. 异常处理原则
- 当函数内部有throw抛出异常对象,并未进行try处理。必须在函数上声明,否则编译失败。
RuntimeException及其子类除外。
- 假设函数声明了异常。调用者须要进行处理。处理方式有两种。即捕捉和抛出。
- 函数上声明异常。可以提高安全性。强制调用者进行处理。
- 调用到抛出异常的功能时。抛出几个,就处理几个。出现一个try相应多个catch。当中父类的catch放最以下。
自己定义异常
依照Java的面向对象思想。将程序中出现的特有问题进行封装。
用法
定义继承Exception或者RuntimeException的异常类
1. 为了让该自己定义类具有可抛性。
2. 让该类具备操作异常的共性方法。
3. 当要定义自己定义异常信息时,能够使用父类已经定义好的功能,异常信息传递给父类的构造函数。
class MyException extends Exception{MyException(String msg){super(msg);}}
自己定义异常的优点
1. 将问题进行封装。
2. 将正常流程代码和问题处理代码相分离,方便阅读。
自己定义异常在父子类方法重写中的情况
1. 子类在重写父类时。假设父类的方法抛出异常,那么子类的重写方法,仅仅能抛出父类的异常或者该异常的子类。
2. 假设父类方法抛出多异常,那么子类的重写方法。仅仅能抛出父类异常的子集。
3. 假设父类或者接口方法中没有异常抛出。那么子类在重写方法时,也不能够抛出异常。假设子类方法发生异常,仅仅能在方法内部进行捕捉处理。
演示样例
/** 自己定义异常继承体系* Exception* |--AException* | |--BException* |--CException*/class AException extends Exception {}class BException extends AException {}class CException extends Exception {}class Father {void func() throws AException {}}class Son extends Father {void func() throws BException {// 仅仅能抛出AException或者AException的子类BException,不能抛出CException// 假设子类产生新异常CException。这里仅仅能try,不能抛出。}}
自己定义异常演示样例
class NegativeException extends Exception {private int value;NegativeException(String msg) {super(msg);}NegativeException(String msg, int value) {super(msg);this.value = value;}int getValue() {return value;}}class Demo {int customExc(int x) throws NegativeException // 函数内手动抛出非执行时异常。必须对其进行捕捉或声明抛出。{if (x < 0) throw new NegativeException("负数!", x);return x;}int runtimeExc(int x) // 函数内手动抛出RuntimeException异常或其子类异常,不须要对其进行捕捉或声明抛出。{if (x == 0) throw new ArithmeticException("数值为0!
");return x;}void checkString(String s) {if (s.equals("String"))// 避免空指针异常,应改动为:// if("String".equals(s))System.out.println("PASS!");elseSystem.out.println("FAIL!");}}public class ExceptionCustom {public static void main(String[] args) // throws Exception{Demo d = new Demo();try {int x = d.customExc(-3);System.out.println("x = " + x);} catch (NegativeException e) {System.out.println(e.toString() + "\n该数为:" + e.getValue());}System.out.println("-------------------");d.runtimeExc(0); // 算术异常(执行时),停止程序,须要程序猿改动代码。System.out.println("-------------------");d.checkString("String");d.checkString(null); // 空指针异常(执行时)。
System.out.println("-------------------");}}
自己定义异常实例
// 员工使用电脑案例/*** 电脑死机异常*/class CrashException extends Exception {CrashException(String msg) {super(msg);}}/*** 电脑烧毁异常*/class BurnException extends Exception {BurnException(String msg) {super(msg);}}/*** 无法工作异常*/class WorkException extends Exception {WorkException(String msg) {super(msg);}}class Computer {// 电脑状态,0电脑正常。1电脑死机。2电脑烧毁private int state = 0;public void run() throws CrashException, BurnException {if (state == 1) throw new CrashException("电脑崩溃了!");if (state == 2) throw new BurnException("电脑烧毁了!");System.out.println("电脑执行...");}public void reboot() {System.out.println("电脑重新启动...");state = 0;}public void setState(int state) {this.state = state;}}abstract class Employee {private String name;Employee(String name) {this.name = name;}abstract void work() throws WorkException;}class Staff extends Employee {private Computer com;Staff(String name) {super(name);com = new Computer();}public void work() throws WorkException {try {com.run();} catch (CrashException e) {// 假设电脑死机了。则重新启动电脑就可以System.out.println(e.toString());com.reboot();} catch (BurnException e) {// 假设电脑烧毁了。则向上级报告。抛出无法工作异常请求放假。throw new WorkException("无法继续工作!\n原因:" + e.toString());}System.out.println("工作!");}public void computerStateChange(int state) {com.setState(state);}}public class ExceptionCase {public static void main(String[] args) {Staff s = new Staff("Jacob");// 分别针对不同的电脑状态,模拟工作情况for (int i = 0; i < 3; i++) {System.out.println("------------------情况" + i + ":------------------");// 更改员工电脑的状态s.computerStateChange(i);// 员工工作try {s.work();} catch (WorkException e) {System.out.println(e.toString() + "\n放假!
");}}}}
执行结果
------------------情况0:------------------
电脑执行...
工作!
------------------情况1:------------------
CrashException: 电脑崩溃了。
电脑重新启动...
工作。
------------------情况2:------------------
WorkException: 无法继续工作!
原因:BurnException: 电脑烧毁了!
放假。
浙公网安备 33010602011771号