异常:在运行时,发生不正常的情况
在java中用类的形式对不正常情况进行了描述和封装对象
描述不正常情况的类,就称为异常类
以前正常流程代码和问题处理代码相结合
现在将正常流程代码和问题处理代码分离,提高阅读性
其实异常就是java通过面向对象的思想将问题封装成了对象,用异常类对其进行描述
不同的问题用不同的类进行具体描述
异常的体系:
问题很多,意味着描述的类也很多,将其向上抽取,形成了异常体系
最终问题(不正常情况)就分成了两大类:一般不可处理的 和 可处理的两大类;
在java中,对于不可处理的,一般用Error类来表示,对于 可处理的 , 一般用Exception来示。
Throwable(可抛):无论是error,还是exception,都是问题,问题发生就应该抛出,让调用者知
道并处理(该体系的特点就在于Throwable及其所有的子类都具有可抛性;对于不具有可抛性的问
题是不能进行抛出的)
可抛性到底是什么?其实是通过两个关键字来体现的; throws 和 throw这两个关键字,凡是被这
两个关键字所操作的类和对象都具备可抛性。
一般不可处理的。Error
特点:是由jvm抛出的严重性问题。这种问题一般不针对进行处理,直接修改程序。
该体系的特点:子类的后缀名都是用其父类名作为后缀,阅读性很强。
1. 一般不可处理的。Error
2. 可处理的。Exception
下面的程序为throw关键字示例
class Demo
{
public int method(int[] arr, int index)
{
if (arr == null)
{
throw new NullPointerException("这是一个空指针异常,哥们儿、你太疯狂啦!");
}
if (index >= arr.length)
{
throw new ArrayIndexOutOfBoundsException("数组的角标越界啦,哥们儿、你是不是疯啦?");
}
if (index < 0)
{
throw new ArrayIndexOutOfBoundsException("数组的角标不能为负数,哥们儿、你真的是疯啦!");
}
return arr[index];
}
}
class ExceptionDemo
{
public static void main(String[] args)
{
int [] arr = new int[]{1,2,3};
Demo d = new Demo();
int num = d.method(arr,2);
System.out.println("这是正确的输出" + num);
int num1 = d.method(arr,3);
System.out.println("这是异常的情况");
System.out.println("这里是主程序结束的标志");
}
}
对于角标是整数不存在,可以用角标越界表示
对于负数为角标的情况,准备用负数角标异常来表示
负数角标这种异常在java中并没有定义过,那就按照java异常的创建思想,面向对象,将负数角标进行自定义描述,并封装成对象。这种自定义的问题描述称为自定义异常。
注意:如果让一个类称为一个异常类,则必须继承异常体系,因为只有继承异常体系的子类才有资格具备可抛性,才可以被两个关键字所操作(throw 和 throws)
class ArrayFuShuIndexException extends Exception
{
ArrayFuShuIndexException(){}
ArrayFuShuIndexException(String msg)
{
super(msg);
}
}
class Demo1
{
public int method(int[] arr, int index) throws ArrayFuShuIndexException
{
if (arr == null)
{
throw new NullPointerException("这是一个空指针异常,哥们儿、你太疯狂啦!");
}
if (index >= arr.length)
{
throw new ArrayIndexOutOfBoundsException("数组的角标越界啦,哥们儿、你是不是疯啦?");
}
if (index < 0)
{
throw new ArrayFuShuIndexException("数组的角标不能为负数,哥们儿、你真的是疯啦!");
}
return arr[index];
}
}
class ExceptionDemo1
{
public static void main(String[] args) throws ArrayFuShuIndexException
{
int [] arr = new int[]{1,2,3};
Demo1 d = new Demo1();
int num = d.method(arr,2);
System.out.println("这是正确的输出" + num);
int num1 = d.method(arr,-1);
System.out.println("这是异常的情况");
System.out.println("这里是主程序结束的标志");
}
}
异常(Exception)的分类:
1. 编译时被检测的异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系;编译时异常问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式,这样的问题都可以针对性处理
2. 编译时不检测的异常(运行时异常):就是Exception中的RuntimeException和其子类;这种问题的发生,无法让功能继续,运算无法进行,更多的时候是调度者导致的。或者引发了内部状态的改变导致的。那么、这种问题一般不进行处理,直接编译通过,在运行时,让调用时的程序强制停止。让调用者对代码进行修正。
自定义异常时,要么继承Exception,要么继承RuntimeException。
Throws 和 throw区别:
1. Throws 使用在函数上;Throw使用在函数内
2. Throws抛出的是异常类,可以抛出多个,用逗号隔开;throw抛出的是异常对象
异常处理的捕捉形式:
这是可以对异常进行针对性的处理方式
异常处理格式:
Try
{放需要被检测异常的代码}
Catch(异常类 变量) //该变量用于接收发生的异常对象
{真正处理异常的代码}
Finally
{一定会被执行的代码}
class ArrayFuShuIndexException extends Exception
{
ArrayFuShuIndexException(){}
ArrayFuShuIndexException(String msg)
{
super(msg);
}
}
class Demo1
{
public int method(int[] arr, int index) throws ArrayFuShuIndexException
{
if (arr == null)
{
throw new NullPointerException("这是一个空指针异常,哥们儿、你太疯狂啦!");
}
if (index >= arr.length)
{
throw new ArrayIndexOutOfBoundsException("数组的角标越界啦,哥们儿、你是不是疯啦?");
}
if (index < 0)
{
throw new ArrayFuShuIndexException("数组的角标不能为负数,哥们儿、你真的是疯啦!");
}
return arr[index];
}
}
class ExceptionDemo1
{
public static void main(String[] args)
{
int [] arr = new int[]{1,2,3};
Demo1 d = new Demo1();
int num ;
try
{
num = d.method(arr,-1);
}
catch (ArrayFuShuIndexException e)
{
System.out.println(e.getMessage());
System.out.println("数组角标不能为负数");
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("数组越界");
}/*
catch (NullPointerException e)
{
System.out.println("传入的数组为空指针");
}*/
catch (Exception e)
{
e.printStackTrace();
}
finally
{
System.out.println("程序退出");
System.exit(1);
}
}
}
注意:jvm的异常处理机制默认就是调用printStackStrace方法
但实际上,如果有生成日志的需求,均是使用第三方工具,例如log4j,log4j即log for java!
注意:在多catch的情况下,父类的catch一定要放在子类的catch之下(代码上下位置)
异常处理原则;
1. 函数内容如果抛出需要检测的异常,那么函数上必须声明,否则必须在函数内用try catch捕捉,
否则编译失败
2. 如果调用到了声明异常的函数,那么try catch要么throws,否则编译失败
3. 什么时候catch,什么时候throws?
功能内容可以解决,用catch,解决不了,用throws告诉调用者,由调用者解决
4. 一个功能如果抛出多个异常,那么调用时,必须有多个catch进行针对性的处理;内部有几个
需要检测的异常,就抛几个异常,抛出几个,就catch几个!
异常--finally代码块:通常用于关闭程序中打开的资源
有一种情况,finally代码块不会执行,就是在finally之前执行语句中,包含System.exit()语句。否则、无论是否发生异常,finally都一定会执行。
Try catch finally代码块组合特点:
1. Try catch finally
2. Try catch(多个),当没有必要资源需要释放的时候,使用这种方式
3. Try finally,可用于当出现异常的时候,确保资源立即释放掉,对于出现的异常,可能本类无法处理,交给其他的类来进行处理。
Void show() throws Exception
{
Try
{
Throw new Exception();
}
Finally
{}
}
下面是个例子
class Demo2
{
public int method(int[] arr, int index)
{
if (index >= arr.length)
{
throw new ArrayIndexOutOfBoundsException("数组的角标越界啦,哥们儿、你是不是疯啦?");
}
return arr[index];
}
}
class ExceptionDemo2
{
public static void main(String[] args)
{
int [] arr = new int[]{1,2,3};
Demo2 d = new Demo2();
int num ;
try
{
num = d.method(arr,10);
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("数组越界");
}
finally
{
System.out.println("程序退出");
System.exit(1);
}
}
}
Finally作用很大,例如 实际开发中连接数据库的代码,一旦查询的时候,发生异常,此时就可以在finally中关闭数据库的连接,如果不关闭,很容易耗尽数据库的连接资源。
异常应用:
/*
老师用电脑上课
问题领域中涉及两个对象
老师、电脑
分析其中的问题。
比如电脑蓝屏、冒烟啦
*/
class LanPingException extends Exception
{
LanPingException(String msg)
{
super(msg);
}
}
class MaoYanException extends Exception
{
MaoYanException(String msg)
{
super(msg);
}
}
class NoPlanException extends Exception
{
NoPlanException(String msg)
{
super(msg);
}
}
class Computer
{
private int state = 2;
public void run() throws LanPingException,MaoYanException
{
if (state == 1)
{
throw new LanPingException("电脑蓝屏啦");
}
if (state == 2)
{
throw new MaoYanException("电脑冒烟啦");
}
System.out.println("老师上课的电脑");
}
public void reset()
{
state = 0;
System.out.println("电脑已经进行重启");
}
}
class Teacher
{
private String name;
private Computer comp;
Teacher(String name)
{
this.name = name;
comp = new Computer();
}
Teacher(){}
public void prelect() throws NoPlanException
{
try{
comp.run();
System.out.println("讲课");
}catch (LanPingException e)
{
System.out.println(e.toString());
comp.reset();
prelect();
}catch (MaoYanException e)
{
System.out.println(e.toString());
test();
throw new NoPlanException("对电脑进行维修,课时任务无法完成");
}
}
public void test()
{
System.out.println("大家开始练习");
}
}
class ExceptionTest
{
public static void main(String[] args)
{
Teacher t = new Teacher("zhangsan");
try
{
t.prelect();
}
catch (NoPlanException e)
{
System.out.println("换人...............");
}
}
}
=====================================================
class NoAddException extends Exception{}
void addData(Data d) throws NoAddException
{
连接数据库
try
{
添加数据,出现异常 SQLException
}
catch (SQLException e)
{
throw new NoAddException();
}
finally
{
关闭数据库
}
}
*/
异常注意事项:
1. 子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类。
2. 如果父类抛出多个异常,那么子类只能抛出父类异常的子集
简单而言、实就是子类覆盖父类只能抛出父类的异常或者子集
注意:如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛。就只能try。
Object:所有类的父类
Object是不断的抽取,具备着所有对象都具备的共性内容