异常:就是程序在运行时出现不正常的情况。
异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象
其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分:两种:一种是严重的问题,一种是非严重的问题。
对于严重的,java通过Error类进行描述。
对于Error一般不编写针对性的代码对其进行处理。
对于非严重的,java通过Exception类进行描述。
对于Exception可以使用针对性的处理方式进行处理。
无论Error或者Exception都具有一些共性内容。
比如:不正常情况的信息,引发原因等。
异常体系:
Throwable
|--Error
|--Exception
|--RuntimeException
异常的处理
java提供了特有的语句进行处理
try
{
需要被检测的代码;
}
catch(异常类 变量)
{
处理异常的代码;(处理方式)
}
finally
{
一定会执行的语句;
}
对捕获到的异常对象进行常见方法操作。
String getMessage():获取异常信息
String toString():获取异常的简短描述
void printStaktTrace():获取异常的详细信息
在函数上声明异常,便于提高安全性,让调出者进行处理,不处理编译失败。
对多异常的处理
1、声明异常时,建议声明更为具体的异常,这样处理得更具体
2、对方声明几个异常,就有几个catch块,不要定义多余的catch块
如果多个异常中出现继承关心,那么父类catch放在最下面
建议在进行catch处理时,catch中一定要定义具体的处理方式
不要简单定义一句 e.printStackTrace(),也不要简单的书写一条输出语句
通常生成异常日志,方便更好地维护
class Demo
{
int show(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException//在功能上通过throws的关键字声明了该功能有可能会出现问题。
{
int[] arr=new int[a];
System.out.println(arr[3]);
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args)
{
Demo d=new Demo();
try
{
int div=d.show(2,3);
System.out.println(div);
}
catch (ArithmeticException e)
{
System.out.println("除零了");
System.out.println(e.toString());//异常名称:异常信息
// System.out.println(e.getMessage());//异常信息
//
// e.printStackTrace();//异常名称,异常信息,异常出现的位置
//其实JVM默认的异常处理机制,就是在调用printStackTrace方法
//打印异常的堆栈的跟踪信息。
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("角标越界了"+e.toString());
}
catch (Exception e)
{
System.out.println(e.toString());
}
System.out.println("Over");
}
}
Exception中有一个特殊的子类异常
RuntimeException 运行时异常
如果函数内抛出该异常,函数上可以不用声明,编译一样通过
如果函数上声明了该异常,调用者可以不用进行处理,编译一样通过
之所以不用在函数声明,是因为不需要让调用者处理,当该异常发生,
希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止
程序后,对代码进行修改。
自定义异常时:如果该异常的发生,无法再继续进行运算,就让
自定义异常继承RuntimeException
对于异常非两种:
1、编译时被检测的异常
2、编译时不被检测的异常(运行时异常,RuntimeException以及其子类)
class Demo
{
int div(int a,int b)throws Exception//,ArithmeticException RuntimeException异常不用声明,声明不用处理
{
if (b<0)
throw new Exception("除数为负数");
if(b==0)
throw new ArithmeticException("被零除了");
return a/b;
}
}
需求:毕老师用电脑讲课
class LanPingException extends Exception
{
LanPingException(String message)
{
super(message);
}
}
class MaoYanException extends Exception//RuntimeException
{
MaoYanException(String message)
{
super(message);
}
}
class NoPlanException extends Exception
{
NoPlanException(String message)
{
super(message);
}
}
class Computer
{
private int state=1;
void run()throws LanPingException,MaoYanException
{
if (state==2)
throw new LanPingException("电脑蓝屏了");
if(state==3)
throw new MaoYanException("电脑冒烟了");
System.out.println("电脑运行");
}
void reset()
{
state=1;
System.out.println("电脑重启");
}
}
class Teacher
{
private String name;
private Computer cm;
Teacher(String name)
{
this.name=name;
cm=new Computer();
}
void prelect()throws NoPlanException
{
try
{
cm.run();
System.out.println(name+"用电脑讲课");
}
catch (LanPingException e)
{
System.out.println(e.toString());
cm.reset();
System.out.println(name+"用电脑讲课");
}
catch (MaoYanException e)
{
test();
throw new NoPlanException("课时无法继续"+e.toString());
}
}
void test()
{
System.out.println("练习");
}
}
class ExceptionTest
{
public static void main(String[] args)
{
Teacher t=new Teacher("毕老师");
try
{
t.prelect();
}
catch (NoPlanException e)
{
System.out.println(e.toString());
System.out.println("换老师或者放假");
}
}
}
finally代码块:定义一定执行的代码。
通常用于关闭资源
finally只有一种情况不会执行,当执行到System.exit(0);finally不会执行
class NoException extends Exception
{
}
public void method()throws NoException
{
连接数据库;
数据操作;//throw new SQLException();
关闭数据库;//该动作,无论数据操作是否成功,一定要关闭资源
try
{
连接数据库;
数据操作;//throw new SQLException();
}
catch (SQLException e)
{
会对数据库进行异常处理;//内部进行处理
throw new NoException();//抛出异常,告诉操作未成功
}
finally
{
关闭数据库;
}
}
第一个格式:
try
{
}
catch ()
{
}
第二个格式:
try
{
}
catch ()
{
}
finally
{
}
第三个格式:
try
{
}
finally
{
}
记住一点: catch 是用于处理异常,如果没有catch就代表异常没有被处理过,
如果该异常是检测时异常,那么必须声明。
class Demo
{
public void method()
{
try
{
throw new Exception();
}
finally
{
//关闭资源
}
}
}
异常的好处:
1、将问题进行封装
2、将正常流程代码和问题处理代码相分离,方便于阅读
异常的处理原则:
1、处理方式有两种:try或者throws
2、调用到抛出异常的功能时,抛出几个,就处理几个。
一个try对应多个catch
3、多个catch,父类的catch放到最下面
4、catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace,输出语句,
也不要不写
当捕获到的异常,本功能处理不了时,可以继续在catch中抛出
try
{
throw new AException();
}
catch (AException e)
{
throw e;
}
如果该异常处理不了,但并不属于该功能出现的异常,
可以将异常转换后,再抛出和该功能相关的异常
或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,让调用者知道,
并处理,也可以将捕获的异常处理后,转换为新的异常
try
{
throw new AException();
}
catch (AException e)
{
//对AException处理
throw new BException();
}
异常在子父类覆盖中的体现:
1、子类在覆盖父类时,如果父类的方法抛出异常,那么子类在覆盖方法时,只能抛出父类的异常或者该异常的子类。
2、如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
3、如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常
如果子类方法发生了异常,就必须要进行try处理,绝对不能抛。
举例说明为什么子类不能抛出超出父类的异常?
class AException extends Exception
{
}
class BException extends AException
{
}
class CException extends Exception
{
}
class Test
{
void function(Fu f)
{
try
{
f.show();
}
catch (AException e)
{
}
}
}
class Zi extends Fu
{
void show()throws CException
{
}
}
class
{
public static void main(String[] args)
{
Test t = new Test();
t.function(new Zi());
}
}
需求:有一个圆形和长方形,求面积。
对于面积如果出现非法的数值,视为是获取面积出现问题。
问题通过异常表示,现在开始设计这个程序
class NoValueException extends RuntimeException
{
NoValueException(String message)
{
super(message);
}
}
interface Shape
{
void getArea();
}
class Rec implements Shape
{
private int len,wid;
Rec(int len,int wid) //throws NoValueException
{
if(len<=0|| wid<=0)
throw new NoValueException("非法数值");
this.len=len;
this.wid=wid;
}
public void getArea()
{
System.out.println(len*wid);
}
}
class Circle implements Shape
{
private int radius;
public static final double PI=3.14;
Circle(int radius)//throws NoValueException
{
if(radius<=0)
throw new NoValueException("非法");
this.radius=radius;
}
public void getArea()
{
System.out.println(radius*radius*PI);
}
}
class ExceptionTest
{
public static void main(String[] args)
{
//try
//{
Rec r=new Rec(-3,5);
r.getArea();
//}
//catch (NoValueException e)
//{
// System.out.println(e.toString());
//}
//try
//{
Circle c=new Circle(-8);
c.getArea();
//}
//catch (NoValueException e)
//{
// System.out.println(e.toString());
//}
System.out.println("over");
}
}