Java基础(异常)

来源:互联网 发布:linux route add 作用 编辑:程序博客网 时间:2024/06/05 07:43


一、异常定义

异常就是程序中出现的不正常情况

二、异常的由来:

问题也是现实生活中一个具体的事物,也可以通过Java类的形式进行描述,并封装成对象,其实就是Java对不正常情况进行描述后的对象的体现

三、对于问题的划分    严重和非严重

1、严重:对于严重的Java用Error类进行描述    对于Error一般编写针对性的代码进行处理,因为没必要  就如现实生活中的癌症一样 

2、非严重:对于非严重的Java用Exception类进行描述

四、异常体系

Throwable

|—Error

|—Exception

         |—RuntimeException

异常体系的由来:

无论是Error还是Exception都具有一些共性内容,而通过向上抽取,就形成了一个基本的体系,而抽取出来的这个父类就叫做Throwable      查阅父类内容  ,创建子类对象使用功能   最共性的内容都在Throwable类中

异常体系的特点:

异常体系中的所有类以及建立的对象都具备可抛性,也就是说可以被throw和throws关键字所操作,也只有异常体系具有这个特点

五、异常的处理

1、使用try  catch

作用:用于捕捉函数上声明的异常,并进行处理

格式:

try{需要被检测的代码}catch (异常类 异常类变量){处理异常的代码}finally{一定会执行的代码}

2、使用throw和throws

throw和throws的用法

throw定义在函数内部,用于抛出异常

throws定义在函数上,用于声明异常类,可以抛出多个异常类,异常类之间用逗号隔开

1、当函数内部有throw抛出异常,并未进行try处理,则必须在函数上声明异常,否则编译失败,注意:RuntimeException异常除外,也就是说如果函数内抛出的是RuntimeException异常,函数上可以不用声明

2、如果函数上声明了异常,调用者必须进行处理,处理方法可以try可以抛,如果函数抛出的异常是RuntimeException异常,则调用者可以不进行处理

示例:

