Java中常量的内存空间究竟是在编译期还是运行期分配?
Java编译期常量的内存分配时机
针对你提出的public static final int NUMBER = 5这类常量,内存分配的情况可以分两种场景来看:
1. 常规使用场景:无运行期内存分配
这种直接用字面量赋值的static final基本类型/字符串属于编译期常量,编译器会执行「常量折叠」优化:
- 编译阶段,所有引用
NUMBER的代码都会被直接替换为数值5,生成的字节码里不会保留对NUMBER这个常量名的符号引用。 - 这意味着运行时JVM根本不需要为
NUMBER这个变量分配内存空间——因为代码里已经没有这个变量的影子了,直接用的是硬编码的数值。 - 甚至极端情况:如果其他类只引用了这个常量,而没有触发原类的加载逻辑(比如没创建原类实例、没访问原类的其他静态成员),原类都不会被JVM加载。
2. 类被主动加载时:元数据层面的存储
如果因为其他操作(比如创建原类的实例、访问原类的非final静态变量)触发了原类的加载流程,JVM会把这个常量的信息(名称、值等)存入运行时常量池(属于元空间的一部分)。
- 但这并不是为
NUMBER这个变量分配可直接访问的内存空间,只是存储了常量的元数据——因为代码里已经没有对这个变量的引用了,这个元数据更多是供反射、类信息查询等场景使用。
和普通类变量的核心区别
- 普通
static类变量(非final)会在类加载的「初始化」阶段在元空间分配内存,运行时可以修改其值; - 而编译期常量在编译后就失去了“变量”的特性,变成了硬编码的数值,不存在运行期的变量内存分配。
内容的提问来源于stack exchange,提问作者elvis
相关产品推荐
相关产品推荐

