欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多态机制中的绑定规则

程序员文章站 2024-02-09 18:06:12
...

package com.example;

public class Base {

String var = "BaseVar"; // 实例变量
static String staticVar = "StaticBaseVar"; // 静态变量

void method() // 实例方法
{
System.out.println("Base method");
}

static void staticMethod() // 静态方法
{
System.out.println("Static Base method");
}

}


package com.example;

public class Sub extends Base {

String var = "SubVar"; // 实例变量
static String staticVar = "StaticSubVar"; // 静态变量

void method() // 隐藏父类的method()方法
{
System.out.println("Sub method");
}

static void staticMethod() // 隐藏父类的staticMethod()方法
{
System.out.println("Static Sub method");
}

String subVar = "Var only belonging to Sub";

void subMethod() {
System.out.println("method only belonging to Sub");
}

public static void main(String args[]) {
// 引用变量who被声明为Base类型,引用Sub类的实例
Base who = new Sub();

// 成员变量(静态变量,实例变量)与引用变量所声明的类型(Base类型)的成员变量绑定
System.out.println("who.var = " + who.var); // 所以,打印Base类的var变量

System.out.println("who.staticVar = " + who.staticVar); // 所以,打印Base类的staticVar变量

// 实例方法与引用变量实际引用的对象(Sub对象)的方法绑定
who.method(); // 所以,打印Sub实例的method()方法

// 静态方法与引用变量所声明的类型(Base类型)的方法绑定
who.staticMethod(); // 所以,打印Base类的staticMethod()方法
}
}


1.对于一个引用类型的变量,Java编译器按照它声明的类型来处理.
例如在以下代码中,编译器认为who是Base类型的引用变量,不存在subVar成员变量和subMethod()方法,编译报错

Base who = new Sub(); //引用变量who被声明为Base类型,引用Sub类的实例
who.subVar = "123"; //编译错,在Base类中没有subVar属性
who.subMethod(); //编译错,在Base类中没有submethod()方法

如果要访问Sub类的成员,必须通过强制类型转换:
Base who = new Sub();
//把Base引用类型的who成员变量强制转换为Sub引用类型
//把引用变量转换为子类的类型称为向下转型,把引用变量转换为父类的类型称为向上转型
((Sub)who).subVar = "123";
((Sub)who).subMethod();
Java编译器允许在具有直接或间接继承关系的类之间进行类型转换,对于向上转型,Java编译器会自动进行,对于向下转型,需要进行强制类型转换
如果两种类型之间没有继续关系,即不在继承树的同一个继承分支上,那么Java编译器不允许进行类型转换

2.对于一个引用类型的变量,运行时Java虚拟机按照它实际引用的对象来处理
例如以下代码虽编译可通过,但运行时会抛出ClassCastException运行时异常
Base who = new Base(); //who引用Base类的实例
Sub s = (Sub)who; //运行时会抛出ClassCastException
在运行时,子类的对象可以转换为父类类型,而父类的对象实际上无法转换为子类类型

3, 在运行时环境中,通过引用类型变量来访问所引用对象的方法和属性时,Java虚拟机采用以下绑定规则:
1, 实例方法与引用变量实际引用的对象的方法绑定,这种绑定属于动态绑定,因为是在运行时由Java虚拟机动态决定的

2, 静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经绑定

3, 成员变量(静态变量,实例变量)与引用变量所声明的类型的成员变量绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经绑定