Java中final关键词与常量
1. 什么是 final
在 Java 中,final 是一个修饰符,可以用在类、方法和变量上,它的含义是:不可更改 / 最终确定。
2. final 的作用
2.1 修饰方法
当 final
修饰一个方法时,这个方法不能被任何子类重写(Override)。
作用
-
锁定实现: 确保某个方法的行为在所有子类中保持一致,防止子类修改核心逻辑。
-
提高效率: Java 编译器可以将 final 方法视为非虚方法,可能进行内联优化,从而提高执行效率(尤其是在早期 JDK 版本中)。
示例
class Parent {public final void coreLogic() {// 这是父类的核心逻辑,不希望被子类改变System.out.println("Executing core logic.");}
}class Child extends Parent {// 编译错误:不能重写 final 方法// public void coreLogic() {}
}
2.2 修饰类
当 final
修饰一个类时,这个类不能被其他任何类继承。
作用
-
结构安全: 确保类的结构和实现细节不会被外部修改或扩展,增强安全性。
-
不可变类基础: 许多不可变类(如 Java 的核心类 String、Integer 等)都是用 final 关键字修饰的,以防止被继承并破坏其不可变性。
示例
public final class Math {// Math 类是 final 的,不能被继承
}
// 下面的代码会报错
// class MyMath extends Math {}
2.3 修饰变量
当 final
修饰一个变量时,该变量就成了一个常量,它的值在初始化后就不能再被改变。
规则和用法
-
必须初始化: final 变量必须在声明时、构造方法中或静态初始化块中被赋值一次。
-
不可变性: 一旦初始化,任何尝试修改其值的操作都会导致编译错误。
-
通常配合
static
一起使用,表示类常量(全局共享)。
示例
修饰对象 | 示例代码 | 说明 |
---|---|---|
实例变量 | private final String NAME = "John"; | 每个对象都有一个不可变的 NAME 值。 |
局部变量 | public void method() { final int COUNT = 10; } | COUNT 在方法执行过程中保持为 10。 |
静态变量(类常量) | public static final double PI = 3.14159; | 命名规范:通常使用 static final 修饰,名称全部大写,用于表示全局常量。 |
注意:引用类型
如果 final 修饰的是一个引用类型变量(如一个对象),则:
- 该引用本身不能改变,即不能让它指向另一个新的对象。
final StringBuilder sb = new StringBuilder("Hello");// 1. 允许:修改对象内部状态
sb.append(" World"); // sb 变为 "Hello World"// 2. 编译错误:不能指向新对象
// sb = new StringBuilder("New");
- 引用指向的对象内部的状态(属性值) 是 可以改变的(除非该对象本身是不可变的,如
String
)。
// 创建对象
final Student S = new Student("张三", 23);// 以下行为虽然改变了S的属性,但不会报错
S.setname("李四");
S.setAge(22);
补充:常量
在 Java 中,常量(Constant) 是指一旦被定义和初始化后,其值在程序的整个生命周期内都不能被修改的量。它们通常用于存储固定的配置值、数学常数或不变的标识符。
1. 常量的定义与类型
常量可以分为两大类:
-
字面量常量(Literal Constant):代码中直接写出来的固定值,例如 3.14、“Hello”。
-
符号常量(Named Constant):通过关键字
final
声明的变量,赋值后不能修改。
2.符号常量的几种形式
在 Java 中,我们通过结合使用两个关键的关键字来定义一个符号常量:static
和 final
1 基本常量
使用 final
修饰变量,使其值不可变:
示例
final int DAYS_IN_WEEK = 7;
final double PI = 3.14159;
特点
-
必须在声明时初始化,或者在构造方法中赋值。
-
一旦赋值,不能修改。
2 类常量(全局常量)
常见写法是使用 public static final
定义,通常放在类里。
public
关键字的作用是方便外部直接访问。static
关键字的作用是让变量属于类(Class)本身,所有对象共享,而不是属于类的任何特定对象(Object)。final
关键字的作用是使常量值固定不可变。
如果没有 static 修饰,每创建一个对象,这个常量就会在内存中复制一次,浪费空间。使用 static 确保了该值在内存中只存在一份拷贝,所有地方引用的都是同一个值,这是效率和统一性的要求。
示例
public class Config {public static final int MAX_USERS = 100;public static final String APP_NAME = "MyApp";
}
使用时:
int limit = Config.MAX_USERS;
3.枚举常量
当一组值是固定范围时,用 enum
定义比多个常量更语义化。
示例
enum Direction {NORTH, SOUTH, EAST, WEST
}
使用时:
Direction d = Direction.NORTH;
3. 常量的命名规范
Java 对公共常量的命名有严格的约定,以增强代码可读性:
-
单个单词全部大写
-
多个单词全部大写,单词之间用下划线_分隔
修饰对象 | 示例代码 | 说明 |
---|---|---|
实例常量 | private final String NAME = "John"; | 注意: 仅 final 修饰,不含 static 。它不是传统意义的全局常量,而是每个对象初始化后不能再改变的属性。 |
局部常量 | public void method() { final int COUNT = 10; } | 仅 final 修饰,用于限制方法内部的临时变量不能被重新赋值。 |
静态常量(标准类常量) | public static final double PI = 3.14159; | 命名规范: 使用 static final 修饰,名称全部大写,用于表示全局、不变的常量。 |
4. 为什么要使用常量
- 避免魔法数字(Magic Number)
以下写法不推荐:
推荐写法:if (speed > 120) { ... }
final int MAX_SPEED = 120;if (speed > MAX_SPEED) { ... }
- 易于维护: 如果一个常量的值需要更新(比如
MAX_USERS
从 100 变到 200),只需要修改定义处的一行代码。 - 提高可读性:
DAYS_OF_WEEK
比数字 7 更容易理解代码的意图。 - 防止错误:
final
属性从根本上杜绝了值被程序意外修改的可能性。