Java中基本类型字面量的常量折叠是javac在编译阶段将满足条件的常量表达式直接替换为结果字面量的静态优化,不生成运行时计算字节码。

Java 中基本类型字面量的常量折叠,是编译器(javac)在编译阶段对确定值的表达式直接计算并替换为最终字面量的过程。它不依赖运行时,也不生成任何字节码计算逻辑,纯粹是静态优化。
触发常量折叠的核心条件
只有当表达式满足以下全部要求时,javac 才会执行折叠:
- 所有操作数都是编译期已知的常量(如
10、3.14f、'A'、true,或final修饰且用字面量初始化的基本类型变量) - 表达式仅含简单运算符(
+ - * / % & | ^ << >> >>>、&& || !、?:等),不含方法调用、数组访问、对象字段读取等运行时行为 - 整个表达式属于“常量表达式”(Java 语言规范明确定义)
典型可折叠场景
int a = 2 + 3 * 4; // 编译后直接变成 int a = 14; final int x = 5; final int y = 10; int b = x + y << 1; // 折叠为 int b = 60; boolean flag = (1 == 1) && false; // 折叠为 boolean flag = false; char c = 'a' + 1; // 折叠为 char c = 'b';
这些语句在 .class 文件中不会出现加法、位移或逻辑运算指令,而是直接存储结果字面量。
不可折叠的常见情况
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 非
final变量参与:int i = 5; int j = i + 3;→ 运行时计算 - 含方法调用:
int k = Math.max(2, 3) + 1;→ 即使结果确定,也不折叠(因涉及符号解析与调用) - 含
null或引用类型:基本类型折叠不跨类型,String s = "a" + "b"是 String 折叠,和基本类型无关 - 溢出未报错但按规则计算:
byte b = 127 + 1;→ 编译失败(超出 byte 范围);而int i = 2147483647 + 1;会折叠为-2147483648(符合二进制溢出语义)
折叠后的实际影响
- 字节码更小、运行更快:无计算开销
-
final基本类型字段被内联:若public static final int MAX = 100 + 20;,调用方编译后直接写死120,哪怕你改了原值,不重编译调用方仍用旧值 -
switch表达式要求 case 值必须是常量,正是依赖这套折叠机制来校验合法性
这种机制不是 JVM 做的,而是 javac 在生成 .class 前就完成的纯文本/语法树级替换。

















