Java final关键字:阻止继承和多态
声明类、变量和方法时可以用 final 修饰,表示终态:这个东西定下来以后就不能再改继承关系、不能再被覆盖、不能再被重新赋值。
具体规定:final 类不能被继承;final 方法不能被子类重写;final 变量(成员或局部)只能赋值一次,成为常量。
| 修饰对象 | 效果 | 补充 |
|---|---|---|
| 类 | 不能再派生子类 | 方法隐式 final;字段不会因此变成常量 |
| 方法 | 不能被覆盖,静态绑定 | private / static 方法本身就不能被覆盖 |
| 基本类型变量 | 只能赋值一次 | 常量名习惯全大写 |
| 引用类型变量 | 引用不能再指向别的对象 | 对象内部状态仍可改 |
一、final 变量
final 一般用来保护不该被改掉的通用功能或取值,例如三角函数、幂运算,以及数学常量 Math.PI、Math.E。java.lang.Math 本身也是 final 类,防止被继承后篡改这些实现。
成员变量可以在声明时赋值;若声明时没赋值(空白 final),实例字段必须在每个构造方法里显式赋一次(也可以在实例初始化块里),静态 final 则在静态块里赋。局部 final 可以先声明后一次性赋值。再赋值会编译失败。
引用被标成 final,只锁住“指向谁”,不锁住对象里面的字段。子类可以继承可见的 final 字段并读取,但不能覆盖或重新赋值。
二、final 类
final 放在 class 前面,阻止再派生。例如 java.lang.String 就是 final 类:拿到一个字符串引用,必须就是 String 本身,而不能是某个恶意子类伪装出来的“字符串”。类一旦是 final,其中方法也隐式按 final 处理,变量不会。
三、final 方法与多态
final 方法不能被覆盖,属于静态绑定,运行时不必再查方法表。被 static 或 private 修饰的方法本来就不能参与多态覆盖,动态绑定没有意义。
有人主张“除非明确要多态,否则方法全写成 final”。这偏激了:JVM 的即时编译器能根据运行时继承关系做优化。方法很短且没有被覆盖时,编译器可以内联(inlining),例如把 e.getName() 替换成直接读 e.name。CPU 处理调用时的分支会打乱预取,内联能避开这一点。一旦 getName() 在别的类里被覆盖,编译器就无法预知覆盖代码做什么,也就不能内联。
一句话总结:final 类不能继承,final 方法不能覆盖,final 变量只能赋一次——引用 final 只锁住指向,不锁住对象内容。
转载请注明来源:Java final关键字:阻止继承和多态本文链接地址:https://ai.zhousir.top/?p=97







