理解“向上转型”和“向下转型”的简单例子

import static net.mindview.util.Print.*;

class Useful{
    public void f(){print("Useful:f()");}
    public void g(){print("Useful:g()");}
}

class MoreUseful extends Useful{
    public void f(){print("MoreUseful:f()");}
    public void g(){print("MoreUseful:g()");}
    public void u(){print("MoreUseful:u()");}
    public void v(){print("MoreUseful:v()");}
    public void w(){print("MoreUseful:w()");}
}

public class RTTI{
    public static void main(String[] args){
        Useful[] x = {
                new Useful(),
                new MoreUseful(),
        };
        try {
            x[0].f();
            x[1].g();
//        找不到方法u()
//            x[1].u();
//        downcast/RTTI
            ((MoreUseful)x[1]).u();
//        Exception in thread "main" java.lang.ClassCastException: Useful cannot be cast to MoreUseful
            ((MoreUseful)x[0]).u();
        }
        catch (ClassCastException e )
        {
            print(e);
        }
    }
}/*Output: 
 Useful:f()
 MoreUseful:g()
 MoreUseful:u()
 java.lang.ClassCastException: Useful cannot be cast to MoreUseful
 */

代码参考Bruce Eckel《Think in Java》Fourth Edition

上面的例子可以很好解释java面向对象编程中的“向上转型”与“向下转型”的特点,首先应该明白,这种“转型”发生在具有继承关系的基类和导出类之间,这也是区别何时选择继承,何时选择组合产生新类的方法之一。向上转型是指由导出类转型为基类,在继承图中由下向上转型;向下转型是指由基类转型为导出类,在继承图中由上向下转型;需要格外注意的是,向上转型和向下转型并不总是让人随心所欲,向上转型会丢失具体的类型信息,向下转型也会出现类型转化异常,主要是因为基类不会具有大于导出类的接口。
理解“向上转型”和“向下转型”的简单例子_第1张图片
Useful类型数组中出现了向上转型(隐式),MoreUseful类型转换为它的父类Useful,当我试图调用数组中对象的方法u()时,编译器告诉我找不到u(),u()是MoreUseful类的扩展方法,Useful类不包含此方法的信息,可见,MoreUseful类型转换成Useful类型后把扩展的方法信息“丢失”了,通过向下转型后可以获取方法u()的信息,Useful类创建的对象本身不包含方法u(),程序运行时会对其进行检查,检查时发现它不能够得到我们所希望的类型,就会抛出异常。

你可能感兴趣的:(Java)