3.Java值传递与引用传递( 六 )


诚然,要理解多态我们就必须要明白什么是“向上转型” 。在继承中我们简单介绍了向上转型,这里就在啰嗦下:在上面的喝酒例子中,酒(Win)是父类,剑南春(JNC)、五粮液(WLY)、酒鬼酒(JGJ)是子类 。我们定义如下代码:
JNC a = new JNC();
对于这个代码我们非常容易理解无非就是实例化了一个剑南春的对象嘛!但是这样呢?
Wine a = new JNC();
在这里我们这样理解,这里定义了一个Wine 类型的a,它指向JNC对象实例 。由于JNC是继承与Wine,所以JNC可以自动向上转型为Wine,所以a是可以指向JNC实例对象的 。这样做存在一个非常大的好处,在继承中我们知道子类是父类的扩展,它可以提供比父类更加强大的功能,如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能 。
但是向上转型存在一些缺憾,那就是它必定会导致一些方法和属性的丢失,而导致我们不能够获取它们 。所以父类类型的引用可以调用父类中定义的所有属性和方法,对于只存在于子类中的方法和属性它就望尘莫及了 。
代码如下,根据上面的java重写,在test方法里又调用了另一个方法test2,然后test方法不符合java重写的思想,因为父类没有形参列表,而子类有;test2符合java重写,即子类重写父类的方法 。
public class Person {public void test(){System.out.println("父类的test");test2();}public void test2(){System.out.println("父类的test2");}}--------------------------------------------------------public class Student extends Person {public void test(String a){System.out.println("子类的test");test2();}/*** 子类重写父类方法* 指向子类的父类引用调用test2时,必定是调用该方法*/public void test2(){System.out.println("子类的test2");}}---------------------------------------------------------public class Application {public static void main(String[] args) {Person a = new Student();//父类的引用指向子类a.test();}}/*父类的test子类的test2*/
从程序的运行结果中我们发现,.test()首先是运行父类中的test().然后再运行子类中的test2() 。
分析:在这个程序中子类重载了父类的方法test(),重写test2(),而且重载后的test( a)与 test2()不是同一个方法,由于父类中没有该方法,向上转型后会丢失该方法,所以执行子类的父类类型引用是不能引用test( a)方法 。而子类重写了test2() ,那么指向子类的父类引用会调用子类中test2()方法 。所以对于多态我们可以总结如下:
指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法 。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用) 。
对于面向对象而已,多态分为编译时多态和运行时多态 。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态 。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性 。
9.和类型转换
在绝大多数情况下并不是推荐的做法,应当好好利用多态;
是Java中的二元运算符,左边是对象,右边是类;左边的对象不能是基础数据类型,否则会报错;
严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为: =
其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果 都返回 true,否则返回false 。