讲隐藏和覆盖之前先看两个概念:静态类型和动态类型。
任何一个引用变量都有两个类型:一个叫静态类型,也就是定义该引用变量的类型;另一个叫动态类型,也就是该引用实际指向的对象类型。
比如对于两个类A和类B,有:A a=new B();
那么,引用a的静态类型就是A,动态类型就是B
先看一段示例
class Parent
{
public static String kind="javastudy.extendsstudy.parent";
public static int age=50;
public String name="Parent";
//静态方法,返回包名
public static String getKind()
{
System.out.println("parent的getKind()方法被调用了");
return kind;
}
//静态方法,返回年龄
public static int getAge()
{
System.out.println("Parent的getAge()方法被调用了");
return age;
}
//实例方法,返回姓名
public String getName()
{
System.out.println("Parent的getName()方法被调用了");
return this.name;
}
}
//子类
class Child extends Parent
{
public static String kind="javastudy.extendsstudy.child";
public int age=25;
public String name="child";
//隐藏父类静态方法
public static String getKind()
{
System.out.println("child的getkind()方法被调用了");
return kind;
}
//获取父类包名
public static String getParentKind()
{
return Parent.kind;
}
//覆盖父类实例方法
public String getName()
{
System.out.println("child的getName()被调用了");
return this.name;
}
//获取父类名称
public String getParentName()
{
return super.name;
}
/*
*错误,实例方法不能覆盖父类的静态方法
public int getAge()
{
return this.age;
}
*/
}
public class chongxieyuyincang {
public static void main(String[] args) {
Child child=new Child();
System.out.printf("子类名称:%s,年龄:%d,包名:%s%n",child.name,child.age,child.kind);
//输出:子类名称:child,年龄:25,包:javastudy.extendsstudy.child
//把child转换成parent对象
Parent parent=child;
System.out.printf("转换后的名称:%s,年龄:%d,包名:%s%n",parent.name,parent.age,parent.kind);
//输出:转换后的名称:Parent,年龄:50,包:javastudy.extendsstudy.parent
System.out.printf("子类访问父类被隐藏的实例变量name:%s%n",child.getParentName());
//输出:子类访问父类被隐藏的实例变量name:Parent
System.out.printf("子类访问父类被隐藏的静态变量kind:%s",child.getParentKind());
//输出:子类访问父类被隐藏的静态变量kind:javastudy.extendsstudy.parent
child.getName();
//输出:child的getName()被调用了
//**************注意看这个方法,返回的还是子类的getName
parent.getName();
//输出:child的getName()被调用了
child.getKind();
//输出:child的getkind()方法被调用了
parent.getKind();
//输出:parent的getKind()方法被调用了
}
}
子类名称:child,年龄:25,包名:javastudy.extendsstudy.child
转换后的名称:Parent,年龄:50,包名:javastudy.extendsstudy.parent
子类访问父类被隐藏的实例变量name:Parent
子类访问父类被隐藏的静态变量kind:javastudy.extendsstudy.parentchild的getName()被调用了
child的getName()被调用了
child的getkind()方法被调用了
parent的getKind()方法被调用了
1.同名的实例方法被覆盖 ,同名的静态方法被隐藏 ,child类的getName实例方法覆盖 了parent的getName实例方法,chind的getKind方法隐藏 了parent类的getKind方法
2.隐藏 和覆盖 的区别在于,子类对象转换成父类对象后,能够访问父类被隐藏 的变量和方法,而不能访问父类被覆盖 的方法
3.如果需要访问父类被隐藏 的部分,加上super就好了,比如访问父类的name,写上super.name就好了
这点儿请注意,就是变量只会被隐藏 不会被覆盖 ,无论他是实例变量还是静态变量,而且,子类的静态变量可以隐藏 父类的实例变量,子类的实例变量可以隐藏 父类的静态变量
父类的成员变量只会被隐藏,而且支持交叉隐藏(比如静态变量被非静态变量隐藏)。父类的静态方法只会被静态方法隐藏,不支持交叉隐藏。父类的非静态方法会被覆盖,但是不能交叉覆盖。
下面一个伪代码是自己写的,以便参考
//首先建立父子类,animal和cat ,然后对A函数进行静态隐藏
//对B函数进行重写,这里我就不写了
public class cat {
public static void main(String[] args) {
//接下来进行创建实例对象
Cat mycat=new Cat();
Animal myanimal=new mycat;
Animal.A();
myanimal.A();
Cat.A();
myanimal.B();
mycat.B();
}
}
//这里面,类cat重写了类animal的实例方法,隐藏了animal类方法
//在主函数中农,创建了一个cat的实例对象,调用了animal,myanimal,cat的类方法A
//HE MYANIMAL的实例方法B
//输出结果 父父子子子
//从上到下调用的依次是,类的类方法,对象的类方法,类的类方法
//对象的实例方法,对象的实例方法