多态的实现机制

时间:2023-04-14
标签: #Java #多态 #实现机制 #示例


一旦学会了多态,就可以以多态的思维方式考虑每件事。然而,只有普通的方法调用可以是多态的。例如,如果你直接访问一个属性,该访问会在编译时解析:

// polymorphism/FieldAccess.java 
// Direct field access is determined at compile time 
class Super { 
	public int field = 0; 
	public int getField() {
		return field; 
	} 
} 

class Sub extends Super { 
	public int field = 1; 
	@Override public int getField() { 
		return field; 
	} 
	
	public int getSuperField() { 
		return super.field; 
	} 
} 

public class FieldAccess { 
	public static void main(String[] args) { 
		Super sup = new Sub(); 
		// Upcast 
		System.out.println("sup.field = " + sup.field + ", sup.getField() = " + sup.getField()); 
		Sub sub = new Sub(); 
		System.out.println("sub.field = " + sub.field + ", sub.getField() = " + sub.getField() + ", sub.getSuperField() = " + sub.getSuperField()) 
	} 
}
//输出: sup.field = 0, sup.getField() = 1 sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0 

我注意到上述的代码中 sup.field = 0, sup.getField() = 1,这样我对于 Java 底层实现多态的机制有些迷惑,他是如何确定到底是哪个方法要被执行的呢,是否是有个存储方法的栈之类的呢?

在 Java 中,多态仅适用于方法调用,而不适用于字段访问。这就是为什么在上面的例子中,sup.field 的值为0,而 sup.getField() 的值为1。字段的访问在编译时就已经确定,而方法调用则在运行时动态绑定。

在这个例子中,当我们执行以下语句:

Super sup = new Sub(); // Upcast

sup 是一个 Super 类型的引用,但它实际上引用了一个 Sub 类型的对象。当我们访问字段 sup.field 时,编译器在编译时就已经确定我们访问的是 Super 类型的 field,因此返回值为0。

然而,当我们调用 sup.getField() 时,JVM会在运行时检查sup引用的实际对象类型(即 Sub 类型),并调用 Sub 类中的 getField() 方法。这就是为什么 sup.getField() 返回1的原因。

多态背后的原理是利用了一种称为“虚方法表”(vtable)的机制。简而言之,当一个类被加载时,JVM会为其创建一个包含其所有方法的表。对于继承自父类的方法,子类中若有重写的方法,虚方法表中的对应条目将被子类方法替换。当我们通过一个引用调用一个方法时,JVM会根据引用的实际对象类型查找对应的虚方法表,然后调用表中对应的方法。

这就是Java实现多态的基本机制。要注意的是,多态仅适用于方法调用,不适用于字段访问。因此,在处理多态时,需要确保只通过方法调用来实现多态行为。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值