------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-------
一、定义
就是程序运行是出现不正常的现象
二、异常的由来
问题也是现实生活中具体事务,也可以通过java的类的形式进行描述,并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
问题的划分:
严重问题:java通过Error类来描述
非严重的问题:java通过Exception来描述,可以使用针对性的方式来出理
三、异常的体系
不同的问题用不同的类进行具体的描述,比如角标越界,空指针。
问题有很多,也代表异常有很多,,将其共性内容向上抽取,就形成了异常体系
Throwable
|-----Error
|-----Exception
该体系的特点:就在于Throwable及其所有子类都具有可抛性,throw和throws
四、异常的处理
1.java提供了特有的语句进行处理,有三种格式
<1>try {
需要被检测的代码
} catch (异常类 变量) {
处理异常的代码
}
<2>try {
需要被检测的代码
} catch (异常类 变量) {
处理异常的代码
}
finally{
一定执行的语句(像一些关闭资源的语句)
}
<3>try {
需要被检测的代码
}
finally{
一定执行的语句(像一些关闭资源的语句)
}
记住:
1.catch用于处理异常如果没有catch就表示异常没有被处理过,如果该异常时检测时异常,那么久声明
2.finally中规定以的通常是关闭资源的代码,因为资源必须被释
3.finally只有一种情况下不会被执行到,当执行到System.exit(0),
Finally不会执行
例如:
class Demo{
int div(int a,int b){
return a/b;//(2)...执行这个语句jvm就会产生异常并封装成 对象,即 new ArithmeticException(),然后将其抛给(1)
}
}
public class ExceptionDemo {
/**
* @param args
*/
public static void main(String[] args) {
Demo d = new Demo();
try {
int x = d.div(4, 0);//(1)...跳到(2),后就收(1)的new ArithmeticException(),后将其又丢给了(3)
System.out.println("x = "+x);//不执行
} catch (Exception e) {//(3)
System.out.println("除零啦!");//处理代码
}
System.out.println("over");
}
}
2.对捕获的异常进行方法的操作:
System.out.println(e.getMessage); //by zero
System.out.println(e.toString); //异常的名称,异常的信息
e.printStackTrace(); /异常饿名称,信息和出现异常的位置
3.在函数上声明异常便于提高安全性,让调用者进行处理,不处理编译失败
例如:
class Demo1{
int div(int a,int b)throws Exception{//在功能上通过throws关键字声明了该功能可能出现问题
return a/b;
}
}
public class ExceptionDemo2 {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//有问题也不处理,也抛出
Demo d = new Demo();
int x = d.div(4, 0);
System.out.println("x = "+x);
System.out.println("over");
}
}
4.对多异常的处理
1)声明异常时,建议声明更为具体的异常,这样处理更为具体
2)对方声明几个异常,就对应有几个catch块,不要定义多余的catch快, 如果多个catc块中的异常出现继承关系,父类的异常catc块放在最下面
建议在进行catch块处理时,catch中一定要具体定义具体处理方式,不要单一的一句e.printStackTrace(); ,也不要简单就书写一句输出语句。
五、自定义异常
1.继承Exception
1)因为项目中出现特有的问题,而这些问题并未被java所描述并封装对象,所以对于这些特有的问题可以按照java的对象封装的思想,将特有的问题,进行自定义异常处理。
2)自定义异常必须是自定义类型继承Exception
3)举例:
自定义一个除数为负数的异常
class FushuException extends Exception{
private String msg;
private int value;
public FushuException(String msg, int value) {
super();
this.msg = msg;
this.value = value;
}
public int getValue(){
return value;
}
}
class Demo2{
int div(int a,int b) throws FushuException {
if(b<0)
throw new FushuException("除数出现了负数!",b);
else return a/b;
}
}
public class ExceptionDemo3 {
/**
* @param args
*/
public static void main(String[] args) {
Demo2 d = new Demo2();
try {
int x = d.div(4, -1);
System.out.println("x = "+x);
} catch (FushuException e) {
System.out.println(e.toString()+".....出现的负数是...."+e.getValue());
}
System.out.println("over");
}
}
当函数内部出现了throw抛出异常的对象,那么久必须给定相应的处理,要么抛,要么try,本例中是抛出了throws FushuException。一般情况下函数内出现异常,函数上要声明。
4)自定义异常信息:
因为父类中已经把异常信息操作玩成了,所以子类在构造函数时,只需通过super语句即可,会自动的通过getMessage获取到异常的信息。
4)继承Exception的原因
异常体系有个特点,因为异常类和异常对象都被抛出,同名都具备了可抛性,这个可抛性是Throwable这个体系中的特有特点,只有这个体系中的类和对象才可以被throw和throws。
5)throw和throws的区别
throws使用在函数上,小括号和大括号之间,后面跟的是异常内类,可以跟多个但是用“,”隔开。
Throw使用在函数内。后面跟的是异常对象。
2.继承RuntimeException
该异常的特点:
函数内抛出异常,函数上可以不用声明,编译一样通过,如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过。
如果该异常发生,无法继续进行运算,就让自定义异常继承RuntimeException
例如:
class Demo3{
public int diy(int i, int j) {
if(j==0)
throw new ArithmeticException("被零除啦");
return i/j;
}
}
public class RuntimeExceptionDemo {
/**
* @param args
*/
public static void main(String[] args) {
Demo3 d = new Demo3();
int x = d.diy(4,1);
System.out.println("x = "+x);
}
}
备注:ArithmeticException是RuntimeExceptionDemo的子类
之所以不用再函数上声明,是因为不需要让调用者处理(不声明就不知道有问题,就不需要处理,因为函数内部的代码是被封装了的,只能看到函数声明,没有看到一场就不会处理)
但该异常发生,希望程序停止。因为运行时,出现了无法继续运算的情况,希望程序停止后,由程序员对代码进行修改。(只要传的值是错的,程序就会停止)
再看例子:
class Person{
public void checkName(String name) {
if(name.equals("zhangsan"))
System.out.println("Yes");
else
System.out.println("NO");
}
}
public class RuntimeExceptionDemo1 {
/**
* @param args
*/
public static void main(String[] args) {
Person p = new Person();
p.checkName(null);
}
}
次程序会抛出NullPointerException(是RuntimeException子类) 异常就必须让程序停止,因为name的值是null,没有办法计算了。
所以要修改代码:
修改情况1:
if("zhangsan".equals(name))
修改情况2:
name!=null && name.equals("zhangsan")
六、自定义异常例子(重要):
例1:
老师要用电脑
开始思考上课出现的问题,比如
电脑蓝屏
电脑冒烟
可是电脑冒烟时,出现讲课无法继续的情况
就出现了讲师的问题:k科室计划无法完成
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 = 3;
public void run() throws LanPingException,MaoYanException {
if(state == 1)
System.out.println("电脑运行!");
if(state == 2)
throw new LanPingException("电脑蓝屏!");
else if(state == 3)
throw new MaoYanException("电脑冒烟啦!");
}
public void rest(){
System.out.println("电脑重启!");
}
}
class Teacher{
private String name ;
private Computer comp;
Teacher(String name){
this.name = name;
comp = new Computer();
}
public void prelect()throws NoPlanException //因为电脑解决不了必须把问题抛给老师
{
try{
comp.run();
}
catch (LanPingException e){
System.out.println(e.toString()); //打印异常名称和信息
comp.rest();
}
catch (MaoYanException e){
System.out.println(e.toString());
throw new NoPlanException("课时无法完成 ,因为"+e.getMessage());
}
System.out.println(name+"讲课!");
}
}
class ExceptionDemo3{
public static void main(String[] args) {
Teacher d = new Teacher("老师");
try{
d.prelect();
}
catch (NoPlanException e){
System.out.println(e.toString());
}
}
}
七、异常在子父类覆盖中的体现
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 Fu{
void show() throws AException{
}
}
class Zi extends Fu{
void show() throws BException{//或者throws BException
}
}
public class ExceptionDemo {
public static void main(String[] args) {
Test t = new Test();
t.function(new Zi());
}
}
如果子类抛出的是CException的话,就没有处理语句,因为function方法中的处理语句是针对Fu类抛出异常或者Fu类抛出异常的子异常,所以程序会编译会报错。
八、异常处理的原则
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) {
throw new BException;//BException对AException的处理
}
比如汇款的例子,汇钱,将我的钱汇给张三没汇成功,发生了异常,不能告诉用户汇款失败,就不需要处理了,必须首先将钱收回存回子集的账户(对异常的处理),然后告诉用户没有汇成功。
九、异常的注意事项
在子类覆盖时
1.子类抛出的异常必须是父类的异常的子类或者子集
2.如果父类或者接口没有异常抛出时,子类覆盖出现了异常,只能try不能抛
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-------