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

------- 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)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值