final类不能被继承,这是Java编译期强制限制;其方法默认不可重写,但无需显式加final;可正常实例化、实现接口、含非final字段;设为final旨在保障不可变性与安全,而非单纯防扩展。

final类不能被继承,这是硬性编译限制
Java中用 final 修饰一个类,最直接、不可绕过的特性就是:它**无法被任何其他类继承**。编译器会在编译期就报错,而不是运行时抛异常。
- 错误示例:
final class SecureConfig { /* ... */ } class MyConfig extends SecureConfig { /* 编译失败:Cannot inherit from final 'SecureConfig' */ } - 哪怕子类和父类在同一个包里、构造方法是
public、甚至父类没写任何方法——只要加了final,继承就彻底禁止 - 这个限制不依赖JVM版本或运行环境,是Java语言规范强制要求
final类中的方法默认不可重写,但无需显式加final
因为没有子类,所以所有实例方法天然失去被覆盖(override)的可能。JVM和编译器会把它们当作“事实上的 final 方法”处理,但你**不需要、也不应该**给每个方法都加上 final 关键字。
- 加了也没错,但纯属冗余,比如:
public final void save() { ... }在final类里毫无意义 - 例外:静态方法本来就不可被重写,是否加
final完全不影响行为,只是语义提醒 - 注意:
private方法本来就不可见、不可继承,也等价于final,但和final类无关
final类可以正常实例化、实现接口、包含非final成员变量
很多人误以为 final 类 = “完全冻结”,其实它只锁住继承这一条路,其他一切照常。
- 你可以用
new创建对象:String s = new String("hello");——String是final类,但完全可实例化 - 它可以实现任意接口:
final class Logger implements Runnable { public void run() { System.out.println("logging..."); } } - 它的字段可以是
final,也可以不是:private int counter;合法;但若要保证不可变性,得自己把字段也声明为final
为什么String、Integer这些类必须是final?关键在不可变性与安全
这不是为了“防扩展”而扩展,而是防止恶意或意外破坏核心契约。比如 String 的哈希值缓存、字符串池、== 和 .equals() 行为,全都建立在“内容永不改变”这个前提上。
立即学习“Java免费学习笔记(深入)”;
- 如果允许继承
String,子类就能覆写charAt()或length(),导致HashMap查找失效、序列化错乱、甚至绕过安全检查 -
工具类如
Math、Collections设为final,是为了避免子类偷偷修改max()或unmodifiableList()的逻辑 - 你自己写工具类时,如果它只提供静态方法且无状态,加
final是低成本高收益的安全加固
真正容易被忽略的一点:final 类不等于不可变类。你可以定义一个 final 类,里面全是可变字段(比如 ArrayList 字段),它依然能被外部修改。要实现不可变,还得配合 final 字段 + 私有构造 + 不暴露可变对象引用。










