ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Java常量池与Integer整型数值缓存机制

Java常量池与Integer整型数值缓存机制 在Java日常开发中常量池和Integer整型缓存是极易踩坑的知识点。很多开发者经常遇到Integer 判断结果忽真忽假、字符串对象地址不一致等诡异问题本质都是对这两个机制理解不透彻。本文将详解Java常量池分类、底层原理、Integer缓存机制、源码解析、实战案例以及常见面试坑点看完彻底告别相关代码bug盲区。一、什么是Java常量池1.1 核心定义常量池是JVM为了节省内存、减少重复对象创建、提升程序性能专门开辟的一块内存区域用于存储代码中编译期确定的字面量、符号引用、常量引用等数据。简单来说重复使用的常量JVM不会重复创建直接复用池中已有对象。1.2 核心作用内存复用避免相同字符串、数值常量重复创建对象减少堆内存占用提升性能省去对象创建、销毁的开销提高代码执行效率统一管理集中管理编译期常量优化JVM内存结构二、Java常量池三大分类2.1 静态常量池Class文件常量池存在于.class文件中属于编译期产物。当我们写完Java代码编译生成class文件后文件内部会包含一个静态常量池存储字符串字面量、基本数据类型常量、类名、方法名、字段名、符号引用等所有编译期可确定的常量数据是class文件占用空间最大的模块之一。特点仅存在于文件中未加载到内存程序未运行。2.2 运行时常量池当JVM执行类加载过程时会将Class文件中的静态常量池数据加载到方法区元空间形成运行时常量池。特点运行时常驻内存具备动态性支持运行期间动态加入常量如String.intern()方法全局共享所有线程共享该常量池数据2.3 字符串常量池字符串常量池是JVM单独开辟的、专门用于存储字符串常量的内存区域是开发者接触最多的常量池。不同JDK版本内存位置变化JDK6及之前存放在永久代JDK7及之后移至堆内存核心优化永久代内存有限堆内存更大减少OOMJDK8永久代彻底废弃使用元空间字符串常量池仍在堆中核心规则当使用String s abc字面量创建字符串时JVM会先去字符串常量池检索存在该字符串直接返回池中对象地址不存在在池中创建该字符串对象再返回地址三、整型数值缓存Integer Cache机制3.1 什么是Integer缓存从JDK5开始Java为Integer包装类引入了静态缓存机制IntegerCache底层基于享元模式实现。JVM提前初始化并缓存一批常用Integer对象避免频繁创建小数值Integer对象大幅提升性能、节省内存。3.2 缓存范围默认缓存范围-128 ~ 127包含边界值为什么是这个范围开发者统计发现日常业务中90%以上的整型数值操作都集中在-128~127之间缓存该区间性价比最高兼顾内存占用和性能优化。3.3 支持缓存的包装类汇总并非所有包装类都有缓存仅有4种数值型包装类实现了缓存机制包装类默认缓存范围Byte-128 ~ 127全覆盖Short-128 ~ 127Integer-128 ~ 127Long-128 ~ 127Float、Double无缓存机制浮点数值不固定、离散度高无缓存意义四、实战代码案例案例1缓存区间内-128~127public class IntegerCacheTest { public static void main(String[] args) { Integer a 100; Integer b 100; System.out.println(a b); // true复用缓存同一个对象 } }案例2超出缓存区间public class IntegerCacheTest { public static void main(String[] args) { Integer a 128; Integer b 128; System.out.println(a b); // false超出缓存新建两个不同对象 } }案例3new Integer 与 自动装箱对比public class IntegerCacheTest { public static void main(String[] args) { // 自动装箱走缓存 Integer a 40; // 手动new强制新建堆对象不走缓存 Integer b new Integer(40); System.out.println(a b); // false } }重点总结new Integer()无论数值是否在缓存区间都会强制创建新对象不使用缓存案例4int 与 Integer 对比public class IntegerCacheTest { public static void main(String[] args) { Integer a 128; int b 128; // Integer拆箱为int比较数值本身不比较地址 System.out.println(a b); // true } }核心规则基本类型与包装类比较时包装类会自动拆箱只对比数值不涉及缓存和地址。五、常量池 VS 整型缓存5.1 作用对象不同常量池作用于字符串、类、方法、静态常量等所有编译期常量整型缓存仅作用于Integer、Byte、Short、Long四种数值包装类5.2 实现机制不同常量池JVM底层内存机制编译期确定、运行时加载整型缓存Java代码层面的静态数组缓存基于享元模式类加载时初始化5.3 范围不同常量池所有字面量常量无数值范围限制整型缓存固定 -128~127可自定义上限
返回列表