黑马程序员----面向对象---异常

阅读更多
[size=small]

------- http://www.itheima.comjava培训、android培训期待与您交流!-------


继续学习面向对象,,,,,

八、异常

1、概述
异常就是程序在运行时出现的不正常情况。
在现实生活中,我们也会遇到很多不正常情况。其中有的是可以解决的,有的则没有解决必要。比如,电脑的运行速度慢,我们可以清理清理电脑灰尘或对电脑进行垃圾清理。但是,要是,某天不小心将电脑摔地上了,如果幸运,可以修修,如果不幸运,那么,对不起,就不用修了。
而在java语言中,也有对问题的描述。因为问题也可以归结为一类事物,那么,就可以通过java类的形式对问题进行描述,并封装成对象,也就是说,异常时java对不正常情况进行描述后的对象体现。
问题分为两种:严重的问题:Error  一般不编写针对性的代码对其进行处理
                     非严重的问题:Exception  可以针对性处理
而对于这些问题,Error或Exception,都有一些共性内容,如,不正常情况的信息,引发原因等。所以,将这些共性内容向上抽取就形成了一个体系:
可抛的:Throwable:Error/Exception

2、异常的处理
(1)使用 try - catch - finally  语句进行异常处理
        try {  需要被检测的代码  }catch( 异常类 变量 ){ 处理异常的代码(处理方式) }finally{ 一定 会被执行的语句 }

下面用一个例子解释:
首先定义一个简单的算数运算,求两个数的商(不考虑小数)。我们知道,在进行除法运算时,除数不能为0。所以,我们要遵循这个规则。如果出现了除数为0 ,则报异常,否则程序继续运行。
//定义一个类,用于封装除法运算
class Div
{
        //定义一个方法,用于计算两个数的商
int div(int x,int y)
{
return x/y;
}
}
class  ExceptionDemo
{
public static void main(String[] args)
{
Div d=new Div();
try
{
int x=d.div(4,0);
System.out.println("x="+x);
}
catch (Exception e)//Exception e=new ArithmeticException();
                                           //父类引用指向子类对象   多态的运用
{
System.out.println("除零了,不符合规则");
System.out.println(e.getMessage());//获取异常的信息
e.printStackTrace();//打印异常的堆栈的跟踪信息
}
System.out.println("over");
}
}

分析一下处理异常的流程:
Div d=new Div();在内存中创建对象
int x=d.div(4,0);调用div方法,这时,将4 0传给x、 y,由于除数为0,不符合规则,虚拟机检测到异常(java语言自定义的异常),那么就会出现ArithmeticException,出现了异常,下面的程序就不会执行,将异常转加给catch语句,让他对算法异常进行处理。Exception e=new ArithmeticException();     父类引用指向子类对象   多态的运用
然后,将处理的结果打印出来,这时,异常处理结束。接下来运行异常处理语句外的程序:
System.out.println("over");
                                    
(2)将异常声明(在函数体上声明异常),也就是抛出异常(throws)
还是上面那个例子。我们知道,x和y的值是用户输入的值,那么,传入的值就不明确。如果传入的是符合规则的,程序就不会有什么问题,但如果传入的是不合规则的,程序就会停掉。这是我们不希望的。
所以,我们在方法上将可能出现的问题通过关键字throws标识一下,这时编译时会出现错误信息:必须将异常捕获或声明。
一种方式是:在主函数上将异常抛出(这时是将异常抛给了JVM)
      int div(int x,int y)   throws Exception
一种方式是:在调用方法处捕获异常。
      try - catch
声明异常便于极高安全性,让调用者进行处理,不处理则会失败

(3)多异常处理
    显然,上面的例子只出现了一个异常。但在实际的开发过程中会出现很多异常。所以,要对多个异常进行处理。
A、也就是在函数上声明多个可能出现的异常(一般不同异常类用逗号","隔开),这     样会更具体地处理异常。
如,throws ArithmeticException ,ArrayIndexOutOfBoundException
    那么在处理异常时或捕获或声明异常。
B、在函数上声明几个,那么就要有几个catch块,且声明的和处理的要一致。
   要注意:若多个catch中出现继承关系,父类的异常catch要放在最下面(若放在最上面,出现的异常 父类会处理完,一下的catch块就不会执行,且报错)。
C、若捕获异常,则每个catch语句中要传入具体的异常类(函数上声明什么异常,
     catch中就要处理什么异常),且处理的方法要具体,
     不能输出默认的e.printStackTrace信息,也不能简单地打印自定义的异常信息。
D、当然,在实际开发中不会将出现的异常信息打印出来,这时会用文件记录每个异常发生的时间,情况等信息,存放在异常日志中。

(4)自定义异常
虽然java语言自定义了很多异常类,但是,在实际开发中我们还是会遇到很多意想不到的异常。这时,就需要我们定义属于我们自己的异常处理方式。
还是上面那个例子:java异常体系中只对除数为0的情况定义了异常。但如果除数为负数,这个运算方法也会出错。为了解决这个问题,就要自定义一个异常类,用于封装新出现的异常问题。
class FuShuException  extends Exception
{
   //函数一初始化就会有信息
   FuShuException(String message){
      //因为父类中已经定义了显示异常信息的方法,所以我们可以直接用
      super(message);
     }
}
class Div
{
	int div(int x,int y) throws FuShuException
	{
		if (y<=0)
            //手动通说关键字throw抛出自定义异常对象
			throw  new FuShuException("除数为负数");
		return x/y;
	}
}

