abstract class Animal {
abstract void call();
}
class Dog extends Animal {
public void call(){
System.out.println("汪汪");
}
}
class Cat extends Animal {
public void call(){
System.out.println("喵喵");
}
}
定义:
首先我们先明确几个概念,引用变量、引用变量的声明类型和引用变量的引用类型,在Java虚拟机编译和运行时,会根据引用变量的声明类型和引用类型来静态或动态的绑定相关的属性或方法。
Animal dog = new Dog();
Animal cat = new Cat();
引用变量:变量dog和变量cat为引用变量,引用变量是对类、接口和数组的引用。
引用变量的声明类型:dog和cat的声明类型是Animal。
引用变量的引用类型:dog和cat的引用类型分别是Dog和Cat。
class Base {
String var = "base var"; //实例变量
static String staticVar = "static base var";//静态变量
void method() {} //实例方法
static void staticMethod() {} //静态方法
}
class Sub extends Base {
String var = "sub var"; //实例变量
static String staticVar = "static sub var"; //静态变量
void method() {} //覆盖父类实例方法
static void staticMethod() {} //隐藏父类静态方法
String subVar = "subVar";
void subMethod() {}
}
原则:
1.对于一个引用类型的变量,Java编译器按照它声明的类型来处理。
Base who = new Sub(); //who的声明类型为Base,引用类型为Sub
who.subVar = "abc"; //编译错误
who.subMethod(); //编译错误
因为引用变量who的声明类型为Base,而实际引用类型为Sub。所以在Java虚拟机编译时,在Base类中未发现subVar变量和subMethod方法,导致编译错误。
2.对于一个引用类型的变量,运行时Java虚拟机按照它实际引用的对象来处理。
Base who = new Sub(); //who的声明类型为Base,引用类型为Sub
who.var = "abc"; //给Base的var变量赋值
who.staticVar = "abc"; //给Base的staticVar变量赋值
who.method(); //执行Sub的method方法
who.staticMethod(); //执行Base的staticMethod方法
3.在运行时环境中,通过引用类型变量来访问所引用对象的方法和属性,Java虚拟机采用以下绑定规则。
●实例方法与引用变量实际引用的对象的方法绑定,这种绑定属于动态绑定,因为是在运行时由Java虚拟机动态决定的。
●静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经做了绑定。
●成员变量(包括静态变量和实例变量)与引用变量所声明的类型的成员变量绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经做了绑定。