当前位置: 首页 > news >正文

Java基础(十一):关键字final详解

Java基础系列文章

Java基础(一):初识Java——发展历程、技术体系与JDK环境搭建

Java基础(二):八种基本数据类型详解

Java基础(三):逻辑运算符详解

Java基础(四):位运算符详解

Java基础(五):流程控制全解析——分支(if/switch)和循环(for/while)的深度指南

Java基础(六):数组全面解析

Java基础(七): 面向过程与面向对象、类与对象、成员变量与局部变量、值传递与引用传递、方法重载与方法重写

Java基础(八):封装、继承、多态与关键字this、super详解

Java基础(九):Object核心类深度剖析

Java基础(十):关键字static详解

Java基础(十一):关键字final详解

目录

  • 一、final概述
  • 二、final修饰变量
    • 1、final基本类型变量
    • 2、final引用类型变量
    • 3、final变量的初始化时机
  • 三、final修饰方法
  • 四、final修饰类
  • 五、final修饰参数
  • 六、final在并发编程中的应用

一、final概述

  • final是Java中的一个修饰符,可以用来修饰方法变量。它的核心含义是"不可改变的"
    • final变量:一旦初始化就不能重新赋值
    • final方法:不能被子类重写
    • final类:不能被继承

二、final修饰变量

1、final基本类型变量

  • 当final修饰基本类型变量时,该变量的值一旦被初始化后就不能再改变
final int MAX_VALUE = 100;
// MAX_VALUE = 200; // 编译错误,不能修改final变量的值

特点:

  • 必须在声明时或构造方法/静态块中初始化
  • 一旦赋值后不能再修改
  • 对于基本类型,值本身不可变

2、final引用类型变量

  • 当final修饰引用类型变量时,引用本身不可变(即不能指向其他对象),但对象的内容可以改变
final List<String> names = new ArrayList<>();
names.add("Alice"); // 允许,修改对象内容
// names = new ArrayList<>(); // 编译错误,不能改变引用

特点:

  • 引用不可变 ≠ 对象不可变
  • final只保证引用不变,不保证被引用对象的内容不变

3、final变量的初始化时机

  • 对于实例变量:可以在声明时构造代码块构造方法中初始化
  • 对于静态变量:可以在声明时静态初始化块中初始化
public class Example {// 实例变量final int instanceVar1 = 10; // 声明时初始化final int instanceVar2;final int instanceVar3;{instanceVar2 = 20; // 实例初始化块(构造代码块)初始化}Example() {instanceVar3 = 30; // 构造方法中初始化}// 静态变量static final int STATIC_VAR1 = 10; // 声明时初始化static final int STATIC_VAR2;static {STATIC_VAR2 = 20; // 静态初始化块中初始化}
}

三、final修饰方法

  • 当final修饰方法时,该方法不能被子类重写(override)
class Parent {public final void forbiddenMethod() {System.out.println("我不能被重写");}public void normalMethod() {System.out.println("我可以被重写");}
}class Child extends Parent {// @Override// public void forbiddenMethod() { } // 编译错误:不能重写final方法@Overridepublic void normalMethod() {System.out.println("父类方法被重写了");}
}

设计考虑:

  • 防止子类修改关键方法​:确保方法的行为不会被子类改变
    • 常将框架中的关键方法声明为final
    • 当不希望子类改变特定行为时使用
  • JVM可以对final方法进行内联优化:直接将方法体插入调用处,减少方法调用的开销

四、final修饰类

  • 当final修饰类时,该类不能被继承
final class StringUtils {public static boolean isEmpty(String str) {return str == null || str.trim().isEmpty();}
}// class ExtendedUtils extends StringUtils { } // 编译错误:不能继承final类

常见的final类:

  • String
  • Integer
  • Double
  • Math
  • System

设计考虑:

  1. 不可变类​:如String类,确保对象状态不会被改变
  2. 安全性​:防止通过继承破坏类的安全性或不变性
  3. 设计意图​:明确表示该类不应有子类
  4. 工具类​:如Math,只包含静态方法,不需要实例化或继承

五、final修饰参数

public void process(final int param1, final List<String> param2) {// param1 = 10; // 编译错误// param2 = new ArrayList<>(); // 编译错误param2.add("value"); // 允许,修改对象内容
}

设计考虑:

  1. 防止方法内部意外修改参数引用
  2. 提高代码可读性,明确参数不应被重新赋值

六、final在并发编程中的应用

  • final字段在并发编程中非常重要,因为JVM保证final字段的初始化安全
