马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
一、先看一个段子理解多态和修饰符的关系
想象你和小明在玩"角色扮演游戏":
你是导演(父类),给小明分配了"普通员工"角色(父类方法)
小明(子类)说:"我要演得更骚气!"(方法重写)
但导演说:"不可!这个角色被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() {
- // 仅允许自家剧组(同包或子类)修改
- }
复制代码 潜规则:假如小明在别的影视公司(不同包),须要走后门(继续)才能改剧本,换句话说:
跨包继续时,子类必须通过继续关系才能重写
实战技巧:得当框架设计中的模板方法模式(父类定义骨架,子类添补细节)
- 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类,抽象方法由不同数据库实现
设计规范:抽象类至少有一个抽象方法,逼迫子类创新
四、修饰符组合技(开发者必看)
- 最骚操纵:
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保护制作流程
抽象方法逼迫子类创新
静态方法实现工具功能
私有方法封装实现细节
记住:修饰符是代码世界的交通规则,多态是老司机的漂移技巧。合理使用能让你的代码既有规律性,又能玩出骚操纵!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |