异常
定义
- 对问题的描述,将问题进行对象的封装
异常体系
Throwable
|--Exception
|--RuntimeException
|--...
|--XxxxException
|--Error
异常体系的特点
- 异常体系中的所有类与对象都具有
可抛性
- 也就是说都可以被
throw
、throws
所操作 - JAVA中只有异常体系具备这一特点
throw和throws的用法
- throw定义在
函数内
,用于抛出异常对象 - throws定义在
函数上
,用于声明异常类,可以同时声明多个异常类,用逗号隔开 - 当函数中有throw抛出异常对象,并且没有进行
try
catch
处理,必须在函数上通过hrows
声明异常,否则编译失败
RuntimeException
类异常除外,如果函数中抛出此异常,函数上可以不用声明
- 如果函数声明了异常,调用者在调用时可以继续抛出异常,也可以通过
try
catch
处理此异常
异常分为两种:
- 编译时被检测异常
- 该异常在编译时如果没有处理,编译失败
- 该异常被标识,代表着可以被处理
- 运行时异常(编译时不检测)
- 在编译时不需要处理,编译器不检测
- 该异常的发生,建议不处理,让程序停止并对代码进行修正
异常处理语句
try{
需要被检测的代码
}
catch(捕获的异常对象){
处理异常的代码
}
finally{
一定会被执行的代码
}
异常的三种编写格式
第一种:
try{
} catch( ){
}
第二种:
try{
} catch( ){
} fianlly{
}
第三种:
try{
} finally{
}
注意:
finally中通常定义的是关闭资源代码,因为资源必须被释放。
finally语句中的代码只有一种情况下不会被执行,就是当执行到System.exit(0);
时
自定义异常
- 定义类继承Exception或RuntimeException
- 为了让该自定义类具备可抛性
- 让该类具备操作异常的共性方法
- 当要定义自定义类的异常信息时,可以使用父类已经定义好的功能,让子类异常信息传递给父类的构造函数:
class MyException extends Exception{
MyException(String message){
super(message);
}
}
- 按照JAVA的面向对象的思想,将程序中出现的特有问题进行封装
异常的好处
- 将问题进行封装
- 将正常流程代码和问题处理代码相分离,便于阅读
异常的处理原则
- 处理方式:try 和 throws
- 调用到抛出异常的功能时,抛出几个就要处理几个:一个try对应多个catch
- 多个catch,父类的catch放到最下面
- catch内需要定义针对性的处理方式,不要简单地定义printStackTrace、输出语句,也不要不写
- 当捕获到的异常,本功能处理不了时,可以继续在catch中抛出
try{
throw new AException();
} catch (AException e){
throw e;
}
- 如果该异常处理不了,而且并不属于该功能出现的异常,可以将该异常转换后抛出和该功能相关的异常
- 或者该异常可以处理,但需要将该异常产生的和本功能相关的问题提供出去,让调用者知道并处理;也可以将捕获到的异常处理后,转换新的异常
try {
throw new AException();
} catch (AException e){
//对AException先进行处理
throw new BException();
}
异常的注意事项
- 在子类覆盖时
- 子类抛出的异常必须是父类异常的子集或子类
- 如果父类或者接口没有异常抛出时,子类覆盖异常出现异常,只能try不能抛
子父类异常示例
class BlueScriptException extends Exception{
BlueScriptException(String message){
super(message);
}
}
class BrokenException extends Exception{
BrokenException(String message){
super(message);
}
}
class NoPlanException extends Exception{
NoPlanException(String message){
super(message);
}
}
class Computer{
private int state = 3;
public void run()throws BlueScriptException,BrokenException{
if(state == 2)
throw new BlueScriptException("电脑蓝屏了");
if(state == 3)
throw new BrokenException("电脑坏掉了");
System.out.println("电脑运行");
}
public void reset(){
System.out.println("电脑重启");
}
}
class Teacher{
private String name;
private Computer cmt;
Teacher(String name){
this.name = name;
cmt = new Computer();
}
public void tech()throws NoPlanException{
try{
cmt.run();
System.out.println("老师开始上课");
}
catch(BlueScriptException e){
System.out.println(e.getMessage());
cmt.reset();
}
catch(BrokenException e){
System.out.println(e.getMessage());
throw new NoPlanException("课时进度无法继续");
}
}
public void test(){
System.out.println("同学们做练习题");
}
}
class ExceptionTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO 自动生成的方法存根
Teacher t = new Teacher("蒋老师");
try{
t.tech();
}
catch(NoPlanException e){
t.test();
System.out.println("test原因:"+e.getMessage());
}
}
}
输出结果:
电脑坏掉了
同学们做练习题
test原因:课时进度无法继续
RuntimeException异常示例
interface Mir {
void mianji();
}
class Rec implements Mir{
private double len,wid;
Rec(double len,double wid){
if(len<=0 || wid<=0)
throw new NoValueException("长或宽数据不合法,请重新输入");
this.len = len;
this.wid = wid;
}
public void mianji(){
System.out.println("长方形面积 = "+len*wid);
}
}
class Circle implements Mir{
private double ricl;
public static final double PI = 3.14;
Circle(double ricl){
if(ricl<=0)
throw new NoValueException("半径不合法,请重新输入");
this.ricl = ricl;
}
public void mianji(){
System.out.println("圆形面积 = "+ricl*ricl*PI);
}
}
class NoValueException extends RuntimeException{
NoValueException(String message){
super(message);
}
}
class ExceptionTest2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
try{
Rec r = new Rec(4,5);
r.mianji();
Circle c = new Circle(-5);
c.mianji();
} catch(NoValueException e){
System.out.println(e.toString());
}
}
}
输出结果:
长方形面积 = 20.0
ExceptionTest2.NoValueException: 半径不合法,请重新输入