Java多态性与类生命周期

**多态(Polymorphism)**是面向对象编程的三大特性之一(封装、继承、多态),分为编译时多态(静态多态)和运行时多态(动态多态),

编译时多态

编译时多态是指在编译阶段确定具体执行哪个方法。它主要通过方法重载(Overloading) 实现。

在同一个类中,有多个方法具有相同的名称但参数列表不同(参数类型、参数个数或参数顺序不同)

运行时多态

运行时多态是指在程序运行期间确定具体执行哪个方法。它主要通过方法重写(Overriding)接口(Interface) / 继承(Inheritance‌) 实现,并且需要结合向上转型(Upcasting)和动态绑定(Dynamic Binding)。

转型与绑定

向下转型(Downcasting)指将父类对象的引用 赋值给子类类型的变量 (如 Dog dog = (Dog) animal;

向上转型(Upcasting)是指将子类对象的引用 赋值给父类类型的变量 (如 Animal animal = new Dog();)。

向上转型是多态性的重要体现,其作用在于以统一的父类类型处理不同的子类对象(即同继承链),提高代码灵活性。

向上转型时,实际对象在内存中的结构保持不变(即保留完整子类所有字段和方法),父类引用仅作为访问对象的"视图窗口"(可以理解为只是代码层面的标识变了,对象本身没变)。

向上转型后,调用父类方法,但实际执行的是子类覆盖或继承的方法(动态绑定)。

向上转型后,无法通过调用子类特有的方法,即便是父类中有同名抽象方法也不行。

⚠️ 注意:在一些早期的 Java 版本中,虚拟机可能允许在父类引用变量上调用子类的特定方法,但这是不被推荐的,并且已经被更严格的 Java 规范所取代

绑定(Binding)指的是方法调用(Call)绑定到方法体(Implementation) ,分为静态绑定(Static Binding)动态绑定(Dynamic Binding)

特性 静态绑定 动态绑定
绑定时机 编译期 运行期
绑定方法 绑定到编译时声明类型的方法 绑定到实际对象类型的方法
方法类型 private/static/final/构造方法 可重写的实例方法
java 复制代码
// 抽象父类
abstract class Parent {
    // 具体方法 - 可被子类重写
    public void f1() {
        System.out.println("Parent's f1");
    }
    
    // 抽象方法 - 必须由子类实现
    public abstract void f2(); 
    
    // 静态方法 - 不能被重写,只会被隐藏
    public static void staticMethod() {
        System.out.println("Parent's static method");
    }
    
    // 最终方法 - 禁止子类重写
    public final void finalMethod() {
        System.out.println("Parent's final method (cannot be overridden)");
    }
    
    // 私有方法 - 不能被子类重写或访问
    private void privateMethod() {
        System.out.println("Parent's private method (only accessible within Parent)");
    }
    
    // 受保护方法 - 可被子类重写
    protected void protectedMethod() {
        System.out.println("Parent's protected method (can be overridden)");
    }
}

// 子类
class Child extends Parent {
    // 重写父类方法 - 动态绑定
    @Override
    public void f1() {
        System.out.println("Child's overridden f1");
    }

    // 实现父类抽象方法 - 动态绑定
    @Override
    public void f2() {
        System.out.println("Child's implementation of f2");
    }

    // 子类特有方法 - 父类引用无法访问
    public void f3() {
        System.out.println("Child's specific method f3");
    }
    
    // 隐藏父类的静态方法 - 静态绑定
    public static void staticMethod() {
        System.out.println("Child's static method (hiding parent's)");
    }
    
    // 尝试重写 final 方法会导致编译错误
    // @Override
    // public void finalMethod() { 
    //     System.out.println("This would cause an error");
    // }
    
    // 尝试"重写"父类 private 方法 - 实际上是新方法
    private void privateMethod() {
        System.out.println("Child's private method (not overriding)");
    }
    
    // 重写父类的 protected 方法
    @Override
    protected void protectedMethod() {
        System.out.println("Child's overridden protected method");
    }
}

public class Main {
    public static void main(String[] args) {
        // 向上转型:Parent引用指向Child对象
        Parent p = new Child(); 
        
        System.out.println("=== 动态绑定演示 ===");
        p.f1(); // 输出: "Child's overridden f1" - 动态绑定
        p.f2(); // 输出: "Child's implementation of f2" - 动态绑定
        p.protectedMethod(); // 输出: "Child's overridden protected method" - 动态绑定
        
        System.out.println("\n=== 私有方法行为演示 ===");
        p.callPrivate(); // 输出: "Child calling: Child's private method" - 调用子类重写的callPrivate
        
        System.out.println("\n=== 父类私有方法隔离演示 ===");
        Parent realParent = new Parent() {
            @Override
            public void f2() {
                System.out.println("Anonymous implementation of f2");
            }
        };
        realParent.callPrivate(); // 输出: "Parent calling: Parent's private method" - 调用父类私有方法
        
        System.out.println("\n=== 静态方法调用演示 ===");
        p.staticMethod(); // 输出: "Parent's static method" - 静态绑定
        Child.staticMethod(); // 输出: "Child's static method" - 直接调用
        
        System.out.println("\n=== Final方法调用演示 ===");
        p.finalMethod(); // 输出: "Parent's final method" - 不可重写
        
        System.out.println("\n=== 子类特有方法访问限制 ===");
        // p.f3(); // 编译错误:Parent类型中没有f3方法
        
        System.out.println("\n=== 向下转型演示 ===");
        if (p instanceof Child) {
            Child c = (Child) p; // 安全的向下转型
            c.f3(); // 输出: "Child's specific method f3" - 成功调用
            c.staticMethod(); // 输出: "Child's static method" - 但编译器会警告
        }
        
        System.out.println("\n=== 静态绑定与动态绑定对比 ===");
        Parent.staticMethod(); // 静态绑定:Parent's static method
        Child.staticMethod();  // 静态绑定:Child's static method
        
        System.out.println("\n=== 私有方法隔离性验证 ===");
        Child child = new Child();
        // child.privateMethod(); // 编译错误:privateMethod()在Child中不可见
        // 只能在Child类内部访问privateMethod
        
        System.out.println("\n=== 方法调用类型总结 ===");
        try {
            System.out.println("f1()调用类型: " + 
                (p.getClass().getMethod("f1").isBridge() ? "桥方法" : "普通虚方法"));
            System.out.println("privateMethod()可见性: " + 
                (p.getClass().getDeclaredMethod("privateMethod") != null ? "存在但不可访问" : "不存在"));
        } catch (NoSuchMethodException e) {
            System.out.println("无法通过反射访问privateMethod: " + e.getMessage());
        }
    }
}

接口与抽象类

特性 接口 (Interface) 抽象类 (Abstract Class)
实现/继承方式 多实现 (implements) 单继承 (extends)
方法实现 默认隐式 public abstract Java 8+ 支持 default 默认方法和 static 静态方法进行实现 自由混合抽象方法和具体实现方法
成员变量 只能是 public static final 常量 任意成员变量(普通/静态/常量)
构造方法 ❌ 不允许 ✅ 可定义构造方法
方法访问修饰符 隐式 public (Java 9+ 可 private 任意访问修饰符
设计目的 定义行为契约("能做什么") 提供基础实现("是什么")基于接口的策略模式(Strategy Pattern)

基于"接口 + 组合"的策略模式(Strategy Pattern),定义策略接口,继而由具体策略类提供具体算法实现,而上下文(Context)持有一个策略对象的引用,通过组合动态切换策略。

基于"抽象类 + 继承"的模板方法模式(Template Method Pattern),就是在抽象类定义算法的骨架,将某些步骤延迟到子类实现。

类生命周期

  • 类加载机制:加载(Loading) -> 链接(Linking) -> 初始化(Initialization)
  • 类使用阶段:实例化 (Instantiation) -> 方法调用 / 字段访问 /反射操作等
  • 类生命周期:类加载机制 -> 使用阶段(Using) -> 卸载(Unloading)

否 否 是 是 开始创建子类B实例 父类A是否已加载? 加载父类A 初始化父类A静态变量 执行父类A静态块 子类B是否已加载? 加载子类B 初始化子类B静态变量 执行子类B静态块 分配堆内存空间 初始化父类A实例变量 执行父类A实例初始化块 执行父类A构造器 初始化子类B实例变量 执行子类B实例初始化块 执行子类B构造器 对象创建完成 第二次创建B实例 分配堆内存空间

java 复制代码
class A {
    // 静态变量
    private static String staticFieldA = initStaticField("A类静态变量");
    
    // 静态初始化块
    static {
        System.out.println("A类静态初始化块");
    }
    
    // 实例变量
    private String instanceFieldA = initInstanceField("A类实例变量");
    
    // 实例初始化块
    {
        System.out.println("A类实例初始化块");
    }
    
    // 构造器
    public A() {
        System.out.println("A类构造器");
    }
    
    // 辅助初始化方法
    private static String initStaticField(String msg) {
        System.out.println(msg);
        return "";
    }
    
    private String initInstanceField(String msg) {
        System.out.println(msg);
        return "";
    }
}

class B extends A {
    // 静态变量
    private static String staticFieldB = initStaticField("B类静态变量");
    
    // 静态初始化块
    static {
        System.out.println("B类静态初始化块");
    }
    
    // 实例变量
    private String instanceFieldB = initInstanceField("B类实例变量");
    
    // 实例初始化块
    {
        System.out.println("B类实例初始化块");
    }
    
    // 构造器
    public B() {
        System.out.println("B类构造器");
    }
    
    // 辅助初始化方法(与父类同名但独立)
    private static String initStaticField(String msg) {
        System.out.println(msg);
        return "";
    }
    
    private String initInstanceField(String msg) {
        System.out.println(msg);
        return "";
    }
}

public class InitializationOrder {
    public static void main(String[] args) {
        System.out.println("--- 第一次创建B实例 ---");
        new B();
        
        System.out.println("\n--- 第二次创建B实例 ---");
        new B();
    }
}
log 复制代码
--- 第一次创建B实例 ---
A类静态变量
A类静态初始化块
B类静态变量
B类静态初始化块
A类实例变量
A类实例初始化块
A类构造器
B类实例变量
B类实例初始化块
B类构造器

--- 第二次创建B实例 ---
A类实例变量
A类实例初始化块
A类构造器
B类实例变量
B类实例初始化块
B类构造器
相关推荐
CryptoRzz2 小时前
对接印度股票市场数据 (India api) 实时k线图表
java·开发语言·python·区块链·maven
CoderYanger2 小时前
第 479 场周赛Q1——3769. 二进制反射排序
java·数据结构·算法·leetcode·职场和发展
程序员岳焱2 小时前
Java 调用 DeepSeek API 的 8 个高频坑
java·人工智能·后端
CoderYanger2 小时前
A.每日一题——1925. 统计平方和三元组的数目
java·开发语言·数据结构·算法·leetcode·哈希算法
小白程序员成长日记2 小时前
2025.12.08 力扣每日一题
java·算法·leetcode
zz0723202 小时前
数据结构 —— 并查集
java·数据结构
Lenyiin3 小时前
makefile
java·大数据·前端
涡轮蒸鸭猫喵3 小时前
-------------------UDP协议+TCP协议-------------------------
java·网络·笔记·网络协议·tcp/ip·udp
汝生淮南吾在北3 小时前
SpringBoot+Vue非遗文化宣传网站
java·前端·vue.js·spring boot·后端·毕业设计·课程设计