毕向东之异常
/*异常:是对问题的处理,将问题进行对象的封装。 异常体系: Throwable |--Error |--Exception |--RuntimeException 只有异常体系中的所有类以及建立的对象才具备可抛性 throws和throw的用法:throw定义在函数内,用于抛出异常对象 throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。 当函数内容有throw抛出异常对象,并未进行try处理,必须要在函数上声明,否则编译失败。 注意:RuntimeException除外,也就是说,函数内如果抛出的是RuntimeException异常,函数上可以不用声明 如果函数声明了异常,调用者需要进行处理,处理方式可以throws 可以try. ------------------------------ 异常有两种: 编译时被检测异常:该异常在编译时,如果没有处理(没有抛也没有try),编译失败。该异常被标识,代表这可以被处理。 运行时异常(编译时不检测):在编译时,不需要处理,编译器不检查。该异常的发生,建议不处理,让程序停止。需要对代码进行修正。 --------------------------------- 异常的处理方式: java提供了特有的语句进行处理: 不可以单独使用 try{ 需要被检测的代码; }catch(异常类 变量){ 处理异常的代码;(处理方式) }finally{ 一定会执行的语句;//通常用来关闭资源 } 在catch中写return的时候,处理完个异常时就执行return跳出这个函数,不会执行该函数下面的语句,但会执行finally里面的语句。但是当把catch 中的return改为 Ststem.exit(0);(jvm结束)时,下面的finally语句就不会执行。 --------------------------- 自定义异常: 定义类继承Exception或RuntimeException 1.为了让该自定义类具备可抛性,2.让该类具备操作异常的共性方法。 当要定义自定义异常的信息时,可以使用父类已经定义好的功能,将异常信息传递给父类的构造函数。 class MyException extends Exception{ MyException(String message){ super(message); } } 自定义异常的好处:1.将问题进行封装。2.将正常流程代码和问题处理代码相分离,方便于阅读。 异常的处理原则: 1.处理方式有两种:try 或者 throws 2.调用到抛出异常的功能时,抛出几个,就处理几个。一个try对应多个catch 3.多个catch,父类的catch放到最下面 4.catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace,输出语句,也不要不写 5.当捕捉到的异常,本功能吹了不了时,可以继续在catch中抛出 3.对捕捉到的异常对象进行常见的方法操作:String getMessage(); */ public class Test1{ public static void main(String[] args){ Demo d=new Demo(); try{ int x=d.div(4,0);//new AritchmeticException(); System.out.println("x="+x);//出现异常就不会执行异常处下面你的程序 异常被捕捉就跳转了 } catch(Exception e){//捕捉异常 = new AritchmeticException(); System.out.println("除零了!"); System.out.println(e.getMessage());// 异常信息(by zero) System.out.println(e.toString());// 异常名称:异常信息 e.printStackTrace();//异常名称,异常信息,异常出现的位置。 //其实jvm默认的异常处理机制就是在调用printStackTrace方法,打印异常的堆栈的跟踪信息 } System.out.println("程序结束"); } } class Demo{ int div(int a,int b){//会把异常交给调用它的对象处理 return a/b; } }
/*对于多异常的处理: 1.声明异常时,建议声明更具体的异常,这样处理的可以更具体. 2.用throws声明几个异常,(如果用catch处理)就对应有几个catch块进行处理,不要定义多余的catch块。 如果多个catch块中的异常出现异常的关系,父类异常catch块放在在下面。(catch块是按照顺序执行的) 对于异常 要么抛 要么try */ public class Test2 { public static void main(String[] args) { Demo2 d=new Demo2(); try{ int x=d.div(4, 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("下标越界了"); } System.out.println("程序结束"); } } class Demo2{ int div(int a,int b) throws ArithmeticException,ArrayIndexOutOfBoundsException{ int[] arr=new int[a]; System.out.println(arr[4]); return a/b; } }
/*因为项目中会出现特有的问题,而这些问题并未被java描述并封装成对象,所以可以将这些特有的问题,进行自定义的异常封装 自定义异常: 1.当在函数中出现了throw抛出异常对象,那么就必须要给对应的处理动作。 2.要么再函数上声明让调用者处理,要么在内部try catch 处理。 一般情况下,在函数内出现异常,函数上需要声明 如何自定义异常信息呢? 因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息通过super(信息)传递给父类 就可以直接通过getMessage()方法获取自定义的异常信息 自定义异常: 必须是自定义类继承Eclipse(原因:异常体系有一个特点:异常类和异常对象都被抛出,他们都具备可抛性, 但是这个可抛性是Throwable这个体系独有的特点,只有这个体系中的类和对象才可以被throws和throw操作) throws和throw的区别: throws用在函数上,throw用在函数内 throws后面跟的是异常类,可以跟多个,用逗号隔开; throw后跟的是异常对象。 */ //在本程序中对除数的负数也认为是无法进行运算的 那么就需要对这个问题进行自定义的描述。 public class Test3 { public static void main(String[] args) { Demo3 d=new Demo3(); try{ int x=d.div(4, -1); System.out.println("x="+x); }catch(FuShuException e){ System.out.println(e.getMessage()); System.out.println("错误的负数是:"+e.getValue()); System.out.println("出现负数了"); } System.out.println("程序结束"); } } class Demo3{ int div(int a,int b)throws FuShuException{ if(b<0) throw new FuShuException("构造方法——自定义的负数异常",b);//手动通过throw关键字抛出一个自定义异常对象 return a/b; } } class FuShuException extends Exception{//只有继承Exception才能抛出异常 private int value; public FuShuException(){ super(); } public FuShuException(String message, int value){ super(message);//将信息传递给父类中的构造函数 //System.out.println(message); //b为自定义的函数的信息 父类没有的 this.value=value; } public int getValue(){ return value; } }
/*对于异常分两种: 1.编译时被检测的异常 2.编译时不能被检测的异常(运行时异常,RuntimeException) 运行时异常 运行时异常:当运行出现这个异常时,程序就不会继续往下执行 */ public class Test4 { public static void main(String[] args){ Demo4 d=new Demo4(); try{ int x=d.div(4,-1); System.out.println("x="+x); }catch(FuShuException4 e){//处理异常 System.out.println(e.getMessage()); }catch(ArithmeticException e){ System.out.println(e.getMessage()); } System.out.println("程序结束"); } } class Demo4{ public int div(int a,int b)/*throws FuShuException4*/{ if(b<0) throw new FuShuException4("负数啦");//创建一个异常 if(b==0) throw new ArithmeticException("除数为零啦"); return a/b; } } class FuShuException4 extends RuntimeException{ public FuShuException4(String message){ super(message); } }
/*try catch finally的三种格式用法: *1.try{} catch(){} 2.try{} catch(){}finally{} 3.try{}finally{} catch用来处理异常 没有解决就需要抛出问题(throws是抛出问题给别人处理,不需要自己处理),throw则是抛出问题(new 一个异常出来创建问题) 而 finally不是处理问题 异常在子父类覆盖中的体现: 1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类(不能抛父类没有的异常)。 2.如果父类方法抛出多个异常,那么子类在覆盖方法时,只能抛出父类异常的子集。 3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。 如果子类方法发生了异常,就必须要进行try处理,绝对不能抛。 当有异常时我们进行处理,异常就回被解决,但程序会继续往下执行,这样当有时候这种异常没有解决的必要时,就可以继承运行时异常 继承RuntimeException时,就不需要catch去处理,因为编译时不会报错 */ public class Test5 { public static void main(String[] args) { Rec r=new Rec(3,-1);//出现异常就跳转带到异常处执行,不会执行r.getArea(); r.getArea(); System.out.println("over"); } } class Rec implements Shape{ private int len,wid; public Rec(int len,int wid){ if(len<=0||wid<=0){ throw new NoValueException("出现非法值"); } this.len=len; this.wid=wid; } public void getArea(){ System.out.println(len*wid); } } class NoValueException extends RuntimeException{ public NoValueException(String message){ super(message); } } interface Shape{ public void getArea(); }