class Fruit {
String color = "未确定颜色";
// 定义一个方法,该方法返回调用该方法的实例
public Fruit getThis() {
return this;
}
public void info() {
System.out.println("Fruit方法");
}
}
public class Apple extends Fruit {
String color = "红色";
// 重写父类的方法
@Override
public void info() {
System.out.println("Apple方法");
}
// 通过super调用父类的Info()方法
public void AccessSuperInfo() {
super.info();
}
// 尝试返回super关键字代表的内容
public Fruit getSuper() {
return super.getThis();
}
public static void main(String[] args) {
// 创建一个Apple对象
Apple a = new Apple();
// 调用getSuper()方法获取Apple对象关联的super引用
Fruit f = a.getSuper();
// 判断a和f的关系
System.out.println("a和f所引用的对象是否相同:" + (a == f));
System.out.println("访问a所引用对象的color实例变量:" + a.color);
System.out.println("访问f所引用对象的color实例变量:" + f.color);
// 分别通过a、f两个变量来调用info方法
a.info();
f.info();
// 调用AccessSuperInfo来调用父类的info()方法
a.AccessSuperInfo();
}
}
我们可以得出一个结论:
当程序创建一个子类对象时,系统不仅会为该类定义的实例变量分配内存,也会为其父类中定义的所有实例变量分配内存,即使子类与父类有同名的实例变量。也就是说,当系统创建一个 Java 对象时,如果该 Java 类有2个父类(一个直接父类 A ,一个间接父类 B ),假设 A 类中定义了2个实例变量, B 类中定义了3个的变量,当前类中定义了2个实例变量,那么这个 Java 对象将会保存2+3+2个实例变重。
如果在类里定义了与父类中已有变量同名的变量,那么子类中定义的变量会隐藏在父类中定义的变量。注意:不是完全覆盖,因此系统在创建子类对象时,依然会为父类中定义的、被隐藏的变量分配内存空间。
为了在子类方法中访问父类中定义的、被隐藏的实例变量,或者为了在子类方法中调用用父类中定义的、被覆盖( Override )的方法,可以使用 super .作为限定来修饰这些实例变量和实例方法
因为子类中定义与父类中同名的实例变量并不会完全覆盖父类中定义的实例变量,它只是简单的隐藏了父类中的实例变量
我们可以看下下面代码
class Parent
{
public String tag = "疯狂Java讲义"; // ①
}
class Derived extends Parent
{
// 定义一个私有的tag实例变量来隐藏父类的tag实例变量
private String tag = "轻量级Java EE企业应用实战";// ②
}
public class HideTest
{
public static void main(String[] args)
{
Derived d = new Derived();
// 程序不可访问d的私有变量:tag,所以下面语句引起编译错误
// System.out.println(d.tag); // ③
// 将d变量显式地向上转型为Parent后,即可访问tag实例变量,
// 程序将输出:"疯狂Java讲义"
System.out.println(((Parent) d).tag); // ④
}
}