其实Java继承中,成员变量(包括静态变量,实例变量,常量)没有覆盖(override)一说,应该叫隐藏(hidden)。override只针对方法来说的。
当成员变量为private时,其他类不能直接访问到,只能通过非private方法 访问,因此直接按照分析方法的思路分析,如该方法是否有覆盖,该方法是否是静态方法。
当成员变量为static时,即静态变量,在类加载过程中就分配了内存,因此只与访问的变量类型有关。
class Super {
static String v = "Super";
}
class Sub extends Super {
static String v = "Sub";
public static void main(String[] args) {
Sub sub = new Sub();
System.out.println(sub.v); // 变量sub属于Sub类型,因此输出Sub
Super sooper = new Super();
System.out.println(sooper.v); // 变量sooper属于Super类型,因此输出Super
Super sb = new Sub();
System.out.println(sb.v); // 这里虽然new了一个Sub对象,但使用Super类型的变量sb指向它,(可以认为把Sub对象强转为了Super类型),因此输出的应该是Super
}
当成员变量为非private时(缺省,protected,public),只与访问的变量类型有关。
把上例中成员变量v的static变为public:
class Super {
public String v = "Super";
}
class Sub extends Super {
public String v = "Sub";
public static void main(String[] args) {
Super sb = new Sub();
System.out.println(sb.v); // 这里也是输出Super
}
这里如果要追问一步:为什么成员变量为public时,也只与访问的变量类型有关?
用“子类的同名变量只是隐藏(hidden)了父类的同名变量”来回答觉得只是从形式上回答了。
Super sb = new Sub() 这里有个隐式强制转换,显式写就是: Super sb = (Super)new Sub();
因此问题转到强制转换:
System.out.println(((Super)new Sub()).v);
1. 强制转换怎么个转法,能把明明属于子类对象的实例变量v的值转为父类对象的Super?
2. 强制转换怎么处理重写方法?
当调用子类构造函数构建子类对象的时候,必然会先调用父类的构造函数,即构建一个父类对象(怎么得到这个对象?),因此父类的成员(变量和方法)也会被构建。 如果存在同名,内存中将会同时存在父类的同名成员和子类的同名成员。由于Java的多态性只针对方法来说的,成员变量不存在多态,因此成员变量只与访问的变量类型有关,而方法的调用遵从多态的规则。
1、首相要了解的知识是,成员变量绑定的是引用的类型,方法绑定的是对象的类型,
2、在继承中子类可以重写父类的方法,引用指向的是父类的对象就调用父类的方法,引用指向子类的对象就调用子类重写的方法,相反,成员变量看 的是引用的类型,父类型调用父类的成员变量,子类型调用子类的成员变量。
3、简单说 方法看对象,变量看类型。属性是静态绑定在类上,方法是动态绑定到对象上 。