Java JVM是否会像复用String一样复用自定义类的相同不可变实例?
首先我们先明确:JVM针对String的重复实例复用(也就是字符串驻留、常量池机制)是专门为这个核心基础类做的定制化优化,默认不会对自定义类做类似的自动实例复用处理,针对你提出的三个问题具体解答如下:
首先给出你提到的类代码参考:
final public class ImmutReuseTest { final public int num; final public SomeImmutableThing thing; public ImmutReuseTest(final int num, final SomeImmutableThing thing) { this.num = num; this.thing = thing; } } final public class SomeImmutableThing { final public int nomm; final public String text; public SomeImmutableThing(final int nomm, final String text) { this.nomm = nomm; this.text = text; } }
- 问题1答案:不会
String的实例复用依赖专门的字符串常量池逻辑,普通自定义不可变类没有这套默认自动去重机制。只要你主动调用构造方法创建新实例,哪怕所有字段的取值完全相等,JVM也会为每个new操作分配独立的堆内存,不会自动复用已有同值实例。如果需要复用你得自己手动实现享元模式,通过缓存池来管理实例的创建和返回。 - 问题2答案:不会
哪怕所有ImmutReuseTest实例内部的SomeImmutableThing字段都指向同一个实例,JVM也不会自动对ImmutReuseTest本身做实例复用。唯一可能和“消除重复创建”沾边的优化是JIT的逃逸分析标量替换:如果某个ImmutReuseTest实例的作用域完全没逃出当前方法,JIT可能会直接把实例拆解成独立的字段放到栈上存储,完全跳过堆上的对象创建流程,这不属于实例复用,是直接消除了对象创建。 - 问题3答案:不会
不管类是严格不可变还是有效final,JVM都不会默认对自定义类做自动实例复用。尤其是类内部存在可变字段的场景,哪怕你实际上不会修改这些字段,JVM也不可能主动做复用——万一后续字段被修改,复用实例会直接导致逻辑错误,风险完全不可控。这类场景下的复用只能由开发者自己保证实例的不可变性,手动实现缓存逻辑来完成。
内容的提问来源于stack exchange,提问作者Dreamspace President
相关产品推荐
相关产品推荐

