一、final 关键字概述
final是最终、不可改变的意思,可以用来修饰类、方法、变量。 被 final 修饰之后,内容就不能被修改,不同修饰对象效果完全不同。
二、final 修饰类
1. 核心规则
final 修饰的类叫最终类,不能被继承,没有子类,但是它可以去继承别的父类。
底层原理:为了防止类的功能被子类篡改,Java 中很多源码类都是 final 类,比如
String、Integer。
2. 语法格式
// final修饰类,该类无法被继承 final class Animal{ } // 下面这行代码编译报错,final类不能被继承 // class Dog extends Animal{}重点阐释:final 类里面所有的方法,会隐式全部带上 final 效果,但是成员变量不受 final 影响,可以正常修改。
三、final 修饰方法
1. 核心规则
final 修饰的方法叫最终方法,该方法可以被继承,但是不能被子类重写。
使用场景:如果某个方法逻辑不希望子类覆盖改写,就加上 final。
2. 代码示例
class Person{ // final修饰方法:可以被子类调用,但是不能重写 public final void sleep(){ System.out.println("人需要睡觉"); } } class Student extends Person{ // 编译报错!父类final方法不允许重写 /* @Override public void sleep() { System.out.println("学生睡觉"); } */ } public class TestFinalMethod{ public static void main(String[] args) { Student s = new Student(); s.sleep(); // 子类可以直接继承调用父类final方法 } }注意:final 和 private 区别:
private私有方法,子类看不见,本质不能重写;final方法子类可以继承调用,禁止重写。
四、final 修饰变量
变量被 final 修饰,就变成常量,只能赋值一次,赋值完成后不能修改。
注意:变量分为局部变量、成员变量(实例成员变量、静态成员变量),规则有差异。
1.final 修饰局部变量
局部变量:写在方法、代码块内部的变量。
- 可以先声明,后赋值,只能赋值唯一一次;
- 一旦赋值,不能再次修改。
public class TestFinalVar{ public static void main(String[] args) { final int a; a = 10; //第一次赋值,允许 // a = 20; //编译报错,final局部变量不能二次修改 System.out.println(a); } }2.final 修饰实例成员变量(普通成员变量,属于对象)
实例成员变量属于对象,必须保证对象创建完成前完成唯一一次赋值。 两种赋值时机二选一:
- 定义的时候直接赋值
- 在构造方法中赋值
❗不能在普通方法里面给 final 实例成员变量赋值。
class Demo{ //方式1:定义直接赋值 final int NUM1 = 100; final int NUM2; //方式2:构造方法赋值,对象创建时完成赋值 public Demo(){ NUM2 = 200; } }3.final 修饰静态成员变量(static final,静态常量)
static+final 共同修饰的变量,称为静态常量。
- 属于类,直接类名。常量名访问;
- 赋值时机:定义直接赋值 / 静态代码块赋值;
- Java 开发规范:静态常量名字全部大写,下划线分隔。
class Constants{ //静态常量,规范大写 public static final int MAX_AGE = 150; } public class Test{ public static void main(String[] args) { System.out.println(Constants.MAX_AGE); } }4.final 修饰引用类型变量(重点易错)
⚠️非常容易踩坑! final 修饰引用变量,引用地址不能变,但是对象内部的属性可以修改。
- 引用变量存的是对象地址,final 保证地址不能重新指向别的对象;
- 对象里面的成员变量不受 final 限制,可以修改。
class User{ String name; public User(String name){ this.name = name; } } public class TestFinalRef{ public static void main(String[] args) { //final修饰引用变量u,u存储对象地址 final User u = new User("小明"); u.name = "小红"; //✅允许,修改对象内部属性 System.out.println(u.name); // u = new User("小李"); //❌报错,不能修改引用地址,不能指向新对象 } }五、final 知识点总结表格
| 修饰对象 | 作用效果 |
|---|---|
| final 修饰类 | 类不能被继承;类中方法默认 final 效果 |
| final 修饰方法 | 方法可以继承,不能重写 |
| final 修饰局部变量 | 只能赋值 1 次,值不可更改 |
| final 修饰实例成员变量 | 对象创建前完成唯一赋值,不可修改 |
| static final 静态常量 | 类加载阶段赋值,全局常量,名字大写 |
| final 修饰引用类型 | 对象地址不可改变,对象内部内容可以修改 |
六、常见面试易错点
final abstract能不能一起修饰类?不能!abstract 抽象类必须被继承,final 禁止继承,二者冲突。final abstract能不能修饰方法?不能!abstract 方法必须子类重写,final 禁止重写。