JAVA语言中多态和修饰符的关系


一、先看一个段子理解多态和修饰符的关系
想象你和小明在玩”角色扮演游戏”:

​你是导演(父类),给小明分配了”普通员工”角色(父类方法)
​小明​(子类)说:”我要演得更骚气!”(方法重写)
但导演说:”不行!这个角色被final封印了,你只能按剧本演!”
这就是修饰符对多态的影响——它决定了小明能不能自由发挥演技!

二、访问修饰符:决定”能不能改剧本”   若要搞清楚访问修饰符可点击:                访问修饰符归纳链接访问修饰符归纳链接
1. public(开放派导演)

public class Director {
    public void act() { // 完全开放重写
        System.out.println("标准演技");
    }
}

class XiaoMing extends Director {
    @Override
    public void act() { // 允许魔改
        System.out.println("骚气舞步+激光特效");
    }
}

效果:小明可以随意发挥(完美多态)换句话说:任何类都能调用和重写,多态的”完全体形态”

​经典场景:接口方法默认public,实现类必须重写(如Runnable.run())

2. protected(有限开放导演)

protected void act() { 
    // 仅允许自家剧组(同包或子类)修改
}

潜规则:如果小明在别的影视公司(不同包),需要走后门(继承)才能改剧本,换句话说:

跨包继承时,子类必须通过继承关系才能重写

