故事场景:Java魔法学院的规则与传承
在“Java魔法学院”里,大法师(就是你,程序员)需要制定一些规则,确保学院的魔法(代码)既强大又安全。他最厉害的法术就是施加“终极封印” (final
)。
场景一:final
变量 — “永恒的誓言”
大法师在学院的基石上刻下了两条誓言:
• 誓言1:基本常数 (
final
a primitive type)
final int MAX_SPEED = 120;
大法师宣布:“我们学院魔法扫帚的最高时速,永远被锁定在120!这是铁律,不可更改!” 他在这条规则上施加了“终极封印”。从此,无论谁都无法修改这个速度值。它成了一个恒定的值。• 誓言2:固定的藏宝图 (
final
a reference type)
final List<String> UNMODIFIABLE_REFERENCE_LIST = new ArrayList<>();
大法师拿出一张古老的羊皮卷,说:“这张特定的羊皮卷,将作为我们学院的‘禁咒名单’!” 他对这张羊皮卷本身施加了“终极封印”。• 这意味着:你不能把“禁咒名单”换成另一张纸(不能让
UNMODIFIABLE_REFERENCE_LIST
指向一个新的ArrayList
)。这张羊皮卷的身份是固定的。• 但是:这张羊皮卷并没有被封死。你仍然可以拿起笔,在上面添加新的禁咒(
.add("Apple")
),或者擦掉某个(.remove()
)。• 结论:
final
封印的是“持有藏宝图的那只手”,这只手不能再换别的地图了;但“藏宝图上的内容”是可以修改的。
场景二:final
方法 — “失传的咒语”
学院的图书馆里,记载着各种魔法。
• 普通咒语 (
performBasicSpell
): 比如“漂浮咒”,学生们可以学习并根据自己的理解进行改良,创造出“强力漂浮咒”等新版本(方法重写override
)。• 终极咒语 (
final performSealedSpell
): 但在图书馆最深处,有一本被大法师施加了“终极封印”的古书,上面记载着一个威力巨大的咒语,比如“守护神咒”。大法师规定:“这个咒语的每一个音节、每一个手势都是完美的,后人只可学习和使用,永远不许修改其施法方式!”• 结果:任何学生(子类)都可以学习并使用“守护神咒”,但当他们试图“改良”这个咒语时(重写
final
方法),封印就会被触发,导致魔法失败(编译错误)。
场景三:final
类 — “终极的传承”
有些大法师穷尽一生,创造出了最完美的魔法生物。
• 大法师甘道夫 (
final class Archmage
): 他创造出了自己最杰出的作品——大法师本人。他认为自己的设计(class
)已经达到了魔法的顶峰,是完美的,不应再有任何形式的“后代”或“变种”。于是,他对自己整个传承施加了“终极封印”。• 结果:任何年轻的魔法师(其他类)都不能继承这位大法师的血脉(
extends Archmage
),从而创造出一个“年轻版甘道夫”。这个传承(class
)到他这里就是终点。它自身是完整的,但不能被用作创造新物种的蓝本。
故事总结:
封印对象 |
final 变量 (誓言) |
final 方法 (咒语) |
final 类 (传承) |
封印效果 | 不可变 。基本类型是值不变,引用类型是“那只手”不能再指向别处。 |
不可重写 。子孙后代不许修改我的独门绝技。 |
不可继承 。我的血脉到此为止,不许有后代。 |
故事比喻 | 永恒的誓言 | 失传的咒语 | 终极的传承 |
核心目的 | 保证数据恒定或引用的专一。 |
保证方法行为的统一性和安全性。 |
保证类设计的完整性和不可扩展性。 |
记住大法师的“终极封印”,你就掌握了 final
关键字在Java世界中守护秩序的三大力量。
完整代码
import java.util.ArrayList;
import java.util.List;
publicclassFinalKeywordDemo {
// 1. final 变量: 永恒的契约
// 对于基本类型,值不可变。
privatefinalintMAX_SPEED=120;
// 对于引用类型,引用地址不可变,但对象本身的内容可以修改。
privatefinal List<String> UNMODIFIABLE_REFERENCE_LIST = newArrayList<>();
publicvoiddemonstrateFinalVariable() {
// MAX_SPEED = 130; // 编译错误!无法为最终变量 MAX_SPEED 分配值
UNMODIFIABLE_REFERENCE_LIST.add("Apple");
UNMODIFIABLE_REFERENCE_LIST.add("Banana");
System.out.println("final List 的内容可以修改: " + UNMODIFIABLE_REFERENCE_LIST);
// UNMODIFIABLE_REFERENCE_LIST = new ArrayList<>(); // 编译错误!无法为最终变量分配新引用
}
publicstaticvoidmain(String[] args) {
FinalKeywordDemodemo=newFinalKeywordDemo();
System.out.println("--- 1. 展示 final 变量 ---");
demo.demonstrateFinalVariable();
System.out.println("\n--- 2. & 3. 展示 final 方法和类 ---");
Wizardstudent=newStudentWizard();
student.performBasicSpell(); // 可以调用普通方法
student.performSealedSpell(); // 可以调用 final 方法
}
}
// 2. final 方法: 失传的咒语
classWizard {
publicvoidperformBasicSpell() {
System.out.println("Wizard: 念出基础咒语 'Lumos'!");
}
// 这个方法被 final 修饰,意味着它的实现是最终版本,不希望任何子类修改它。
publicfinalvoidperformSealedSpell() {
System.out.println("Wizard: 念出失传的终极咒语 'Expecto Patronum'!");
}
}
classStudentWizardextendsWizard {
// 子类可以重写父类的普通方法
@Override
publicvoidperformBasicSpell() {
System.out.println("StudentWizard: 我把基础咒语改得更酷 'Lumos MAXIMA'!");
}
// 下面的代码会产生编译错误,因为子类不能重写父类的 final 方法
/*
@Override
public final void performSealedSpell() {
System.out.println("StudentWizard: 我想偷偷修改终极咒语...");
}
*/
}
// 3. final 类: 终极的奥义
// 这个类被 final 修饰,意味着它的设计已经完美,不希望有任何后代(子类)。
// 比如 Java 中的 String, Integer 等都是 final 类。
finalclassArchmage {
privateStringname="Gandalf";
public String getName() {
return name;
}
}
// 下面的代码会产生编译错误,因为我们不能继承一个 final 类
/*
class YoungArchmage extends Archmage {
// 无法继承,也就无法扩展
}
*/