关于继承,有好些要注意的地方。
一般资料介绍:当子类继承父类时,子类会获得父类中定义的成员变量和方法,当访问权允许的情况下,子类可以直接访问父类中定义的成员变量和方法。
可是,Java继承中对成员变量和方法的处理是不同的。
package com;
public class FieldAndMethodTest {
public static void main(String[] args) {
Father father=new Father();
System.out.println(father.count);
father.display();
Son son=new Son();
System.out.println(son.count);
son.display();
Father fs=new Son();//父类引用指向子类
System.out.println(fs.count);//输出的还是father的count
fs.display();//输出的是Son的count
Father fs2=son;//让 fs2 跟 son 指向同一个对象
System.out.println(fs2==son); //true
System.out.println(fs2.count);//输出的是Father的count
System.out.println(son.count);//输出的是Son的count
//两个 指向相同对象的引用,输出结果不一样,必定内存储存有两块内存分别储存父类跟子类的值
}
}
足以证明: 1、调用方法,总是根据应用指向的实际类型决定!
访问成员,总是根据声明时的类型决定!
2、
//两个 指向相同对象的引用,输出结果不一样,必定内存储存有两块内存分别储存父类跟子类的值
就是说分配声明为 子类的对象中有内存用于储存了父类的实例变量
百度技术解答:
1.从对象的内存角度来理解.
假设现在有一个父类Father,它里面的变量需要占用1M内存.有一个它的子类Son,里面的变量需要占用0.5M内存.
现在通过代码来看看内存的分配情况:
2.f = new Father();//系统将分配1M内存.
Son s = new Son();//系统将分配1.5M内存!因为子类中有一个隐藏的引用super会指向父类实例,所以在实例化子类之前会先实例化一个父类,也就是说会先执行父类的构造函数.由于s中包含了父类的实例,所以s可以调用父类的方法.
3.Son s1 = s;//s1指向那1.5M的内存.
Father f1 = (Father)s;//这时f1会指向那1.5M内存中的1M内存,即是说,f1只是指向了s中实例的父类实例对象,所以f1只能调用父类的方法(存储在1M内存中),而不能调用子类的方法(存储在0.5M内存中).
Son s2 = (Son)f;//这句代码运行时会报ClassCastException.因为f中只有1M内存,而子类的引用都必须要有1.5M的内存,所以无法转换.
Son s3 = (Son)f1;//这句可以通过运行,这时s3指向那1.5M的内存.由于f1是由s转换过来的,所以它是有1.5M的内存的,只是它指向的只有1M内存.