final修饰了List,为什么我还能add元素?

发布于:2025-07-09 ⋅ 阅读:(22) ⋅ 点赞:(0)

图片

故事场景: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 {
    // 无法继承,也就无法扩展
}
*/


网站公告

今日签到

点亮在社区的每一天
去签到