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

黑马程序员_面向对象三大特性之——多态以及异常概述

2013-11-20 23:55 453 查看
---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a
href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------

一、多态的定义

多态可以理解为事物存在的多种体现形态。

比如一个学生,你可以说他是一个人,还可以说他是一个男人或女人,还可以说他是学哪个专业的学生等等多种说法。

二、多态的体现

1、父类的引用指向了自己的子类对象。

以Student类继承Person类举例说明:Person p1=new Student();

2、父类的引用也可以接收自己的子类对象。

也就是说当一个方法的参数类型或者返回值类型是父类类型的话,子类对象都可以作为方法的参数或返回值传入或返回。

比如Person类中有方法:goHome(Person p){}

Student类调用Person类的goHome()方法:Person s1=new Student(); s1.goHome(s1);

三、多态的前提

必须是类与类之间有关系,要么继承,要么实现。

通常还有一个前提:存在方法的覆盖。

四、多态的好处

多态的出现大大提高了程序的扩展性。

因为只要是有继承或实现关系,那么父类引用可以指向任何一个子类对象。

五、多态的弊端

虽然提高了程序的扩展性,但是只能使用父类的引用访问父类中的成员。也就是说不可以访问子类中特有的成员。

如果一定要访问子类中的特有成员,可以向下转型后访问。

六、在多态中成员的特点

1、在多态中成员变量的特点

无论编译和运行,都参考左边(引用型变量所属的类)。

2、在多态中非静态成员函数的特点

在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有,编译失败。

在运行时期:参阅对象所属的类中是否有调用的方法。如果没有,那么会调用引用型变量所属的类中相应的方法。

简单一句话:成员函数在多态调用时,编译看左边,运行看右边。

3、在多态中静态成员函数的特点

无论编译和运行,都参考左边。

七、异常

1、什么是异常?

异常就是程序在运行时出现不正常的情况。

异常从字面上理解就是不正常,我们在现实生活中也会接触到很多不正常的事情,比如身体不舒服,感冒、拉肚子等等情况。这些是现实生活中不正常的事物,在java程序中也会遇到很多异常。比如让java编译一个类,但是类名写错了,就会报错;再比如让java程序运行除法运算,可是除数不小心写成了0,这也是一种异常。java把它们通过类的形式进行描述,并封装成对象。其实就是java对程序中不正常情况进行描述后的对象体现。

2、异常的体系

在java中把异常划分为两种:一种是严重的问题,一种是非严重的问题。

严重的问题在java中把它们归为Error类或者其子类,通常出现重大的问题,比如:运行的类不存在或者内存溢出等。这类问题我们解决不了,不编写针对代码进行处理。

非严重的问题在java中把它们归为Exception类或者其子类,这类问题是我们可以进行处理的异常。我们学习异常主要是处理Exception类及其子类,处理方法为:try-catch-finally。

这两种异常拥有一个父类:Throwable,java用它描述程序中的所有问题。Throwable类直接继承自Object类。

3、Throwable类中的方法

1)getMessage():获取异常信息,返回字符串。

2)toString():获取异常类名和异常信息,返回字符串。

3)printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置。返回值为void。

其实java虚拟机默认的异常处理机制,就是在调用此方法,打印异常的堆栈跟踪信息。

4)printStackTrace(PrintStream s):通常用该方法将异常内容保存在日志文件中,以便查阅。

4、throws和throw

1)作用:

throws用于标识函数暴露出的异常。
throw用于抛出异常对象。
2)throws与throw的区别:
thorws用在函数上,后面跟异常类名。可以跟多个异常类,用逗号隔开。这样声明的异常是要让调用者进行处理的,调用者不处理,那么也只能继续throws,否则编译失败(RuntimeException除外)。
throw用在函数内,后面跟异常对象。只能跟一个异常对象。

5、处理异常

java提供了特有的语句进行异常的处理。

try
{
     需要被检测的代码;
}
catch(异常类  变量)
{
     异常处理代码;
}
finally
{
     一定会执行的代码; (通常用于关闭资源)
}
catch代码块不一定只有一个,如果程序执行中会遇到多种异常,那么有几种异常就对应几个catch代码块。不要定义多余的代码块。如果多个catch代码块中的异常出现继承关系,父类异常catch代码块放在最下面,否则编译失败。
finally代码块只有一种情况不会被执行:就是在之前执行了System.exit(0),代表程序退出。程序都退出了,后面的代码当然不会被执行到了。

try-catch-finally这三个代码块不是每一个都要写上,但必须有try代码块,catch和finally代码块两者根据需要选择其中一个。try代码块不可以单独存在。

