您的位置:首页 > 职场人生

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

2014-11-01 23:18 260 查看
------- 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:

//定义蓝屏异常,由于该异常可处理,继承Exception
class BlueScreenException extends Exception
{
BlueScreenException(Stringmessage)
{
super(message);
}
}
/*
定义过热异常
该异常虽然不能处理
但由于不会抛至最终调用者
因此不继承RuntimeException
*/
class OverHeatingException extends Exception
{
OverHeatingException(Stringmessage)
{
super(message);
}
}
//定义讲课中断异常,该异常同样可以处理,继承Exception
class 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()
{
//重启后将状态值恢复到1
state = 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)
{
//发生蓝屏异常以后的处理方式就是重启
//对应到代码上,就将状态改为2
System.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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: