黑马程序员——异常机制5:练习

来源:互联网 发布:优化组织管理模式 编辑:程序博客网 时间:2024/05/18 00:19

------- android培训、java培训、期待与您交流! ----------

1. 练习一

需求:老师用电脑上课。

分析一:通过前面讲到的名词提炼法,提炼出两个名词——老师和电脑。因此,分别需要定义两个类——Teacher和Computer。老师类中定义两个方法——prelect(讲课)和布置练习(test),Computer类中也定义两个方法run(打开电脑)和reset(重新启动)。在为老师对象进行初始化时除了初始化姓名,还要为其初始化电脑对象。

为了便于理解,可以把主函数理解为老师的上级领导,也就是说领导“调用”老师们的讲课方法为学生授课。

代码一:

代码1:

//定义电脑类,包含开机和重启方法class Computer{public void run(){System.out.println("电脑运行");}public void reset(){System.out.println("电脑重启");}}//定义老师类,包含讲课和布置练习方法class Teacher{private String name;private Computer comp;Teacher(String name){this.name = name;comp = newComputer();} public void prelect(){//打开电脑comp.run();System.out.println(name+"讲课");}public void test(){System.out.println("做练习");}}class ExceptionTest{public static void main(String[] args){Teacher t = new Teacher("老师");t.prelect();}}
运行结果为:

电脑运行

老师讲课

 

分析二:

1) 定义问题

在讲课这个动过发生过程中,可能会出现一些问题,比如电脑蓝屏或者电脑过热冒烟。对应到代码上就是异常,按照面向对象的思想,应该对这两个问题进行描述并定义为两个类——BlueScreenException和OverHeatingException。

2) 状态判定

在Computer类中定义一个私有整型成员变量,用于记录电脑所处的状态。该变量的使用方法是:在run方法中进行判断,1代表正常,打印输出“电脑运行”;2代表蓝屏,抛出蓝屏异常;3代表过热,抛出过热异常。

3) 问题转换

当发生蓝屏异常时,老师是可以就地处理的,方式就是重启。那么重启的作用体现到代码上就是将状态值改为1。

当发生过热异常时,对于使用电脑对象的老师来说是无法处理的。此时,就应该继续向上抛出异常——也就是说将问题抛给领导。但是,这样做有两个问题:1) 当发生电脑故障异常时,作为老师最直接的问题是讲课无法继续,而不是电脑损坏;2) 即使将电脑故障异常抛给领导,领导也是无法处理的。因此接收到过热异常以后,应向上抛出讲课中断异常,换句话说,对异常进行了转换,此时领导接受到讲课中断异常后只需帮助老师更换电脑即可解决。为此,需要再定义一个新的异常——讲课中断异常。

另外,按照现实情况,在领导处理讲课中断异常的同时,为了不耽误时间,老师可以为学生布置练习。

4) throw语句后不能再接任何语句

根据前面的内容我们知道throw的作用在向上级调用者抛出异常的同时,还将当前执行程序停止并跳转至catch语句中。因此,一旦真的抛出异常,throw后面的代码是无法执行到的,所以这样的设计是不能通过编译的。这一特点也适用于return。

代码二:

代码2:

//定义蓝屏异常,由于该异常可处理,继承Exceptionclass BlueScreenException extends Exception{BlueScreenException(Stringmessage){super(message);}}/*定义过热异常该异常虽然不能处理但由于不会抛至最终调用者因此不继承RuntimeException*/class OverHeatingException extends Exception{OverHeatingException(Stringmessage){super(message);}}//定义讲课中断异常,该异常同样可以处理,继承Exceptionclass ClassSuspendException extends Exception{ClassSuspendException(Stringmessage){super(message);}}//定义电脑类,包含开机和重启方法class Computer{//定义用于记录状态的私有整型变量,1表示正常,2表示蓝屏,3表示过热private int state = 1;public void run()throws BlueScreenException,OverHeatingException{//如果状态为2,表示蓝屏if(state == 2)throw newBlueScreenException("蓝屏!");//如果状态为3,表示过热else if(state == 3)throw newOverHeatingException("电脑过热!");//否则,表示状态正常System.out.println("电脑运行");}public void reset(){//重启后将状态值恢复到1state = 1;System.out.println("电脑重启");}}//定义老师类,包含讲课方法和布置练习方法class Teacher{private String name;private Computer comp;Teacher(String name){this.name = name;comp = newComputer();} public void prelect()throws ClassSuspendException{/*打开电脑因为问题产生是在电脑运行期间因此需要对调用run方法的代码进行try-catch处理*/try{comp.run();}//catch代码块数量等于声明异常数量catch(BlueScreenException e){//发生蓝屏异常以后的处理方式就是重启//对应到代码上,就将状态改为2System.out.println(e.getMessage());comp.reset();}catch(OverHeatingException e){//过热异常无法处理,向上抛出讲课中断异常//在处理讲课中断异常之前,给学生布置一些练习System.out.println(e.getMessage());test();throw new ClassSuspendException("讲课中断!");}System.out.println(name+"讲课");}//老师在讲课之余可能会给学生布置一些课堂练习public void test(){System.out.println("给学生布置练习。");}}class ExceptionTest2{public static voidmain(String[] args){Teacher t = new Teacher("老师");try{t.prelect();}catch(ClassSuspendException e){//主函数接收到讲课中断异常//通过换电脑对该异常进行处理System.out.println("处理方式:换电脑!");}}}
2. 练习二