在抛出自定义异常对象后,我们可以有两种解决方式:
A、在函数内部使用try - catch处理
B、在函数上声明
这里我们直接在函数上声明了
测试一下:
public static void main(String[] args) throws FuShuException
	{
		Div d=new Div();
		int x=d.div(4,0);
		System.out.println("x="+x);
}


3、RuntimeException
  RuntimeException是java语言异常体系中比较特殊的一个异常类。为什么说他特殊呢?我们通过上面的例子解释一下:
class Div
{
	int div(int x,int y) 	{
		if (y==0)
           			throw  new ArithmeticException("除数为0");
		return x/y;
	}
}

测试一下:
public static void main(String[] args) 	{
		Div d=new Div();
		int x=d.div(4,0);
		System.out.println("x="+x);
}

这里我们只是在函数内部将ArithmeticException这个异常对象抛出去,并没有在函数上声明,也没有在函数内部通过try - catch进行处理,但是在编译时(javac)并没有出现出错提示。这是为什么呢?
这里就涉及到ArithmeticException这个异常类的特点,
也就是RuntimeException的特殊之处:
A、若在函数内抛出该异常(这里所说的异常是RuntimeException异常及RuntimeException  的子类异常:空指针异常、算法异常、角标越界异常等),函数上可不用声明,编译能通过
B、若在函数上声明了该异常,调用者可不用进行处理,编译一样通过。
分析一下原因:
我们定义的这个算数方法是提供给用户使用的。用户并不知道他们输入的数值(这里只限数值)是怎样的。所以,输入合法的数值程序就会正常运行,若输入的数值不合法,那么JVM就会检测出输入的数值不合法,就会使用自定义的异常方式处理。但不需要将检测后的处理过程暴露给用户,只要将程序停止,那么用户就会意识到输入的数值不合法(不对),从而就会重新输入。

那么对于自定义异常,若该异常发生无法再继续进行运算,就让自定义异常继承RuntimeException。

异常分两种:
编译时检测异常(能处理的可标识出去)
运行时异常(编译时不被检测异常RuntimeException及其子类)

4、finally代码块
   finally代码块中定义的是一定要执行的语句,同常用于关闭资源。
处理语句的其他搭配:
try{}catch(){}
try{}catch(){}finally{}
try{}finally{}

5、覆盖时的异常特点
   我们知道,一般解决异常要么在函数上声明,要么在函数(方法)内抛出异常对象,要么在函数内使用try - catch进行处理。而函数(方法)具有覆盖的特点,那么,当子类覆盖父类的方法时,父类又有异常处理,子类在覆盖时应该注意那么问题呢?
(1)子类在覆盖父类方法时,如果父类中方法抛出异常,则子类在覆盖时抛出的异常必须是 父类方法抛出的异常或父类抛出异常的子类或者不抛。
(2)当父类方法中抛出多个异常时,子类覆盖父类方法时抛出的异常要能被父类处理(只能抛 出父类方法中异常的子集)
(3)如果父类或接口的方法中未抛出异常,则子类在覆盖方法时也不可抛出异常。
若此时子类发生了异常则必须进行try处理,且绝对不能抛(没有接的)

6、异常练习
异常可以将正常流程与出现的问题分离。
定义一个方法,用于计算圆(Circle)和长方形(Rectangular)的面积。由于计算的都是图形的面积,但是圆和长方形的面积公式不同,及实现的具体内容不同,可以定义一个接口,在接口中定义一个没有主体的方法,让子类具体实现(当然,也可以将计算面积的功能视为基本功能,定义抽象类和抽象方法,让子类复写父类的方法,并定义自己的具体计算方式)。
由于我们编写的程序是供用户使用的,他们不知道输入的内容具体是什么,如输入的数值是小于0的数,这时有可能出现问题。所以,要定义异常处理方式来避免问题的发生。
//定义异常
class NoValueException extends RuntimeException{
	NoValueException(String message){
		super(message);
	}	}
interface Shape
{
  //因为计算图形的面积公式不同,且要传递的参数也不同,
  //计算要使用到图形自身的长、宽或半径
	void getArea();//double getArea();无参 
}
class Rec implements Shape{
	//定义长方形的属性
	private int len,wid;
	//构造函数 初始化
	Rec(int len,int wid) //throws NoValueException 
						//继承RuntimeException 不用声明
	{
		if (len<=0 || wid<=0)
			throw new  NoValueException("非法值");
				//程序结束
		{
			this.len = len;
			this.wid = wid;
		}	
	}
	//覆盖getArea()方法
	public void getArea()
	{
		System.out.println("S(rec)="+len*wid);
	}
}

class Circle
{
	private int  radius;
  //全局常量,
	public static final double  PI=3.14;
	Circle(int radius)
	{
		if (radius<=0)
			throw new RuntimeException("非法值");//NoValueException 提示不同
		this.radius = radius;
	}
	public void  getArea()
	{
	System.out.println("S(circle)="+radius*radius*PI);
	}
}
class  ExceptionTest2
{
	public static void main(String[] args) 
	{
		
			Rec r = new Rec(3,8);//当长方形的长或宽出现负数时,若不做任何处理,程序继续运行,并打印结果,不合逻辑。
								 //故添加异常处理
			r.getArea();

			Circle c = new Circle(-2);
			c.getArea();
		//若此处处理,则程序继续运行到 over ,
		/*
		try
		{
			Rec r = new Rec(-3,8);
			r.getArea();
		}
		catch (NoValueException e)
		{
			System.out.println("over");
		}
		
	*/
	}   }







------- http://www.itheima.comjava培训、android培训期待与您交流!-------
[/size]

你可能感兴趣的:(黑马程序员----面向对象---异常)