Java初学者入门final关键字:从懵懂到清晰的学习笔记
作为一名刚接触Java不久的初学者,最近在学习关键字的时候,被final搞得有点晕——一会儿修饰类,一会儿修饰方法,还有变量,不同场景下的规则好像还不一样。直到跟着代码敲了几遍,又反复琢磨了文档里的细节,才慢慢理清了思路。今天就以初学者的视角,分享一下我对final关键字的学习心得,希望能帮到和我一样刚开始摸索的小伙伴~
一、先搞懂:final到底是什么?
文档里说final是"最终的"意思,光看字面有点抽象,结合代码实践后我才明白:final本质是给Java中的元素加了"不可变"的限制,具体限制啥,取决于它修饰的是类、方法还是变量。
简单总结就是:final就像一个"保护锁",但锁的东西不一样——锁类就不让它被继承,锁方法就不让它被重写,锁变量就不让它被二次赋值。
二、final的三大应用场景
1. 修饰类:"我就是我,不能有子类"
当final修饰类时,这个类就成了"最终类",核心规则是不能被继承。
final class A {
}
// class B extends A {} // 报错!final类不能被继承
刚开始我没懂为啥要限制类不能被继承,后来查了下才知道,这是为了保护类的完整性。比如Java里的String类就是final的,这样就避免了有人通过继承修改String的核心逻辑,保证了字符串操作的安全性。
2. 修饰方法:"我的逻辑,不能被改写"
final修饰方法时,这个方法就是"最终方法",规则是子类不能重写它。
class C {
public final void show() {
System.out.println("show方法被执行");
}
}
class D extends C {
// @Override 这里会报错!final方法不能重写
// public void show() {
// System.out.println("想改写show方法");
// }
}
这一点我深有体会——刚开始学继承和重写,总想着子类能改父类的方法,后来才知道,有些核心方法(比如父类的工具方法)如果被随意改写,可能会导致程序出问题。final就像给方法加了"保护罩",确保它的逻辑不变。
3. 修饰变量:"一次赋值,终身不变"
这是final最常用也最容易踩坑的场景!核心规则是变量有且仅能被赋值一次,但这里要分两种情况——基本类型和引用类型,差别很大!
(1)修饰基本类型变量:值不能改
比如文档里的PI和a:
final double PI = 3.14;
// PI = 3.16; // 报错!第二次赋值不允许
final int a = 10;
// a = 20; // 同样报错
这个很好理解,基本类型变量存的就是具体的值,final直接锁住这个值,不能修改。
(2)修饰引用类型变量:地址不能改,但内容能改!
这是我踩过的第一个大坑!刚开始以为final修饰对象,对象里的内容也不能改,直到跑了数组的例子:
final int[] arr = {1, 2, 3};
// arr = new int[]{2, 3, 4}; // 报错!地址不能改
arr[0] = 2; // 不报错!数组内容可以改
System.out.println(arr[0]); // 输出2
原来引用类型变量存的是对象的"地址",final只锁住这个地址(不让变量指向新的对象),但地址指向的对象内部内容,是可以随便改的!比如上面的数组,我不能让arr重新指向一个新数组,但可以修改数组里的元素。
还有方法参数里的final,比如buy方法:
public static void buy(final double z) {
// z = 0.1; // 报错!方法参数被final修饰,不能二次赋值
System.out.println(z);
}
这说明不管是局部变量、成员变量还是方法参数,只要被final修饰,都遵循"一次赋值"规则。
三、进阶:static final 常量——系统配置的"最佳拍档"
文档里提到,static final修饰的成员变量叫"常量",这是final最实用的场景之一,用来记录系统配置信息。
1. 常量的定义和命名规范
常量的定义格式是:public static final 数据类型 常量名 = 字面量;
- 命名规范:全部大写,多个单词用下划线连接(比如
SCHOOL_NAME、SYSTEM_NAME) - 例子:
// FinalDemo1.java 里的常量
public static final String SCHOOL_NAME = "东华理工大学";
// Constant.java 里的常量
public static final String SYSTEM_NAME = "AI智能家居系统";
2. 为什么要用常量?—— 可读性+维护性+性能
刚开始我觉得直接写字面量也一样,比如直接写"东华理工大学",后来才发现差距太大了:
- 可读性:
SCHOOL_NAME一看就知道是"学校名称",比一堆字符串直观多了; - 维护性:如果学校名称要改,只需要改常量定义的地方,不用在代码里到处找"东华理工大学"替换;
- 性能:编译时,所有用到常量的地方都会被直接替换成字面量,比如
System.out.println(Constant.SYSTEM_NAME)会变成System.out.println("AI智能家居系统"),和直接写字面量性能一样好。
就像FinalDemo2里的用法,多次打印SYSTEM_NAME,不管用多少次,修改起来都只需要改Constant类里的定义,太方便了!
// FinalDemo2.java
package com.wmh.finaldemo;
public class FinalDemo2 {
public static void main(String[] args) {
System.out.println(Constant.SYSTEM_NAME);
System.out.println(Constant.SYSTEM_NAME);
System.out.println(Constant.SYSTEM_NAME);
// ... 多次调用
}
}
四、初学者必避的2个坑
- 混淆引用类型和基本类型:以为
final修饰对象,对象内容就不能改(其实是地址不能改); - 常量命名不规范:刚开始我习惯用驼峰命名(比如
schoolName),后来才知道常量必须全大写+下划线,这是Java的编码规范,能让别人一眼认出是常量; - final修饰实例变量没意义:文档里提到
public final String name = "张三"这种写法,实例变量每个对象都有一份,用final修饰虽然能保证一次赋值,但不如常量(static final)实用,一般不用。
五、总结:final的核心价值
学完final后,我觉得它的核心作用就是"保证不变性":
- 修饰类/方法:保证代码逻辑不被篡改(继承/重写层面);
- 修饰变量/常量:保证数据不被二次赋值,尤其是常量,在项目中用来存配置信息,能大大提升代码的可维护性。
作为初学者,我最深的体会是:final的规则不算复杂,但一定要亲手敲代码测试!比如final修饰数组的例子,光看文档我肯定不懂,跑一遍代码报错了,才真正理解"地址不能改,内容能改"的区别。
希望这篇笔记能帮到和我一样刚开始学Java的小伙伴,如果你也有学习final时的困惑,欢迎在评论区交流呀~ 一起加油,从懵懂到清晰!
"在Java的世界里,final不是终点,而是起点。它不阻止你创新,而是确保你创新的基石稳固。"