需求:

描述圆形类和长方形类,并为两种类都定义求面积方法。

 

分析一:

在这个例子中我们认为,求面积是上述两类的扩展方法,因此需要定义一个接口,其内定义抽象的计算面积方法(也可以定义Shape抽象类,内部定义求面积抽象方法)。圆形类和长方形类分别实现该接口,并定义各自具体的计算面积方法。

 

代码一:

代码3:

interface Area{//定义抽象的计算面经方法,需子类实现并复写该方法public abstract void getArea();}class Rectangle implements Area{//长方形类的两个私有属性——长和宽private float len, wid;Rectangle(float len, float wid){this.len = len;this.wid = wid;}//计算面积,并打印public void getArea(){System.out.println("长方形面积为:"+(len* wid));}}class Circle implements Area{//圆形类的私有属性——半径private float rad;Circle(float rad){this.rad = rad;}//计算圆形面积public void getArea(){System.out.println("圆形面积为:"+(Math.PI* rad * rad));}}class ExceptionTest3{public static void main(String[] args){Rectangle rec = new Rectangle(3f, 4f);rec.getArea(); Circle cir = new Circle(5f);cir.getArea();}}
运行结果为:

长方形面积为:12.0

圆形面积为:78.53981633974483

 

分析二:

然而,在运行上述代码过程中,可能会由于调用者传入错误的数值而无法计算,比如0或者负数,那么这样的问题就需要通过异常机制来解决。

因此,需要自定义异常——IllegalValueException,非法数值异常。在圆形和长方形两个类构造方法中对所传入的参数进行判断,如果大于零就为对象成员变量进行初始化,否则抛出异常。

另外,上述异常的发生是由调用者传入错误的数值造成的问题,就像前面讲过的那样,不应对此类异常进行处理,而是暴露该异常,并修改代码。因此IllegalValueException应该继承RuntimeException。

代码二:

代码4:

//定义非法数值异常class IllegalValueException extends RuntimeException{IllegalValueException(Stringmessage){super(message);}}interface Area{//定义抽象的计算面经方法,需子类实现并复写该方法public abstract void getArea();}class Rectangle implements Area{//长方形类的两个私有属性——长和宽private float len, wid;Rectangle(float len, floatwid){//如果调用者传入的长度和宽度非正,则抛出非法数值异常if(len <= 0 ||wid <= 0)throw new IllegalValueException("长宽不能是非正数!");             this.len = len;this.wid = wid;}//计算面积,并打印public void getArea(){System.out.println("长方形面积为:"+(len* wid));}}class Circle implements Area{//圆形类的私有属性——半径private float rad;Circle(float rad){//如果调用者传入的半径非正,则抛出非法数值异常if(rad <= 0)throw new IllegalValueException("半径不能是非正数!"); this.rad = rad;}//计算圆形面积public void getArea(){System.out.println("圆形面积为:"+(Math.PI* rad * rad));}}class ExceptionTest4{public static voidmain(String[] args){//创建长方形对象,并传入长款,为演示异常,传入负数Rectangle rec = new Rectangle(-3f, 4f);rec.getArea(); //创建圆形对象,传入半径值Circle cir = new Circle(5f);cir.getArea(); System.out.println("over");}}
运行结果为:

Exception in thread "main" IllegalValueException: 长宽不能是非正数!

        at Rectangle.<init>(ExceptionTest4.java:25)

        at ExceptionTest4.main(ExceptionTest4.java:58)


0 0