摘抄自:https://blog.csdn.net/han_yankun2009/article/details/40451981
Animal 父类,可以是接口或者类
Cat 子类,继承或实现Animal的子类。
从内存角度看,假设Aninal父类,它里面的变量需要占用1M,它的子类Cat,需要占用0.5M内存。
Animal animal=new Animal(); //系统将分配内存1M
Cat cat=new Cat(); //系统将分配1.5M内存!因为子类有一个隐藏引用super会指向父类实例。所以实例化子类前会先实例化一个父类。先执行父类构造函数。由于包含了父类的实例,所以cat可以调用父类的方法。
Animal animal1= (Animal) cat;//这时候animal1会指向1.5M内存中1M内存,animal1只是指向cat中实例的父类实例对象。所以animal1只能调用父类的方法,不能调用子类的方法(存储在0.5M内存中).
Cat cat1=(Cat)animal //运行时会报ClassCatException。因为animal中只有1M内存,而子类的引用都必须要有1.5M内存,所以无法转换。
Cat cat2=(Cat) animal1;//这句可以通过运行,这时cat2指向那1.5M的内存.由于animal1是由cat转换过来的,所以它是有1.5M的内存的,只是它指向的只有1M内存
Animal a = new Cat(); 这代表什么意思呢?它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。这就是“向上转型”。
子类Child继承了父类Father,并重载了父类的func1()方法,重写了父类的func2()方法。重载后的func1(inti)和func1()不再是同一个方法,由于父类中没有func1(int i),那么,父类类型的引用child就不能调用func1(inti)方法。而子类重写了func2()方法,那么父类类型的引用child在调用该方法时将会调用子类中重写的func2()。
child.func1();//打印结果将会是什么?
child.func1(68);//由于在父类中没有定义这个方法,所以它不能被父类类型的引用调用, 所以在child.func1(68)会跑出异常的