class SafePublication {final int safeValue;int unsafeValue;public SafePublication(int value) {this.safeValue = value;    // 正确初始化this.unsafeValue = value;  // 可能发生重排序// 在构造函数返回后,safeValue对所有线程立即可见}public int getSafeValue() {return safeValue; // 总是能看到正确初始化的值}public int getUnsafeValue() {return unsafeValue; // 可能看到默认值0}
}

Java内存模型对final字段有特殊规定:

  • 在构造函数中对final字段的写入,与随后将被构造对象的引用赋值给一个引用变量,这两个操作不能重排序
  • 初次读包含final字段的对象的引用,与随后初次读这个final字段,这两个操作不能重排序

这意味着​:正确构造的对象的final字段,对于所有线程都是可见的,无需额外的同步措施


文章转载自:

http://cvRaMYAT.dmcxh.cn
http://fR7oDiww.dmcxh.cn
http://TTMjTiJ3.dmcxh.cn
http://i6Y5lqM4.dmcxh.cn
http://8fN07Uh7.dmcxh.cn
http://xwtuaxYn.dmcxh.cn
http://18SgN6PO.dmcxh.cn
http://t9yn82zK.dmcxh.cn
http://kPrUNOS1.dmcxh.cn
http://rHFEt018.dmcxh.cn
http://iM7V6PPe.dmcxh.cn
http://hQ7mmz0u.dmcxh.cn
http://Bnay3qgb.dmcxh.cn
http://9IG7m1Et.dmcxh.cn
http://THb3aUX0.dmcxh.cn
http://R4GqiqVJ.dmcxh.cn
http://4Wdn6h0o.dmcxh.cn
http://O76JD9cm.dmcxh.cn
http://IBGEjVDt.dmcxh.cn
http://ZJbwVOo5.dmcxh.cn
http://Iv6F5Mt2.dmcxh.cn
http://QwUtQUG4.dmcxh.cn
http://q4KsT6lM.dmcxh.cn
http://sVYawCvy.dmcxh.cn
http://qI5I8aMT.dmcxh.cn
http://Sa8IBGJn.dmcxh.cn
http://JXbAHuvS.dmcxh.cn
http://QYckCQdk.dmcxh.cn
http://75iEgvMh.dmcxh.cn
http://9XBzZkV2.dmcxh.cn
http://www.dtcms.com/a/373077.html

相关文章:

  • Java全栈开发面试实录:从基础到微服务的实战经验分享
  • Matlab机器人工具箱使用1 简单的描述类函数
  • 自动捕鱼器设计cad+设计说明书+三维图
  • 深入理解 MyBatis-Plus 的 `ServiceImpl`
  • 软件可靠性定量核心指标与关系深入解析
  • Android音频学习(十七)——音频数据流转
  • 如何一次性将多个PPT幻灯片批量转换成PDF文档
  • Vue响应式底层原理:深入解析依赖追踪机制
  • 抖音批量上传视频怎么弄?抖音矩阵账号管理的专业指南
  • 数学知识--行向量与矩阵相乘,和矩阵与行向量相乘的区别
  • 【硬件-笔试面试题-70】硬件/电子工程师,笔试面试题(知识点:过压保护电路)
  • PostgreSQL打印实时查询语句(监控PostgreSQL监控)(未成功)
  • “代练护航”小程序API源码搭建:高并发接单系统的技术突破与实战,多端适配与跨平台开发 如何覆盖微信、H5、APP全场景?
  • 从航空FACE的一个落地方案漫谈汽车HPC软件架构的思维转变(1/3)FACE基础概念与落地案例
  • Docker多共享网络配置策略(Docker多网络、Docker networks、Docker Compose网络、Docker网络、Docker共享网络)
  • Terraform 从入门到实战:历史、原理、功能与阿里云/Azure 上手指南
  • 阿里云国际代理:稳定、高效、便捷的数据库服务-云数据库RDS
  • Django中的软删除
  • PyCharm旧版本下载地址
  • 华为USG6000v2 NAT模式下IPSEC IKE V1 实验
  • 深入实践G1垃圾收集器调优:Java应用性能优化实战指南
  • sqlite3的使用
  • LeetCode Hot 100 Python (81~90)
  • LeetCode 面试经典 150 题:删除有序数组中的重复项(双指针思想解法详解)
  • apifox的post的表单提交的gbk的解决方案
  • leetcode算法刷题的第二十九天
  • 绿联科技全球化突围:业财一体化如何打通全球电商全链路数字化
  • golang-gin包
  • SpringAI调用MCP服务的实现思路
  • react16到react19更新及底层实现是什么以及区别