final
和 effectively final
?为什么这些关键字重要?
在 Java 中,一些变量需要在初始化后不再变化,以确保程序的安全性和可读性。
为什么你需要关心 final
和 effectively final
?
final
和 effectively final
来说,懂得它们之间的区别,你就能更好地利用 lambda
表达式和匿名内部类。 定义:
final
是 Java
的编译时常量修饰符,可用于变量、方法和类,表示在初始化后不能被修改。
基本规则:
示例:
// 1. 变量声明时初始化
final int MAX_VALUE = 100;
// 2. 初始化块中赋值
class MyClass {
final String name;
{
name = "Test"; // 这里允许赋值
}
}
使用场景:
PI
)final class MyClass
)final void myMethod()
)限制:
final int x = 10;
x = 20; // 编译错误:无法为最终变量 x 赋值
定义:
Java 8
引入了 effectively final
概念,用于区分部分已经在初始化后不再被修改的局部变量,尽管未显式使用 final
。
基本规则:
final
示例:
int effectivelyFinalVar = 10;
Runnable runnable = () -> {
System.out.println(effectivelyFinalVar); // 允许访问
};
使用场景:
Lambda
表达式和匿名内部类final
修饰符限制:
int count = 0;
Runnable counter = () -> {
count++; // 编译错误:该变量不是 effectively final
};
public void test() {
int x = 10; // 初始化
x = 5; // 重新赋值,破坏 effectively final
Runnable r = () -> System.out.println(x); // 编译错误
}
public void testEffectivelyFinal() {
String effectivelyFinalStr = "Hello";
// 以下代码编译错误
// effectivelyFinalStr = "World";
Runnable efLambda = () -> {
System.out.println(effectivelyFinalStr); // 允许访问
};
}
特性 | final | effectively final |
---|---|---|
修饰符显式性 | 必须显式声明 | 隐式规则 (编译器自动推断) |
适用范围 | 类字段、方法、类、局部变量 | 仅适用于局部变量 |