class Demo{public int getNum(int a, int b)throws Exception//因为函数内部抛出了异常,而且还不是RuntimeException异常,所以应在函数上声明抛出的异常类型{//因为b作为除数可能会为0,所以应加入判断并手动抛出异常if(b==0)throw new Exception();return a/b;}}class Test1{public static void main(String [] args){Demo d = new Demo();/*因为函数上声明了异常,所以当调用声明异常的函数时,调用者要对函数进行处理,要么抛要么try 这里我们使用try来处理*/try {int num = d.getNum(4,1);System.out.println("num="+num);} catch (Exception e) {/*因为可能会出现异常,所以我们要提示错误信息,这时就需要用到Throwable中沿袭下来的方法了 */System.out.println("e.getMessage()="+e.getMessage()); //获取异常信息   返回值类型为String类型System.out.println("e.toString()="+e.toString()); //获取异常类的名称 返回值类型为String类型e.printStackTrace(); //获取异常类的名称、异常类的信息、异常出现的位置 没有具体的返回值void}}}

六、自定义异常

定义:

项目中出现的一些特有的问题,而这些问题并没有被Java所描述,并封装成对象,所以对于这些特有的问题可以按照Java对问题封装的思想,将特有问题进行自定义封装

/*需求:定义一个功能给学生进行初始化,要求学生年龄在0-100之间在这里为什么要使用自定义异常呢?因为Java中并没有对这类问题进行描述,那么年龄要怎么符合规定呢?只能通过自定义一个异常类来实现了1、如何自定义异常类呢?要想成为异常类,就必须成为异常中的一员,所以只需要继承异常类就行了,我们通常都继承Exception类那么问题出现了,大家都知道异常类是可以打印异常信息的,那么自定义异常类后怎么输出异常信息呢?2、添加异常信息通过父类的构造函数添加异常信息*/class AddAgeException extends Exception{//给自定义异常类初始化异常信息AddAgeException(String message){super(message);}}//描述学生class Student{private String name;private int age;//初始化属性Student(String name, int age)throws AddAgeException{//函数内部抛出异常,所以函数上应声明抛出的异常类//因为是对年龄限制,所以加入判断并抛出异常就行if(age<0||age>100)throw new AddAgeException("年龄非法");//这里抛出的是自定义异常this.name = name;this.age = age;}}class Test4{public static void main(String [] args){//由于调用了声明异常类的函数,所以应处理try{new Student("z",5);}catch (AddAgeException e){//打印自定义异常信息,还是通过getMessage方法System.out.println(e.getMessage());}}}
自定义异常为什么一定要继承异常类呢?

因为只有异常异常类才具备可抛性,只有具备可抛性才可以被throw和throws锁

七、异常处理原则

1、处理方式:try或抛

2、调用到抛出异常的功能时,函数上声明几个异常,就处理几个,也就是几个catch语句块,也就拥有了一个try对应多个catch的情况

3、当需要多个catch语句块处理时,父类catch语句块要放在最下面

4、catch语句块内需要定义针对性的处理方式,不要简单的定义e.printStrackTrace,或者仅仅一两条输出语句甚至不写,

5、当捕捉到的异常本功能处理不了时,可以继续在catch语句块中抛出

try{throw new AException();}catch (AException e){throw e;}

6、当捕捉到的异常本功能处理不了,而且不属于本功能出现的异常时,可以将异常转换后抛出和该功能相关异常

try{throw new AException();}catch (AException e){throw new BException();}

7、当捕捉到的异常本功能处理不了,而且不属于本功能出现的异常时,而且需要将与本功能相关的问题告诉给调用者,并需要调用者处理时,可以先在本功能中处理后,转换为调用者可以解决的异常在抛出去

try{throw new AException();}catch (AException e){对异常进行处理后再throw new BException();}

代码演示:

当函数上声明多个异常:

class Demo{public int getNum(int a, int b)throws ArrayIndexOutOfBoundsException,ArithmeticException{int [] arr = new int[a];//这句代码可能会出现数组角标越界异常,如传入的a的值为4,当访问arr[4]时,该角标下的元素是不存在的,所以会参生角标越界异常,所以应在函数上声明角标越界异常ArrayIndexOutOfBoundsExceptionSystem.out.println(arr[a]);//因为b作为除数可能会为0,所以应加入判断并手动抛出算术异常ArithmeticExceptionif(b==0)throw new ArithmeticException();return a/b;}}class Test2{public static void main(String [] args){Demo d = new Demo();/*因为函数上声明了异常,所以当调用声明异常的函数时,调用者要对函数进行处理,要么抛要么try 这里我们使用try来处理 由于是函数上声明了多个异常,所以应使用多个catch进行处理*/try {int num = d.getNum(4,1);System.out.println("num="+num);} catch (ArithmeticException e) {//用于处理除数为0出现的异常ArithmeticExceptionSystem.out.println(e.toString());System.out.println("被0除了");}catch(ArrayIndexOutOfBoundsException e)//用于处理角标越界出现的异常ArrayIndexOutOfBoundsException{System.out.println(e.toString());System.out.println("数组角标越界了");}catch(Exception e)//当有多个catch语句块时,父类catch应放在catch语句块的最后一个  一般是函数上声明几个异常,调用者就处理几个异常就行了 这种情况不多见{System.out.println(e.toString());System.out.println("其他异常");}}}


当捕捉到的异常本功能处理不了时,继续在catch语句块中抛出

/*需求:用代码描述  老师用电脑讲课使用名词提炼法:1、发现需要连个对象 老师和电脑2、老师拥有讲课的功能,但是需要使用到电脑这个工具,所以需要电脑对象3、电脑拥有运行的功能,为了更好的体现分析:老师讲课过程中会不会出现什么问题呢?比如电脑坏了,这个有可能吧?就拿cpu短路来说说异常的体现吧*///自定义电脑CPU短路异常class cpuException extends Exception{cpuException(String message){super(message);}}//电脑class Computer{//用该变量,CPU短路的状态 短路状态下state的值为2private int state = 0;//电脑运行方法public void run()throws cpuException{if(state == 2)throw new cpuException("cpu已坏,电脑无法运行");System.out.println("电脑运行,老师开始讲课");}}//老师class Teacher{private String name;//老师一存在就拥有name这个属性Teacher(String name){this.name = name;}//老师讲课方法public void doTeachering(Computer c)throws cpuException{/*这里调用了声明异常的方法,但是cup坏了电脑不能运行,这时候老师在使用电脑时,老师可以出来这个问题么?老师只具备讲课的功能,不具备修电脑的功能,所以老师也修不了,那就不管,继续往上抛呗*/c.run();}}class Test3{public static void main(String [] args){//由于老师没有把问题解决,所以谁调用老师的讲课方法谁就要处理这个问题try{new Teacher("毕姥爷").doTeachering(new Computer());}catch (cpuException e){System.out.println(e.getMessage());}}}

当捕捉到的异常本功能处理不了,而且不属于本功能出现的异常时,将异常转换后抛出和该功能相关异常

/*需求:用代码描述  老师用电脑讲课使用名词提炼法:1、发现需要连个对象 老师和电脑2、老师拥有讲课的功能,但是需要使用到电脑这个工具,所以需要电脑对象3、电脑拥有运行的功能,为了更好的体现分析:老师讲课过程中会不会出现什么问题呢?比如电脑坏了,这个有可能吧?就拿cpu短路来说说异常的体现吧*///自定义电脑CPU短路异常class cpuException extends Exception{cpuException(String message){super(message);}}//抛出新异常class NoPlanException{NoPlanException(String message){super(message);}}//电脑class Computer{//用该变量,CPU短路的状态 短路状态下state的值为2private int state = 0;//电脑运行方法public void run()throws cpuException{if(state == 2)throw new cpuException("cpu已坏,电脑无法运行");System.out.println("电脑运行,老师开始讲课");}}//老师class Teacher{private String name;//老师一存在就拥有name这个属性Teacher(String name){this.name = name;}//老师讲课方法public void doTeachering(Computer c)throws NoPlanException{/*这里调用了声明异常的方法,但是cup坏了电脑不能运行,这时候老师在使用电脑时,老师可以出来这个问题么?老师只具备讲课的功能,不具备修电脑的功能,所以老师也修不了,虽然可以继续往上面抛,但是会出现一个问题,你抛给了调用者调用者可以解决么?所以这时你应该抛出可以让调用者解决的问题*/try{c.run();}catch (cpuException e){throw new NoPlanException("课时无法继续,原因:"+e.getMessage()+";请校长指示");}}}class Test3{public static void main(String [] args){try{new Teacher("毕姥爷").doTeachering(new Computer());}catch (NoPlanException e){System.out.println(e.getMessage());}}}

当捕捉到的异常本功能处理不了,而且不属于本功能出现的异常时,而且需要将与本功能相关的问题告诉给调用者,并需要调用者处理时,先在本功能中处理后,转换为调用者可以解决的异常在抛出去

/*需求:用代码描述  老师用电脑讲课使用名词提炼法:1、发现需要连个对象 老师和电脑2、老师拥有讲课的功能,但是需要使用到电脑这个工具,所以需要电脑对象3、电脑拥有运行的功能,为了更好的体现分析:老师讲课过程中会不会出现什么问题呢?比如电脑坏了,这个有可能吧?就拿cpu短路来说说异常的体现吧*///自定义电脑CPU短路异常class cpuException extends Exception{cpuException(String message){super(message);}}//抛出新异常class NoPlanException{NoPlanException(String message){super(message);}}//电脑class Computer{//用该变量,CPU短路的状态 短路状态下state的值为2private int state = 0;//电脑运行方法public void run()throws cpuException{if(state == 2)throw new cpuException("cpu已坏,电脑无法运行");System.out.println("电脑运行,老师开始讲课");}}//老师class Teacher{private String name;//老师一存在就拥有name这个属性Teacher(String name){this.name = name;}//定义老师给学生安排自习的方法public void DoZiXiing(){System.out.println("电脑坏了,学生先上自习");}//老师讲课方法public void doTeachering(Computer c)throws NoPlanException{/*这里调用了声明异常的方法,但是cup坏了电脑不能运行,这时候老师在使用电脑时,老师可以出来这个问题么?老师只具备讲课的功能,不具备修电脑的功能,所以老师也修不了,虽然可以继续往上面抛,但是会出现一个问题,你抛给了调用者调用者可以解决么?所以这时你应该抛出可以让调用者解决的问题*//*出现了老师解决不了的问题时,老师可以先按照自己的想法解决问题,然后在向领导报道*/try{c.run();}catch (cpuException e){doTeachering();throw new NoPlanException(e.getMessage()+";请校长指示");}}}class Test3{public static void main(String [] args){try{new Teacher("毕姥爷").doTeachering(new Computer());}catch (NoPlanException e){System.out.println(e.getMessage());}}}

八、RuntimeException异常

Exception中有一个特殊的子类异常RuntimeException异常(运行时异常)

1、如果函数内部抛出了该异常或该异常的子类,在函数上不需要声明,编译一样可以通过

2、如果在函数上声明了该异常或该异常的子类,那么调用者可以不用处理,编译一样通过

原因:之所以不用在函数上声明,是因为不需要让调用者处理,当异常发生,希望程序停止,因为在运行时出现了无法继续运行的情况,希望停止程序后,对代码进行修正

九、异常分类:

一种是编译时检测异常(该异常在编译时没有处理,没有抛也没有try,编译失败,该异常被标示,代表可以被处理)

一种是运行时异常(编译时不检测)(该异常不用标识,异常出现,程序停止)

十、异常在子父类中的体现

1、子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法只能抛出父类异常或者该异常的子类或者不抛出(也就是说不能抛出父类中没有的异常)

/*如如下异常:class AException extends Exception              //A异常继承Exception{}class BException extends AException//B异常继承了A异常{}class CException extends Exception //C异常继承Exception{}*/class Fu{//父类的方法抛出异常Apublic  void show()throws AExection{}}class Zi{//那么子类只能抛出异常A或异常B或不抛出,绝不能抛出异常Cpublic void show(){}}

2、如果父类抛出多个异常,那么之类只能抛出父类异常的子集

/*    如如下异常:class AException extends Exception        //A异常继承Exception{}class BException extends AException        //B异常继承了A异常{}class CException extends Exception         //C异常继承Exception{}*/class Fu{//父类抛出多个异常,异常A、异常B、异常Cpublic void show()throws AException,CException,BException{}}class Zi{//那么子类只能抛出父类抛出中的异常,不能抛出父类抛出的异常中没有的异常,而且可以抛出多个public void show()throws AException,CException{}}

3、如果父类或者接口的方法中没有抛出异常,那么子类在覆盖是也不可以抛出异常,如果子类方法发生了异常,那么之类必须自己使用try catch处理异常

<pre name="code" class="java">/*    如如下异常:class AException extends Exception        //A异常继承Exception{}class BException extends AException        //B异常继承了A异常{}class CException extends Exception         //C异常继承Exception{}*/
class Fu{//父类不抛出异常public void show(){}}class Zi{//那么子类也不能抛出异常 如果发生了异常,那么之类必须自己使用try catch处理异常public void show(){try{}catch (异常类 异常类变量){}}}

十一、try   catch处理的几种格式

1、try{需要被检测的代码}catch (){处理异常的代码}2、try{需要被检测的代码}catch (){处理异常的代码}finally{一定执行的代码}3、try{需要被检测的代码}finally{一定执行的代码}

小练习题:

注:按Java规范书写程序代码,如果你认为程序有错误,请指出,并说明程序错误原因。1.写出程序结果class Demo{public static void func()//throws Exception{try{throw  new Exception();}finally{System.out.println("B");}}public static void main(String[] args){try{func();System.out.println("A");}catch(Exception e){System.out.println("C");}System.out.println("D");}}编译失败:如果func放上声明了该异常。结果是?B C D====================================================================2.写出程序结果class Test{Test(){System.out.println("Test");}}class Demo extends Test{Demo(){//super();System.out.println("Demo");}public static void main(String[] args){new Demo();new Test();}}TestDemoTest考的子类的实例化过程。====================================================================3.写出程序结果interface A{}  class B implements A{public String func(){return "func";}}class Demo{public static void main(String[] args){A a=new B();System.out.println(a.func());}}编译失败:因为A接口中并未定义func方法。====================================================================4.写出程序结果class Fu{boolean show(char a){System.out.println(a);return true;}}class Demo extends Fu{public static void main(String[] args){int i=0;Fu f=new Demo();Demo d=new Demo();for(f.show('A'); f.show('B')&&(i<2);f.show('C')){i++;d.show('D');}}boolean show(char a){System.out.println(a);return false;}}A B====================================================================5.写出程序结果interface A{}class B implements A{public String test(){return "yes";}}class Demo{static A get(){return new B();}public static void main(String[] args){A a=get();System.out.println(a.test());}}编译失败,因为A接口中没有定义test方法。====================================================================6.写出程序结果:   class Super{int i=0;public Super(String a){System.out.println("A");i=1;}public Super(){System.out.println("B");i+=2;}}class Demo extends Super{public Demo(String a){//super();System.out.println("C");i=5;}public static void main(String[] args){int i=4;Super d=new Demo("A");System.out.println(d.i);}}B C 5====================================================================7.interface Inter{void show(int a,int b);void func();}class Demo{public static void main(String[] args){//补足代码;调用两个函数,要求用匿名内部类Inter in = new Inter(){public void show(int a,int b){}public void func(){}};in.show(4,5);in.func();}}====================================================================8.写出程序结果class TD{int y=6;class Inner{static int y=3;  void show(){System.out.println(y);}}}class TC{public static void main(String[] args){TD.Inner ti=new TD().new Inner();ti.show();}}编译失败,非静态内部类中不可以定义静态成员。内部类中如果定义了静态成员,该内部类必须被静态修饰。====================================================================9.选择题,写出错误答案错误的原因,用单行注释的方式。class Demo{ int show(int a,int b){return 0;}}下面那些函数可以存在于Demo的子类中。A.public int show(int a,int b){return 0;}//可以,覆盖。B.private int show(int a,int b){return 0;}//不可以,权限不够。C.private int show(int a,long b){return 0;}//可以,和父类不是一个函数。没有覆盖,相当于重载。D.public short show(int a,int b){return 0;}//不可以,因为该函数不可以和给定函数出现在同一类中,或者子父类中。E.static int show(int a,int b){return 0;}//不可以,静态只能覆盖静态。====================================================================10.写出this关键字的含义,final有哪些特点?this:代表本类对象,哪个对象调用this所在函数,this就代表哪个对象。final:1,修饰类,变量(成员变量,静态变量,局部变量),函数。2,修饰的类不可以被继承。3,修饰的函数不可以被覆盖。4,修饰的变量是一个常量,只能赋值一次。====================================================================11.写出程序结果:  class Fu{int num=4;void show(){System.out.println("showFu");}}class Zi extends Fu{int num=5;void show(){System.out.println("showZi");}}class T{public static void main(String[] args){Fu f=new Zi();Zi z=new Zi();System.out.println(f.num); System.out.println(z.num); f.show(); z.show(); }}45showZishowZi====================================================================12.interface A{void show();}interface B{void add(int a,int b);}class C implements A,B{//程序代码private int a,b;//private int sum;public void add(int a,int b){this.a =a;this.b = b;//sum = a+b;}public void show(){System.out.println(a+b);//System.out.println(sum);}}class D{public static void main(String[] args){C c=new C();c.add(4,2);c.show();//通过该函数打印以上两个数的和。}}====================================================================13.写出程序结果class Demo{public static void main(String[] args){try{showExce(); System.out.println("A");}catch(Exception e){System.out.println("B");}finally{System.out.println("C");}System.out.println("D");}public static void showExce()throws Exception{throw new Exception();}}// B C D====================================================================14.写出程序结果class Super{int i=0;public Super(String s){i=1;}}class Demo extends Super{public Demo(String s){i=2;}public static void main(String[] args){Demo d=new Demo("yes");System.out.println(d.i);}}//编译失败,因为父类中缺少空参数的构造函数。//或者子类应该通过super语句指定要调用的父类中的构造函数。====================================================================15.写出程序结果class Super{public int get(){return 4;}}class Demo15 extends Super{public long get(){return 5;}public static void main(String[] args){Super s=new Demo15();System.out.println(s.get());}}编译失败,因为子类父类中的get方法没有覆盖。但是子类调用时候不能明确返回的值是什么类型。所以这样的函数不可以存在子父类中。====================================================================16.写出程序结果:class Demo{public static void func(){try{throw  new Exception();System.out.println("A");}catch(Exception e){System.out.println("B");}}public static void main(String[] args){try{func();}catch(Exception e){System.out.println("C");}System.out.println("D");}}//编译失败。 因为打印“A”的输出语句执行不到。记住:throw单独存在,下面不要定义语句,因为执行不到。====================================================================17.class Demo{public void func(){//位置1;new  Inner();}class Inner{}public static void main(String[] args){Demo d=new Demo();// 位置2 new Inner();//不可以,因为主函数是静态的。如果访问inner需要被static修饰。}}A.在位置1写 new Inner();//okB.在位置2写 new Inner();C.在位置2写 new d.Inner();//错误,格式错误。new new Demo().Inner();D.在位置2写 new Demo.Inner();//错误,因为inner不是静态的。====================================================================18.写出程序结果class Exc0 extends Exception{}class Exc1 extends Exc0{}class Demo{public static void main(String[] args){try{throw new Exc1();}catch(Exception e){System.out.println("Exception");}catch(Exc0 e){System.out.println("Exc0");}}}//编译失败。多个catch时,父类的catch要放在下面。====================================================================19.interface Test{void func();}class Demo{public static void main(String[] args){//补足代码;(匿名内部类)new Demo().show(new Test(){public void func(){}});}void show(Test t){t.func();}}====================================================================20.写出程序结果class Test{ public static String output=""; public static void foo(int i){ try{ if(i==1)throw new Exception(); output+="1"; } catch(Exception e){ output+="2"; return; } finally{ output+="3"; } output+="4"; }public static void main(String args[]){ foo(0);System.out.println(output);//134foo(1); System.out.println(output); //13423}} ====================================================================21.建立一个图形接口,声明一个面积函数。圆形和矩形都实现这个接口,并得出两个图形的面积。注:体现面向对象的特征,对数值进行判断。用异常处理。不合法的数值要出现“这个数值是非法的”提示,不再进行运算。====================================================================22.补足compare函数内的代码,不许添加其他函数。class Circle{private static double pi=3.14;private double radius;public Circle(double r){radius=r;}public static double compare(Circle[] cir){//程序代码//其实就是在求数组中的最大值。int max = 0;//double max = cir[0].radius;for(int x=1; x<cir.length; x++){if(cir[x].radius>cir[max].radius)max = x;}return cir[max].radius;}}class TC{public static void main(String[] args){Circle cir[]=new Circle[3];//创建了一个类类型数组。cir[0]=new Circle(1.0);cir[1]=new Circle(2.0);cir[2]=new Circle(4.0);System.out.println("最大的半径值是:"+Circle.compare(cir));}}====================================================================23.写出程序结果public class Demo{     private static int j = 0; private static boolean methodB(int k){j += k; return true; }public static void methodA(int  i){         boolean b;   b = i < 10 | methodB (4); b = i < 10 || methodB (8); }public static void main (String args[] ){methodA (0); System.out.println(j); //4} }====================================================================24.假如我们在开发一个系统时需要对员工进行建模,员工包含 3 个属性:姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。 ====================================================================25.在一个类中编写一个方法,这个方法搜索一个字符数组中是否存在某个字符,如果存在,则返回这个字符在字符数组中第一次出现的位置(序号从0开始计算),否则,返回-1。要搜索的字符数组和字符都以参数形式传递传递给该方法,如果传入的数组为null,应抛出IllegalArgumentException异常。在类的main方法中以各种可能出现的情况测试验证该方法编写得是否正确,例如,字符不存在,字符存在,传入的数组为null等。getIndex(null,'a');public int getIndex(char[] arr,char key){if(arr==null)throw new IllegalArgumentException("数组为null");for(int x=0; x<arr.length; x++){if(arr[x]==key)return x;}return -1;}====================================================================26.补足compare函数内的代码,不许添加其他函数。class Circle{private double radius;public Circle(double r){radius=r;}public Circle compare(Circle cir){//程序代码/*if(this.radius>cir.radius)return this;return cir;*/return (this.radius>cir.radius)?this: cir;}}class TC{public static void main(String[] args){Circle cir1=new Circle(1.0);Circle cir2=new Circle(2.0);Circle cir;cir=cir1.compare(cir2);if(cir1==cir)System.out.println("圆1的半径比较大");elseSystem.out.println("圆2的半径比较大");}}



0 0
原创粉丝点击