JAVA基础 之 父类引用指向子类对象(多态)

本文探讨了JAVA中的多态特性,通过一个实例解释了父类引用如何指向子类对象。当父类引用指向子类对象时,只能调用父类已有的方法和属性,不能访问子类独有的部分。同时,介绍了动态绑定的概念,即如果父类方法被子类覆写,父类引用将调用子类覆写后的方法。此外,父类和子类各自定义的同名变量保存在不同内存空间,父类引用调用的是父类的变量值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在弄懂桥接设计模式的时候,看到了这样一条语句Bridge bridge = new MyBridge();相关类:
public class Bridge {
	private Sourceable source;
	public void method(){
	}
	
	public Sourceable getSource() {
		return source;
	}

	public void setSource(Sourceable source) {
		this.source = source;
	} 
	
}

public class MyBridge extends Bridge{
	 public void method(){  
	        getSource().method();  
	    }
}

显而易见的MyBridge类继承了Bridge类,那这里为什么可以Bridge bridge = new MyBridge();呢?父类引用指向了子类的对象。

为了方便理解,我们来看下面的例子:

public class Father {
	public String a = "123456";
	public void func1(){
	        System.out.println("AAA");
	    }
	 public void func2() {
	        System.out.println("BBB");
	    }
}

class Child extends Father { 
	public String a ="45466";
	    public void func1(int i) {//重
### Java 多态的原理及父类引用指向子类对象的工作机制 Java 中的多态一种重要的面向对象特性,它允许可变数量的不同型的对象以统一接口的形式呈现出来。以下是关于父类引用指向子类对象工作机制的具体解析。 --- #### 1. **多态的核心概念** 多态指的是在继承关系下,当父类子类拥有相同签名的方法时,运行时会调用实际对象所属中的方法而非声明型中的方法[^1]。这种行为依赖于动态绑定(Dynamic Binding),也称为后期绑定或运行时绑定。 - 动态绑定意味着 JVM 在程序运行期间决定应该调用哪个具体实现。 - 只有实例方法支持动态绑定,静态方法和变量则不参与多态[^3]。 --- #### 2. **JVM 的内存模型分析** 为了更好地理解父类引用指向子类对象的行为,可以从 JVM 的内存管理角度出发: ##### (1)**栈区与堆区的作用** - 当创建一个对象时,JVM 在 **堆区** 创建了完整的子类对象,其中包括子类自身的属性、方法以及从父类继承来的所有成员[^3]。 - 同时,在 **栈区** 创建了一个父类型的引用变量,用来保存堆中对象的地址。 ##### (2)**引用对象的关系** - 栈中的父类引用仅能访问父类定义范围内的方法和字段。 - 若子类重写了父类的方法,则运行时会优先调用子类中的实现。 - 如果尝试访问子类特有的方法或字段,则需显式地将父类引用向下转型为子类型[^2]。 --- #### 3. **代码示例及其解释** 以下是一个典型的多态场景演示: ```java class Animal { public void makeSound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { @Override public void makeSound() { System.out.println("Dog barks"); } public void wagTail() { System.out.println("Dog wags its tail"); } } public class TestPolymorphism { public static void main(String[] args) { // 父类引用指向子类对象 Animal animal = new Dog(); // 调用了子类重写的 makeSound 方法 animal.makeSound(); // 输出: Dog barks // 尝试调用子类特有方法会报错 // animal.wagTail(); // 编译错误! // 下转型后可访问子类特有方法 ((Dog) animal).wagTail(); // 输出: Dog wags its tail } } ``` - 上述代码展示了父类引用 `animal` 指向子类对象 `Dog`。 - 运行时调用了子类重写的 `makeSound()` 方法[^1]。 - 若要调用子类独有的方法 `wagTail()`,必须先将其强转回子类型[^2]。 --- #### 4. **方法覆盖 vs 方法隐藏的区别** 需要注意的是,只有非静态方法才能体现多态性,因为它们会被动态绑定到实际对象上。而对于静态方法而言,编译期就已经决定了调用哪一个版本,这被称为方法隐藏而不是覆盖。 举例如下: ```java class Parent { public static void display() { System.out.println("Parent's static method"); } public void test() { System.out.println("Parent's instance method"); } } class Child extends Parent { public static void display() { System.out.println("Child's static method"); } @Override public void test() { System.out.println("Child's instance method"); } } public class StaticVsInstance { public static void main(String[] args) { Parent p = new Child(); p.display(); // 输出: Parent's static method 【静态方法未被覆盖】 p.test(); // 输出: Child's instance method 【动态绑定生效】 Child c = new Child(); c.display(); // 输出: Child's static method 【直接调用本静态方法】 } } ``` --- #### 5. **总结工作流程** 基于以上讨论,可以归纳出父类引用指向子类对象的工作机制如下: 1. 声明阶段:定义一个父类型的引用变量。 2. 初始化阶段:让该引用指向一个具体的子类对象实例。 3. 访问控制:通过父类引用只能访问父类可见的部分;若子类重写了某些方法,则运行时会选择子类的实际实现。 4. 特殊需求处理:如需操作子类独占的功能,可通过强制型转换恢复原始型[^2]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值