先上结论
在多态中,变量和静态方法都是与类相挂钩的,和具体的对象是哪个无关。而实例方法的访问可以通过一条口诀来记忆:编译看左边,运行看右边。
结论验证
1. 访问变量和静态方法
之所以将它们俩归在一起总结,是因为结论很类似,但实际上,静态内容和实例内容差别是很大的。
比如 Parent p = new Child(); 如果是通过引用p去方法静态方法或者变量,那么访问的一定是父类中的内容,无论子类中是否存在与父类同名的静态方法或变量。
public class Parent
{
// 成员变量
public String publicString = "父类public修饰的成员变量";
// 静态变量
public static String staticString = "父类static修饰的静态变量";
// 静态方法
public static void method2()
{
System.out.println("父类public static修饰的成员方法");
}
public static void main(String[] args)
{
Parent p = new Child();
System.out.println(p.publicString );
System.out.println(p.staticString);
p.method2();
}
}
class Child extends Parent
{
//与父类同名的成员变量
public String publicString = "子类public修饰的成员变量";
//与父类同名的静态变量
public static String staticString = "子类static修饰的成员变量";
// 与父类重名的静态方法
public static void method2()
{
System.out.println("子类public static修饰的成员方法");
}
}
输出结果
父类public修饰的成员变量
父类static修饰的静态变量
父类public static修饰的成员方法
2.访问实例方法
实例方法才是多态的表现,静态方法和变量在多态中都是无效的。在 Parent p = new Child();中,使用引用p去调用实例方法,需要Parent类中有这个实例方法,才能编译通过,这称为静态绑定。但是在运行的时候,需要去在Child中寻找对应的方法,称为动态绑定。
public class Parent
{
// 父类中的成员方法
public void method1()
{
System.out.println("父类public修饰的成员方法");
}
public static void main(String[] args)
{
Parent p = new Child();
p.method1();
}
}
class Child extends Parent
{
// 与父类重名的成员方法
public void method1()
{
System.out.println("子类public修饰的成员方法");
}
}
运行结果:
子类public修饰的成员方法
但是,好像在子类中不重写父类的方法,好像一样可以调用方法。
public class Parent
{
// 父类中的成员方法
public void method1()
{
System.out.println("父类public修饰的成员方法");
}
public static void main(String[] args)
{
Parent p = new Child();
p.method1();
}
}
class Child extends Parent
{
// 子类中没有重写父类的method1方法
}
运行结果
父类public修饰的成员方法
虽然看起来好像是调用了父类中的方法,但实际上是因为子类继承了父类中的这个方法,运行的时候,还是去子类中寻找的。