6、Exception异常的分类

Exception异常分为两种:

1)编译时被检测异常。

该异常在编译时,如果没有处理(没有try,也没有throws),会编译失败。

2)运行时异常(编译时不检测,比如RuntimeException及其子类)。

该异常在编译时,不需要处理,编译器不检查。需要对代码进行修正。

7、自定义异常

自定义异常的由来

因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对于这些特有的问题可以按照java对问题封装的思想将特有的问题进行自定义的异常封装,这就是自定义异常。

自定义异常类继承Exception或者其子类,并通过构造函数定义异常信息。
例:
Class DemoException extends Exception
{
     DemoException(String message)
    {
         super(message);
     }
}
通过throw将自定义异常抛出。
继承Exception类的原因:
1)异常体系有一个特点,因为异常类和异常对象都被抛出。它们都具备可抛性。这个可抛性是Throwable这个体系中的独有特点。也就是说只有这个体系中的类和对象才可以被throws和throw操作。
2)让该自定义异常类具备操作异常的共性方法。

8、RuntimeException异常

RuntimeException以及其子类如果在函数中被throw抛出,可以不用在函数上声明,编译一样通过。
如果在函数上声明(throws)了该异常,调用者可以不用进行处理,编译一样通过。
之所以不用在函数上声明,是因为不需要让调用者进行处理。当该异常发生时,希望让程序停止。因为在运行时,出现了无法继续运算的情况,或者运算后的结果没有了意义的情况,那么就让程序停止,强制调用者对代码进行修正。
比如下面的代码,定义了一个NoValueException异常类,继承RuntimeException类。程序的功能是求取长方形和圆形的面积,由调用者向其方法中传递参数。如果传递的参数不符合规则,那么运算的结果肯定没有意义。这时就可以抛出我们定义的异常类对象,让程序停止,强制调用者对代码进行修正。
 
/*
有一个圆形和长方形。
都可以获取面积。对于面积如果出现非法的数值,视为是获取面积出现问题。
问题通过异常来表示。
现对这个程序进行基本设计。
*/

//自定义异常类
//由于圆形和长方形求面积如果出现异常,将有可能导致程序的后续代码出现问题
//所以将此异常继承RuntimeException,一发生异常,就终止程序运行
class NoValueException extends RuntimeException
{
NoValueException(String msg){
super(msg);
}
}

//由于求面积并不是长方形和圆形的基本功能,是一个扩展功能,
//所以定义一个接口,如果是基本功能,那就定义一个抽象类。
interface MianJi
{
void getMianJi();
}

//长方形
class Chang implements MianJi
{
private double length,width;
Chang(double length,double width)//throws NoValueException  不能声明,让程序停止
{
if(length<=0 || width<=0)
throw new NoValueException("长方形的长或者宽的值非法!");
this.length=length;
this.width=width;
}

public void getMianJi(){
System.out.println(length*width);
}
}

//圆形
class Yuan
{
private double r;
public static final double PI=3.14;

Yuan(double r)//throws NoValueException
{
if(r<=0)
throw new NoValueException("圆形的半径的值非法!");
this.r=r;
}

public void getMianJi(){
System.out.println(r*r*PI);
}
}

class ExceptionDemo2
{
public static void main(String[] args)
{
Chang c=new Chang(4,6);
c.getMianJi();

Yuan y=new Yuan(-7);
y.getMianJi();

System.out.println("Hello World!");
}
}


9、异常的好处
1)将问题进行封装。
2)将正常流程代码和问题处理代码相分离,方便于阅读。
10、异常的处理原则
1)对异常的处理方式有两种:try-catch-finally或者throws。
2)调用到抛出异常的功能时,抛出几个,就处理几个。
3)多个catch代码块,父类的catch代码块放到最下面。
4)catch代码块内,需要定义针对性的处理方式。不要简单的定义printStackTrace等输出语句,更不要不写处理代码。
如果该异常处理不了,但并不属于该功能出现的的异常,那么可以将异常转换后,再抛出和该功能相关的异常。
11、异常的注意事项
一个方法被覆盖时:
1)覆盖它的方法必须抛出相同的异常或异常的子类。
2)如果父类抛出多个异常,那么重写(覆盖)方法必须抛出那些异常的一个子集,不能抛出新的异常。
3)如果父类或者接口中的方法没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须要进行try-catch-finally处理,绝对不能抛。 

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a
href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------

详细请查看:<a href="http://edu.csdn.net" target="blank">http://edu.csdn.net</a>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: