【Java】Java核心关键字:final、static、volatile、synchronized、transient(附《面试高频考点》)

简介: Java五大核心关键字精讲:final(不可变性)、static(类级共享)、volatile(可见性+禁重排)、synchronized(原子性/可见性/有序性)和 transient(非序列化)。涵盖原理、场景、多线程与序列化特性,直击面试高频考点。

Java 5大核心关键字


5大关键字——对比表

关键字 核心作用 多线程相关 序列化相关 主要场景
final 限制可变性(类、方法、变量) 间接保证可见性 常量、不可变类、安全设计
static 类成员共享(变量、方法等) 工具类、全局变量、类初始化
volatile 可见性、禁止重排序 状态标记、DCL 单例
synchronized 原子性、可见性、有序性 临界区同步、复合操作保护
transient 跳过变量序列化 敏感数据、临时缓存、不可序列化字段

1. final 关键字

定义

final 用于限制类、方法或变量的可变性,表示“最终的、不可改变的”。

作用

  • 修饰类:该类不可被继承(如 StringMath 类)。
  • 修饰方法:该方法不可被子类重写
  • 修饰变量
    • 基本类型变量:值不可修改
    • 引用类型变量:指向的对象地址不可修改(但对象内部状态可改变)。

使用场景

  • 定义常量(如 public static final double PI = 3.14)。
  • 防止类被继承或方法被重写(确保设计安全性)。
  • 方法参数使用 final,避免参数被意外修改。

实现原理

  • 编译期:final 变量会被编译器优化为“常量折叠”(直接替换值)。
  • 运行期:JVM 会禁止对 final 变量的二次赋值,并通过内存屏障确保 final 变量在构造函数中初始化后才被其他线程可见。

注意事项

  • final 变量必须显式初始化(声明时、构造器或代码块中),否则编译报错。
  • 引用类型的 final 仅限制引用地址,不限制对象内部状态(需结合其他机制保证不可变)。

2. static 关键字

定义

static 表示“静态的”,用于修饰类成员(变量、方法、代码块、内部类),使其属于类而非实例

作用

  • 修饰变量:静态变量(类变量)被所有实例共享,内存中仅存一份。
  • 修饰方法:静态方法可直接通过类名调用,无需创建实例
  • 修饰代码块:静态代码块在类加载时执行一次,用于初始化类资源。
  • 修饰内部类:静态内部类不依赖外部类实例,可直接创建。

使用场景

  • 定义全局共享变量(如计数器、配置常量)。
  • 工具类方法(如 Math.random()Collections.sort())。
  • 类初始化操作(如加载驱动、读取配置文件)。

实现原理

  • 静态变量存储在方法区(JDK 8 后为元空间),随类加载而创建,类卸载而销毁。
  • 静态方法在字节码层面通过 invokestatic 指令调用,不依赖 this 引用。

注意事项

  • 静态方法不能直接访问实例变量或实例方法(无 this 引用),但实例方法可访问静态成员。
  • 静态代码块仅执行一次,且按定义顺序执行。

3. volatile 关键字

定义

volatile 是多线程同步关键字,用于保证变量的可见性禁止指令重排序,但不保证原子性

作用

  • 可见性:一个线程修改了 volatile 变量,其他线程能立即看到最新值(避免变量被缓存在寄存器或本地内存中)。
  • 禁止重排序:通过内存屏障禁止编译器和 CPU 对指令进行重排序(确保执行顺序与代码逻辑一致)。

使用场景

  • 状态标记(如 boolean isRunning = true;,用于线程停止标记)。
  • 双重检查锁定(DCL)实现单例模式(防止指令重排序导致的空指针异常)。

实现原理

  • 可见性:通过缓存一致性协议(如 MESI),变量修改后立即刷新到主内存,其他线程嗅探到变化后失效本地缓存。
  • 禁止重排序:在变量读写前后插入内存屏障(如 LoadLoad、StoreStore 屏障),限制指令重排范围。

注意事项

  • volatile 不能替代 synchronized,因为它不保证原子性(如 count++ 这类复合操作仍需锁)。
  • 仅适用于“一个线程写、多个线程读”的场景,多线程写需额外同步。

4. synchronized 关键字

定义

synchronized 是 Java 中最常用的同步机制,用于保证多线程环境下的原子性、可见性和有序性

作用

  • 原子性:确保被修饰的方法或代码块同一时间只能被一个线程执行
  • 可见性:线程释放锁前,会将变量修改刷新到主内存;获取锁后,会从主内存读取最新值。
  • 有序性:通过锁的“排他性”保证代码执行的有序性(禁止临界区内的重排序)。

使用场景

  • 保护共享变量的复合操作(如 count++、转账操作)。
  • 同步方法或代码块,确保多线程安全访问临界资源。

实现原理

  • 对象头与 Mark Word:每个对象的对象头中存储锁状态(无锁、偏向锁、轻量级锁、重量级锁)。
  • monitorenter/monitorexit 指令:编译后,同步代码块会插入这两个指令,用于获取和释放对象的监视器(Monitor)。
  • 锁升级机制:JDK 6 后引入锁升级(偏向锁→轻量级锁→重量级锁),减少锁竞争带来的性能开销。

注意事项

  • 锁的是对象而非代码:实例方法锁 this,静态方法锁类对象(Class),代码块锁指定对象。
  • 避免锁粒度太大(影响性能)或太小(导致线程安全问题)。
  • 支持可重入性:同一个线程可多次获取同一把锁(避免死锁)。

5. transient 关键字

定义

transient 用于修饰变量,表示该变量不需要被序列化(Java 序列化机制会忽略 transient 变量)。

作用

  • 跳过敏感数据或临时数据的序列化(如密码、缓存计算结果)。
  • 减少序列化后的文件大小,提升性能。

使用场景

  • 缓存字段(如临时计算的中间结果,反序列化后可重新计算)。
  • 敏感信息(如用户密码,避免序列化后泄露)。
  • 不可序列化的字段(如 ThreadInputStream,需标记为 transient 避免报错)。

实现原理

  • Java 序列化时,ObjectOutputStream 会检查字段是否被 transient 修饰,若是则跳过该字段的写入。
  • 反序列化时,transient 变量会被初始化为默认值(引用类型为 null,基本类型为 0/false)。

注意事项

  • static 变量天然不参与序列化(属于类状态,非对象状态),无需加 transient
  • 若需手动控制 transient 变量的序列化,可实现 Externalizable 接口,重写 writeExternal()readExternal() 方法。

面试高频考点


一、单个关键字 分阶高频考点

1. final 关键字

【基础必考题(初中级100%覆盖)】

  1. 简述final关键字的核心作用,分别说明修饰类、方法、变量时的语义
  2. final修饰基本类型变量和引用类型变量的核心区别
  3. 为什么String类要被定义为final?
  4. final和abstract能否一起使用?为什么?
  5. 匿名内部类访问外部局部变量,为什么变量必须加final?JDK8后为什么不用显式声明了?

【进阶深挖题(中高级高频)】

  1. final如何保证多线程下的可见性?和volatile的可见性实现有什么区别?
  2. 什么是不可变类?如何基于final实现一个线程安全的不可变类?
  3. final的编译期优化(常量折叠)是什么?有哪些限制条件?
  4. final方法能不能被重载?和重写的核心区别是什么?
  5. JVM对final字段有哪些重排序规则?为什么要禁止final字段在构造函数初始化完成前发生对象逸出?

【高频坑点题】

  1. final修饰的集合对象,能不能添加/删除元素?为什么?
  2. 被final修饰的变量,一定是编译期常量吗?
  3. final修饰的实例方法,子类中能不能定义同名同参数的方法?

2. static 关键字

【基础必考题(初中级100%覆盖)】

  1. 简述static关键字的核心作用,分别说明修饰变量、方法、代码块、内部类的语义
  2. 静态变量和实例变量的核心区别?存储位置有什么不同?
  3. 静态方法能不能直接访问实例成员(变量/方法)?为什么?
  4. 静态代码块、构造代码块、构造方法的执行顺序是什么?父子类场景下的完整执行顺序?
  5. 静态内部类和非静态内部类的核心区别?

【进阶深挖题(中高级高频)】

  1. static成员的生命周期?类加载的哪个阶段会初始化静态变量和静态代码块?
  2. 静态方法能不能被重写?为什么?(结合多态动态绑定机制说明)
  3. 静态变量存在线程安全问题吗?什么场景下会触发?
  4. static和final组合使用的核心场景?public static final 定义常量的规范与注意事项?
  5. 类加载过程中,静态变量的初始化和静态代码块的执行顺序由什么决定?

【高频坑点题】

  1. 能不能在构造方法中给静态变量赋值?
  2. static代码块能不能捕获异常?
  3. 静态方法用synchronized修饰时,锁的对象是什么?和实例同步方法有什么区别?

3. volatile 关键字

【基础必考题(并发面试100%覆盖)】

  1. volatile关键字的两个核心作用是什么?
  2. 什么是指令重排序?volatile如何禁止指令重排序?
  3. 什么是内存可见性?volatile如何保证变量的可见性?
  4. volatile能不能保证原子性?为什么?举一个典型反例
  5. volatile和synchronized的核心区别?

【进阶深挖题(中高级/大厂必问)】

  1. 双重检查锁定(DCL)实现单例模式,为什么必须加volatile?
  2. volatile的内存屏障机制是什么?读/写操作前后分别插入什么类型的内存屏障?
  3. volatile对应的happens-before规则是什么?
  4. MESI缓存一致性协议和volatile的关系?
  5. volatile在JDK源码中的经典应用?(AtomicInteger、ConcurrentHashMap、ThreadPoolExecutor等)
  6. 什么是伪共享?volatile和伪共享的关系?如何解决伪共享问题?

【高频坑点题】

  1. 加了volatile的count++操作,是线程安全的吗?
  2. volatile修饰long/double类型变量,在32位JVM上读写是原子的吗?
  3. volatile和final能不能一起使用?

4. synchronized 关键字

【基础必考题(并发面试100%覆盖)】

  1. synchronized的三种使用方式?分别锁定的是什么对象?
  2. synchronized如何保证原子性、可见性、有序性?
  3. 什么是锁的可重入性?synchronized是可重入锁吗?底层如何实现?
  4. 一个线程调用对象的synchronized实例方法时,另一个线程能否调用同一个对象的非synchronized方法?
  5. synchronized和Lock接口的核心区别?

【进阶深挖题(中高级/大厂必问)】

  1. 详细说明synchronized的锁升级全流程(偏向锁→轻量级锁→重量级锁),包括每种锁的适用场景、升级触发条件、优缺点
  2. Java对象头的结构是什么?Mark Word在不同锁状态下分别存储什么内容?
  3. synchronized的底层实现原理?monitorenter/monitorexit指令、Monitor监视器机制
  4. JDK6对synchronized做了哪些性能优化?(自适应自旋、锁消除、锁粗化、偏向锁、轻量级锁)
  5. 重量级锁的底层实现?为什么说重量级锁的性能开销大?
  6. synchronized的锁释放时机有哪些?方法抛出异常时会不会释放锁?

【高频坑点题】

  1. 两个线程分别调用同一个类的synchronized静态方法和synchronized实例方法,会不会发生互斥?为什么?
  2. 父类synchronized修饰的方法,子类重写后默认还是同步方法吗?
  3. 自旋锁一定比重量级锁效率高吗?
  4. 能不能在try块中加synchronized,在finally里手动释放锁?

5. transient 关键字

【基础必考题(初中级高频)】

  1. transient关键字的核心作用是什么?
  2. 哪些场景下需要使用transient关键字?
  3. 被transient修饰的变量,反序列化后的默认值是什么?

【进阶深挖题(中高频)】

  1. 被transient修饰的变量,真的完全不能被序列化吗?有没有例外情况?
  2. ArrayList的elementData数组为什么要被transient修饰?
  3. static变量会被序列化吗?加了transient的static变量呢?
  4. 自定义序列化的方式有哪些?如何手动控制transient变量的序列化与反序列化?
  5. ExternalizableSerializable接口的区别?对transient关键字的处理有什么不同?

【高频坑点题】

  1. transient修饰的final变量,能不能被序列化?
  2. 静态内部类的transient变量,序列化有什么限制?

二、跨关键字 综合对比高频题(面试必问拉分题)

  1. 从原子性、可见性、有序性、性能、使用场景等维度,对比volatile和synchronized的核心区别
  2. final和static的核心区别?二者组合使用的场景与注意事项
  3. synchronized和volatile的有序性保证,底层实现有什么区别?
  4. transient和static的核心区别?为什么static变量天然不参与序列化?
  5. final、volatile、synchronized在保证多线程可见性上的区别与实现原理?
  6. 同时使用static和synchronized,和普通实例synchronized方法有什么本质区别?

三、场景手撕与实战题(面试高频手写+原理讲解)

  1. 手写双重检查锁定(DCL)单例模式,解释每一步的作用,尤其是volatile的核心作用
  2. 基于final关键字,手写一个线程安全的不可变类
  3. 写出父子类场景下,静态代码块、构造代码块、构造方法的完整执行顺序代码,并解释执行逻辑
  4. 手写自定义序列化示例,手动控制transient变量的序列化与反序列化
  5. 写出volatile的正确使用场景示例、错误使用场景示例,并解释背后的原因

四、大厂加分深挖题(资深开发/高频)

  1. 详细讲解volatile的内存屏障在x86架构下的具体实现
  2. synchronized的锁撤销、锁降级机制的适用场景与实现原理
  3. JSR-133内存模型中,对final字段的重排序规则做了哪些规范?
  4. 为什么说synchronized是不公平锁?有没有办法实现公平的synchronized?
  5. JDK8前后,静态变量的存储位置发生了什么变化?对static关键字的使用有什么影响?
  6. 序列化机制中,transient关键字和serialVersionUID有什么关联?
相关文章
|
4月前
|
存储 缓存 安全
【HashMap】HashMap 系统性知识体系全解(附《HashMap 面试八股文精简版》)
本文以JDK8为核心,对比JDK7差异,从基础认知、底层结构(数组+链表+红黑树)、哈希函数、扩容机制、线程安全、最佳实践及面试考点七大维度,系统解析HashMap原理与应用,助你构建完整知识体系。
|
27天前
|
设计模式 Java 调度
【Java并发编程】锁机制:AQS抽象队列同步器:核心原理、CLH队列、独占/共享模式、基于AQS实现的组件(CountDownLatch、CyclicBarrier等)(附《思维导图》+《面试高频考点清单》)
AQS(AbstractQueuedSynchronizer)是Java并发包(JUC)的基石框架,基于volatile state状态变量与CLH双向等待队列,通过模板方法模式支持独占/共享同步语义,为ReentrantLock、Semaphore、CountDownLatch等核心组件提供统一底层实现。
|
2月前
|
存储 监控 NoSQL
【Redis】Redis 高可用:主从复制、哨兵Sentinel、Redis Cluster分片原理、哈希槽、故障转移、数据倾斜优化
本文系统梳理Redis高可用演进路径(单机→主从→哨兵→Cluster),深入解析三大方案原理:主从复制的PSYNC增量同步机制、哨兵的双层下线判定与Raft选举、Cluster的哈希槽分片与Gossip通信。涵盖故障自愈、数据一致、水平扩展等核心目标,及脑裂防控、数据倾斜治理等生产级最佳实践。
|
4月前
|
SQL Java 数据库
【MyBatis-Plus】Spring Boot + MyBatis-Plus 进行各种数据库操作(附完整 CRUD 项目代码示例)
本文详解Spring Boot集成MyBatis-Plus全流程:从依赖引入、数据源配置、Mapper扫描到分页/乐观锁/逻辑删除等核心插件配置;涵盖BaseMapper基础CRUD、LambdaQueryWrapper条件查询、Service层封装、自定义XML多表关联及批量优化实践,附完整可运行示例。
1009 1
|
3月前
|
消息中间件 运维 监控
【消息队列MQ】消息积压:原因、紧急处理方案
本文系统解析消息积压问题,涵盖定义影响、全链路根因(90%源于消费者侧)、紧急SOP(止损→定位→消化→恢复)、长效预防、主流MQ(Kafka/RocketMQ/RabbitMQ)差异化处理、常见误区及复盘闭环七大维度,构建覆盖故障应急到架构治理的完整知识体系。
|
3月前
|
存储 运维 算法
【分布式】分布式系统核心知识体系:CAP定理、BASE理论与核心挑战
本文构建“理论边界→工程落地→现实挑战”闭环知识体系,深度解析CAP定理(分布式不可突破的不可能三角)、BASE理论(AP场景下的柔性实践)及八大类核心工程挑战,厘清误区,建立系统化认知框架。
|
3月前
|
存储 安全 前端开发
【微服务】微服务安全:OAuth2.0、JWT、SSO单点登录、RBAC权限模型
本文系统梳理微服务安全四大核心:OAuth2.0(授权协议)、JWT(无状态凭证)、SSO(统一认证)、RBAC(权限模型),从边界定位、原理剖析、落地规范到协同架构四维展开,厘清分层职责与互补关系,提供企业级可落地的安全闭环实践指南。
|
Dart 前端开发 JavaScript
springboot自动配置原理
Spring Boot 自动配置原理:通过 `@EnableAutoConfiguration` 开启自动配置,扫描 `META-INF/spring.factories` 下的配置类,省去手动编写配置文件。使用 `@ConditionalXXX` 注解判断配置类是否生效,导入对应的 starter 后自动配置生效。通过 `@EnableConfigurationProperties` 加载配置属性,默认值与配置文件中的值结合使用。总结来说,Spring Boot 通过这些机制简化了开发配置流程,提升了开发效率。
1013 17
springboot自动配置原理
|
存储 缓存 负载均衡
JVM(Java虚拟机)详解(JVM 内存模型、堆、GC、直接内存、性能调优)
JVM(Java虚拟机)详解(JVM 内存模型、堆、GC、直接内存、性能调优)
69858 9
JVM(Java虚拟机)详解(JVM 内存模型、堆、GC、直接内存、性能调优)