​实战技巧:适合框架设计中的模板方法模式(父类定义骨架,子类填充细节)

  1. default默认(包级导演)
    void act() { // 只允许同剧组(同包)修改 }
    致命伤:小明跳槽到其他公司(不同包)时,会收到”改剧本权限不足”警告,换句话说:

跨包开发时,”看似继承实则无法重写”的坑点

​规避方案:跨包协作时显式使用public/protected

4. private(霸道总裁导演)
private void act() { // 完全私有,禁止修改 }
现实案例:就像老板的加密文件,实习生连看的机会都没有,更别说修改(无法重写)

本质:子类同名方法≠重写,是平行宇宙的新方法

反模式案例:试图用子类private方法覆盖父类public方法导致多态失效

三、特殊修饰符:多态的”封印术”
1. final(如来佛封印)
`public final void act() { … } // 方法封印

public final class Director { … } // 类级封印`
三连暴击:

封印方法:子类只能照本宣科(无法重写)
封印变量:像被焊死的螺丝(常量)
封印类:直接断绝子嗣(无法继承)
​内存原理:final变量在编译期优化(常量池),方法内联优化
设计哲学:JDK中的String类被final修饰,保证不可变性安全

2. static(机器人演员)
public static void act() { ... }
反多态三定律:

属于类而不是实例(像没有灵魂的AI)
编译时绑定(导演提前录好的磁带)
同名不算重写,是隐藏(替身演员冒充本尊)
​字节码真相:静态方法在invokestatic指令中绑定,无多态性
​常见误区:误以为静态方法可以重写,实际是类级别
Director.act(); // 永远调用父类 XiaoMing.act(); // 这是新的静态方法!
3. abstract(强制创新导演)
public abstract void act(); // 必须重写
创作自由:
父类只给剧本大纲(抽象方法) 子类必须自己写分镜(强制实现)
模板方法模式:Hibernate的SessionImpl类,抽象方法由不同数据库实现
​设计规范:抽象类至少有一个抽象方法,强制子类创新

四、修饰符组合技(开发者必看)

  1. 最骚操作:
    public abstract class Animal { public abstract void eat(); // 必须重写 public final void breathe() { // 禁止修改 System.out.println("氧气是人类的朋友"); } }
    设计哲学:

呼吸方法final:生命不可儿戏
进食方法abstract:允许自由发挥
2. 死亡组合:
private final static String DNA = "ATCG";
四重封印:

私有访问 + 不可修改 + 类级别存在 + 常量

五、避坑
​final偷袭:重写final方法时,编译器会露出姨母笑(报错)
​静态伪装:以为重写static方法,实际是创建新方法
​跨包悲剧:用默认修饰符写的方法,在其他包无法多态
​private假动作:子类定义同名方法≠重写,是平行世界的新方法
六、多态机制:
一.影帝的千面人生
​1. 动态绑定(幕后特效)​
Animal animal = new Cat(); animal.eat(); // JVM通过虚方法表查找Cat.eat()
​JVM原理:虚方法表(vtable)实现运行时查找
​性能优化:HotSpot虚拟机的内联缓存(Inline Cache)
​2. 转型操作(换装魔法)​
// 向上转型(自动)
Actor actor = new StuntDouble();

// 向下转型(需显式) if(actor instanceof StuntDouble) { StuntDouble sd = (StuntDouble)actor; sd.dangerousAction(); }
​ClassCastException:Spring框架的Bean转型异常处理
​类型检查:Apache Commons的ClassUtils工具类封装
​3. 构造器陷阱(时间悖论)​
`class Father {
public Father() {
init(); // 危险操作!
}
public void init() { // }
}

class Son extends Father {
private String data;
@Override
public void init() {
System.out.println(data.length()); // NPE!
}
}​对象初始化顺序:父类构造器→子类成员变量初始化→子类构造器 ​安全规范:《Effective Java》条款19:禁止在构造器中调用可重写方法 二、实战:剧组生存指南 ​1. 防御式编程public final class SafeActor {
// 防止恶意子化
private final Object lock = new Object();

// 敏感方法封闭
public final void coreLogic() { /*...*/ }

}​2. 框架设计 // Spring风格的抽象模板public abstract class JdbcTemplate {
public final void execute() {
getConnection();
doStatement(); // 抽象方法
releaseConnection();
}
protected abstract void doStatement();
}​3. 性能优化 ​​​​ // 用final促进JIT编译优化public class Vector3D {
private final double x, y, z; // 基本类型final提升性能
// …
}​4. 安全审计 // FindBugs规则:检查final方法被意外重写if (!method.isFinal() && hasOverrideInSubclass()) {
reportSecurityRisk();
}三、全维度对照表 修饰符 多态影响 典型应用场景 JVM级特性public 完全开放多态 接口方法实现 虚方法表绑定
protected 受控继承环境多态 模板方法模式 跨包访问检查
private 禁止多态(方法隐藏) 内部工具方法 编译期静态绑定
final 封印多态(禁止重写/继承) 工具类/常量定义 方法内联优化
static 破坏多态(类级别绑定) 工具方法/单例模式 invokestatic指令
abstract 强制多态(必须重写) 框架扩展点设计 抽象方法报错校验`
四、开发者自查清单
是否所有public方法都考虑过被重写的风险?
final修饰的核心方法是否做了文档说明?
跨包继承时protected方法是否考虑访问控制?
静态方法是否被误用导致多态失效?
构造器中是否存在可重写方法调用?
向下转型是否都有instanceof安全检查?
抽象类的抽象方法是否稳定无需修改?
如果把这些概念比作剧组规则:

public是主角的自由发挥权 ​protected是配角的限定戏份 ​final是剧本的不可修改条款 ​abstract是导演留下的即兴发挥空间 ​多态就是演员的千人千面表演能力
理解这些规则,你就能在Java世界里既遵守规范,又演绎出精彩代码

​开放原则:需要多态的方法用public/protected
​安全锁:核心算法用final保护
​静态警示:工具类方法用static,但注意失去多态特性
​抽象契约:定义接口时多用abstract强制规范
​权限最小化:像管理后宫一样管理访问权限
举个栗子:咖啡店多态系统
`public abstract class Coffee {
public final void prepare() { // 固定流程
boilWater();
brew();
pourInCup();
addCondiments();
}

protected abstract void brew(); // 必须实现
protected abstract void addCondiments(); 

private void boilWater() { ... } // 底层细节不开放
public static void cleanMachine() { ... } // 静态方法

}

class Latte extends Coffee {
protected void brew() { … } // 必须实现
protected void addCondiments() { … }

public static void cleanMachine() { 
    // 这是新的静态方法!
}

}
`
设计精妙:

prepare()用final保护制作流程
抽象方法强制子类创新
静态方法实现工具功能
私有方法封装实现细节
记住:​修饰符是代码世界的交通规则,多态是老司机的漂移技巧。合理使用能让你的代码既有纪律性,又能玩出骚操作!

来源链接:https://www.cnblogs.com/Fenikso/p/18752789

© 版权声明
THE END
支持一下吧
点赞10 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容