final修饰变量、方法、类分别表示不可变引用、禁止重写、禁止继承;常量需static final组合,但仅此不足以保证对象不可变。

final修饰变量:一旦赋值就不能再改
Java里final加在变量前,表示这个变量只能被赋值一次。基本类型(如int、boolean)赋值后值不可变;引用类型(如String、List)赋值后引用地址不可变,但对象内部状态仍可能改变。
- 声明时未初始化,必须在构造方法或初始化块中完成赋值(类成员变量)
- 局部变量用
final,必须在声明后“明确赋值”,且不能重复赋值 -
final int x;在方法里不赋值会编译报错:variable x might not have been initialized -
final List合法,后续可调用list = new ArrayList(); list.add("a")—— 因为只是修改了对象内容,没改变list指向的地址
final修饰方法:禁止子类重写
加在方法签名前,表示该方法不能被子类覆盖。常见于模板方法模式中固定流程的步骤,或防止关键逻辑被意外修改。
-
final void process() { ... }子类继承后无法用@Override重写它 - 不影响重载(overload),只限制重写(override)
- 性能上现代JVM基本不依赖
final做内联优化,别为了“性能”盲目加final - 构造方法不能用
final(语法错误),静态方法加final无意义(本来就不能被重写)
final修饰类:彻底封死继承链
final class Utils { ... } 表示这个类不能被继承。这是最彻底的封装手段,适用于工具类、不可变类(如String、Integer)。
- 任何试图
class MyUtils extends Utils的代码都会触发编译错误:cannot inherit from final Utils - 类中所有方法自动成为
final(无需显式写),但已有private方法本来就不可见,不受影响 - 如果类含非
final字段,仍需自行保证不可变性(比如字段也得是final+ 不提供修改方法)
常量定义为什么习惯用static final
Java里“常量”通常指全局唯一、运行期不可变的值,标准写法是public static final TYPE NAME = VALUE;。
立即学习“Java免费学习笔记(深入)”;
-
static让变量属于类而非实例,避免每个对象都存一份 -
final确保值不可变,配合static才构成真正意义上的常量 - 编译器会对
static final基本类型/字符串做“编译期常量优化”:直接内联字面量,所以修改值后依赖方不重新编译可能看不到更新 - 注意:如果用
static final List但没做不可变包装(如Collections.unmodifiableList),外部仍可能通过引用修改内容
final不是“一加就安全”,它只管引用或值的绑定关系。真正要实现不可变对象,字段得全final,类型得不可变或防御性拷贝,构造过程还得防泄漏——这些容易被忽略。









