一、异常解释
异常:就是程序在运行时出现不正常情况。
异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分:两种:一种是严重的问题,一种非严重的问题。
- 对于严重的,java通过Error类进行描述。对于Error一般不编写针对性的代码对其进行处理。
- 对与非严重的,java通过Exception类进行描述。对于Exception可以使用针对性的处理方式进行处理。
Throwable
|--Error
|--Exception
二、异常的处理
java 提供了特有的语句进行处理。
try
{
需要被检测的代码;
}
catch(异常类 变量)
{
处理异常的代码;(处理方式)
}
finally
{
一定会执行的语句;
}
在函数上声明异常。便于提高安全性,让调用出进行处理,不处理编译失败。
对多异常的处理。
1,声明异常时,建议声明更为具体的异常。这样处理的可以更具体。
2,对方声明几个异常,就对应有几个catch块。不要定义多余的catch块。如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。
建立在进行catch处理时,catch中一定要定义具体处理方式。不要简单定义一句 e.printStackTrace(),也不要简单的就书写一条输出语句。
class Demo
{
int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException//在功能上通过throws的关键字声明了该功能有可能会出现问题。
{
int[] arr = new int[a];
System.out.println(arr[4]);
return a/b;
}
}
class ExceptionDemo2
{
public static void main(String[] args)// throws Exception
{
Demo d = new Demo();
try
{
int x = d.div(3,0);
System.out.println("x="+x);
}
catch (ArithmeticException e)
{
System.out.println(e.toString());
System.out.println("被零除了!!");
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println(e.toString());
System.out.println("角标越界啦!!");
}
catch(Exception e)
{
System.out.println("hahah:"+e.toString());
}
/*
int x = d.div(7,0);
System.out.println("x="+x);
*/
System.out.println("over");
}
}
三、自定义异常
必须是自定义类继承Exception。继承Exception原因:
异常体系有一个特点:因为异常类和异常对象都被抛出。他们都具备可抛性,这个可抛性是Throwable这个体系中独有特点。只有这个体系中的类和对象才可以被throws和throw操作。
throws和throw的区别:
- throws使用在函数上;throw使用在函数内。
- throws后面跟的异常类,可以跟多个,用逗号隔开;throw后跟的是异常对象。
public class ExceptionDemo02
{
/**
* 自定义异常
*/
public static void main(String[] args)
{
Demo d=new Demo();
try
{
int result=d.div(10, -5);
System.out.println(result);
} catch (FushuException e)
{
System.out.println(e.getMessage());
e.printStackTrace();
System.out.println("负数:"+e.getValue());
}
System.out.println("over");
}
}
//自定义异常继承自Exception
class FushuException extends Exception
{
private int value;
public FushuException(String message,int value)
{
super(message);//调用父类构造函数
this.value=value;
}
public int getValue()
{
return this.value;
}
}
class Demo
{
public int div(int a,int b) throws FushuException
{
if(b<0)
throw new FushuException("除数小于0",b);//手动通过throw关键字抛出一个自定义异常对象。
else
return a/b;
}
}
四、RuntimeException
- Exceptoin中有一个特殊的子类异常RuntimeException 运行时异常。
- 如果在函数内容抛出该异常,函数上可以不用声明,编译一样通过。
- 如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过;
- 之所以不用在函数声明,是因为不需要让调用者处理。当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修正。
自定义异常时:如果该异常的发生,无法在继续进行运算,就让自定义异常继承RuntimeException。
对于异常分两种:
1,编译时被检测的异常。
2,编译时不被检测的异常(运行时异常。RuntimeException以及其子类)
class FuShuException extends RuntimeException
{
FuShuException(String msg)
{
super(msg);
}
}
class Demo
{
int div(int a,int b) //throws FuShuException,ArithmeticException
{
if(b<0)
throw new FuShuException("出现了除数为负数了");//throw RuntimeException实例函数上可以不throws
if(b==0)
throw new ArithmeticException("被零除啦");
return a/b;
}
}
class ExceptionDemo4
{
public static void main(String[] args)
{
Demo d = new Demo();
int x = d.div(4,-9);//产生异常时候希望程序停止,修改代码
System.out.println("x="+x);
System.out.println("over");
}
}
五、异常覆盖问题
异常在子父类覆盖中的体现;1,子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类(要么不抛)。
2,如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
3,如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
4,如果子类方法发生了自己特有的异常。就必须要在子类内部进行try处理,绝对不能抛。
一句话来说:父类不抛,子类绝不能抛,父类抛了,子类只能抛的异常必须是父类抛的异常的子集或者子异常,要么子类就不抛。
class AException extends Exception
{
}
class BException extends AException
{
}
class CException extends Exception
{
}
/*
Exception
|--AException
|--BException
|--CException
*/
class Fu
{
void show()throws AException
{
}
}
class Test
{
void function(Fu f)
{
try
{
f.show();
}
catch (AException e)
{
}
}
}
class Zi extends Fu
{
void show()throws AException//父类抛的是AException
{ //子类的的情况只能如下:1不抛,2抛AException或者抛AException的子类BException
//3.子类特有的异常绝对不能抛,在函数的内部try{} catch(){}
}
}
class ExceptionTest
{
public static void main(String[] args)
{
Test t = new Test();
t.function(new Zi());
}
}
七、异常练习
1、
public class ExceptionTest1
{
/**
* 老师用电脑上课
* 可能出现问题:电脑蓝屏 , 电脑冒烟
* 引发问题:老师无法继续上课,教学计划无法按时完成
*/
public static void main(String[] args)
{
Teacher t=new Teacher();
try
{
t.prelect();
} catch (NoplanException e)
{
System.out.println(e.getMessage());
System.out.println("换老师或者放假!");
}
}
}
class LanpingException extends Exception//蓝屏异常类
{
LanpingException(String message)
{
super(message);
}
}
class MaoyanException extends Exception//电脑冒烟类
{
public MaoyanException(String message)
{
super(message);
}
}
class NoplanException extends Exception//教学任务异常类
{
NoplanException(String message)
{
super(message);
}
}
class Computer //电脑类
{
private int state=3;
public void run()throws LanpingException,MaoyanException
{
if(state==2)
throw new LanpingException("蓝屏了!");
if(state==3)
throw new MaoyanException("冒烟了!!");
System.out.println("电脑运行!");
}
public void reset()
{
state=1;
System.out.println("电脑重启!");
}
}
class Teacher//教师类
{
private Computer comp;
String name;
public Teacher()
{
this.name=name;
comp=new Computer();
}
public void prelect()throws NoplanException//讲课
{
try
{
comp.run();
} catch (LanpingException e)
{
System.out.println(e.getMessage());
comp.reset();
} catch (MaoyanException e)
{
System.out.println(e.getMessage());
test();
throw new NoplanException("电脑冒烟了!教学无法继续!");
}
}
public void test()//自习
{
System.out.println("学生自习!");
}
}
public class Test
{
/*
有一个圆形和长方形。
都可以获取面积。对于面积如果出现非法的数值,视为是获取面积出现问题。
问题通过异常来表示。
现有对这个程序进行基本设计。
*/
public static void main(String[] args)
{
Rec r=new Rec(3,4);
r.getArea();
try
{
Circle c=new Circle(0);
c.getArea();
} catch (NoValueException e)
{
System.out.println(e.getMessage());
}
System.out.println("over");
}
}
class NoValueException extends RuntimeException
{
public NoValueException(String message)
{
super(message);
}
}
interface Shape
{
void getArea();
}
class Rec implements Shape
{
private int a;
private int b;
public Rec(int a,int b)
{
if(a<=0||b<=0)
throw new NoValueException("非法值!");
this.a=a;
this.b=b;
}
public void getArea()
{
System.out.println(a*b);
}
}
class Circle implements Shape
{
private int radius;
public static final double PI=3.14;
public Circle(int radius)
{
if(radius<=0)
throw new NoValueException("非法值!");
this.radius=radius;
}
public void getArea()
{
System.out.println(PI*radius*radius);
}
}