最近学习jvm相关的知识,然后想到了多态,有点没想通,这里就写程序实验了一下,这中间自己写的备注太多,有点乱。这个时候梳理一下,对自己对别人也是一个良好的启发吧。
先建两个类,一个父类一个子类
父类:
public class Parent01 { public void speak() { System.out.println("parenet speak"); } public void doSomething() { System.out.println("parent like doSomething"); } public static void doStatic() { System.out.println("dosomething static"); } }
子类: public class Child01 extends Parent01 { @Override public void speak() { System.out.println("Child speak"); } public void say() { System.out.println("Childrens like say"); } @Override public void doSomething() { System.out.println("child dosomething"); } public static void doStatic() { System.out.println("child dosomething static"); } }
1、/**向上转型后,父类引用指向子类对象,子类复写了父类的方法,此时用父类的引用调用复写的方法,此时执行的是子类复写的方法**/
这个应还是蛮好理解的,在类加载的过程中,方法区存放了类的数据结构,堆内存存放了类的实例,此时,用父类的的引用调子类的实例。向上转型父类只能调用自己的方法,调用方法的过程中,遇见了子类复写,此时就用子类的实现。
子类初始化的过程当中,要先对父类进行初始化。所以子类天然能用父类的非private方法。
2、/**父类的引用想要调子类 自己的方法,这个时候需要向下转型,向下转型首先要向上转型,然后再强制转换类型**/
这个其实也很好理解,先是父类的引用指向子类的实例,这个时候我们把父类的引用
问:这样转了型有什么作用,多此一举。为为甚不直接new Child01 一个对象,直接调用他的方法呢?
答:Child01 child01 = new Child01(); child01.say();
向下转型最主要的目标是支持Java 泛型编程。
例如,我要创建一个List的集合,要将child和parent全都装进去,这个时候我我们不能List<Child01>,List<Parent01>来创建对象,因为还有其他人也要装进去。这个时候我们就用他们一个公共的父类List<Object> list = new ArrayList<Object>();然后再list.add(child01),list.add(parent01),在添加子类实例的时候已经默认执行了向上转型,这个时候集合中只有Object默认的方法,而没有子类自己扩展的方法。当我们需要用的时候,将实例取出来,再向下转型即可用了。
问:向下转型,能不能转换成其他类型呢?
答:不能,这个时候编译器会报错的。
问:子类引用能指向父类实例吗?
答:不能,我理解应该是 子类引用中可能有许多自己的方法,父类的实例可能实现不了,这个时候强制转换类型是不行的
问:子类实例能够调用父类静态方法吗?
答:能够调用父类静态方法,但是子类是不能够覆写父类的静态方法。而且idea编译器其实不支持实例调静态方法,实例调静态方法是没有智能提示的。静态方法再类加载的时候,已经存入到jvm的方法区中了,静态方法的调用是属于类的,而不是在实例中。而我们说的继承,多态都是在实例的基础上完成的。