Java Integer 缓存特性(Integer最大/小值探究、整型的自动装箱)

简介: Java Integer 缓存特性(Integer最大/小值探究、整型的自动装箱)

问题引出


Integer最大/小值


java中Integer是有最大值和最小值的


最大值为


Integer.MAX_VALUE = 2147483647


最小值为


Integer.MIN_VALUE = -2147483648


注意:两个值并没有互为相反数



Integer.MAX_VALUE + 1 = Integer.MIN_VALUE


同理


Integer.MIN_VALUE - 1 = Integer.MAX_VALUE


Integer最大/小值案例


但是用到了这样的一个案例:


public static void test() {
    //true
    Integer a1 = 127, b1 = 127;
    System.out.println(a1 == b1);
    //false
    Integer a2 = new Integer(127);
    Integer b2 = new Integer(127);
    System.out.println(a2 == b2);
    //false
    Integer a3 = 128, b3 = 128;
    System.out.println(a3 == b3);
    //true
    Integer a4 = 128, b4 = 128;
    System.out.println(a4.equals(b4));
}
public static void main(String[] args) {
    test();
}


比较答案:


true
false
false
true


结果原因


  • 第一个使用"=="判断 Integer a1 = 127 和 Integer b1 = 127


相等原因:Integer的取值范围是-128~127


  • 第二个使用"=="判断Integer a2 = new Integer(127) 和 Integer b2 = new Integer(127)


不相等原因:装箱时,java为了提高效率,IntegerCache类中有一个数组将-128<=i<=127范围之内的数据打包成缓存里的Integer对象了,因此不用new,这个区间里的值用直接=赋值方法得到的变量地址就是同一个,而超出这个范围的数值就会new一个Integer对象出来


  • 第三个使用"=="判断Integer a3=128 和 Integer b3 = 128


不相等原因:因为Integer类型赋值范围在-128—127之间,超出这个范围的数值就会重新new一个Integer对象出来,直接用==去比较是比较a3和b3的地址,a3和b3的地址是不相等的


  • 第四个使用使用"=="equals()方法判断Integer a4=128 和 Integerb4 = 128


相等原因:使用equals()方法比较的是a4和b4的数值


注意点:"=="可以用于原始值进行比较,也可以用于对象进行比较,当用于对象与对象之间比较时,比较的不是对象代表的值,而是检查两个对象是否是同一对象,这个比较过程中没有自动装箱发生。进行对象值比较不应该使用”==“,而应该使用对象对应的equals方法。


小总结


JVM会自动维护八种基本类型的常量池,int常量池中初始化-128~127的范围,所以当为Integer i=127时,在自动装箱过程中是取自常量池中的数值,而当Integer i=128时,128不在常量池范围内,所以在自动装箱过程中需new 128,所以地址不一样。


上面就用到了Java自动装箱的概念,下面我们来深入了解一下:


Integer 自动装箱


IntegerCache缓存


Integer 缓存是 Java 5 中引入的一个有助于节省内存、提高性能的特性。


Integer中有个静态内部类IntegerCache,里面有个cache[],也就是Integer常量池,常量池的大小为一个字节(-128~127)。JDK源码如下(摘自JDK1.8源码):


    /**
    * Cache to support the object identity semantics of autoboxing for values between
    * -128 and 127 (inclusive) as required by JLS.
    *
    * The cache is initialized on first usage.  The size of the cache
    * may be controlled by the -XX:AutoBoxCacheMax=<size> option.
    * During VM initialization, java.lang.Integer.IntegerCache.high property
    * may be set and saved in the private system properties in the
    * sun.misc.VM class.
    */
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];
        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low));
            }
            high = h;
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }
        private IntegerCache() {}
    }


当创建Integer对象时,不使用new Integer(int i)语句,大小在-128~127之间,对象存放在Integer常量池中。


例如:Integer a = 10;


调用的是Integer.valueOf()方法,代码为:


public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}


这也是自动装箱的代码实现。


Java自动装箱


JAVA将基本类型自动转换为包装类的过程称为自动装箱(autoboxing)。


实际上在 Java 5 中引入这个特性的时候,范围是固定的 -128 至 +127。后来在Java 6 后,最大值映射到 java.lang.Integer.IntegerCache.high,可以使用 JVM 的启动参数设置最大值。(通过 JVM 的启动参数 -XX:AutoBoxCacheMax=size 修改)


缓存通过一个 for 循环实现。从小到大的创建尽可能多的整数并存储在一个名为 cache 的整数数组中。这个缓存会在 Integer 类第一次被使用的时候被初始化出来。以后,就可以使用缓存中包含的实例对象,而不是创建一个新的实例(在自动装箱的情况下)。


测试情况:


int i = 10;
int i1 = 10;
Integer in1 = 10;
Integer in2 = 10;
Integer in3 = new Integer(10);
Integer in4 = new Integer(10);
Integer in5 = 199;
Integer in6 = 199;
System.out.println(i == i1);    // true
System.out.println(i == in1);   // true
System.out.println(i == in2);   // true
System.out.println(i == in3);   // true
System.out.println(in1 == in2);   // true
System.out.println(in5 == in6);   // false
System.out.println(in1 == in3);   // false
System.out.println(in3 == in4);   // false


在 Boxing Conversion 部分的Java语言规范(JLS)规定如下:


如果一个变量 p 的值属于:-128至127之间的整数(§3.10.1),true 和 false的布尔值 (§3.10.3),’u0000′ 至 ‘u007f’ 之间的字符(§3.10.4)中时,将 p 包装成 a 和 b 两个对象时,可以直接使用 a == b 判断 a 和 b 的值是否相等。


所有整数类型的类都有类似的缓存机制:


  • 有 ByteCache 用于缓存 Byte 对象


  • 有 ShortCache 用于缓存 Short 对象


  • 有 LongCache 用于缓存 Long 对象


Byte,Short,Long 的缓存池范围默认都是: -128 到 127。可以看出,Byte的所有值都在缓存区中,用它生成的相同值对象都是相等的。


所有整型(Byte,Short,Long)的比较规律与Integer是一样的。


同时Character 对象也有CharacterCache 缓存 池,范围是 0 到 127。


除了 Integer 可以通过参数改变范围外,其它的都不行。


相关文章
|
5月前
|
Java API 数据处理
Java新特性:使用Stream API重构你的数据处理
Java新特性:使用Stream API重构你的数据处理
Java API 开发者
174 0
|
7月前
|
并行计算 Java API
Java List 集合结合 Java 17 新特性与现代开发实践的深度解析及实战指南 Java List 集合
本文深入解析Java 17中List集合的现代用法,结合函数式编程、Stream API、密封类、模式匹配等新特性,通过实操案例讲解数据处理、并行计算、响应式编程等场景下的高级应用,帮助开发者提升集合操作效率与代码质量。
343 1
|
7月前
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
833 1
|
7月前
|
缓存 安全 Java
Java 并发新特性实战教程之核心特性详解与项目实战
本教程深入解析Java 8至Java 19并发编程新特性,涵盖CompletableFuture异步编程、StampedLock读写锁、Flow API响应式流、VarHandle内存访问及结构化并发等核心技术。结合电商订单处理、缓存系统、实时数据流、高性能计数器与用户资料聚合等实战案例,帮助开发者高效构建高并发、低延迟、易维护的Java应用。适合中高级Java开发者提升并发编程能力。
291 0
|
7月前
|
安全 Java API
Java 17 及以上版本核心特性在现代开发实践中的深度应用与高效实践方法 Java 开发实践
本项目以“学生成绩管理系统”为例,深入实践Java 17+核心特性与现代开发技术。采用Spring Boot 3.1、WebFlux、R2DBC等构建响应式应用,结合Record类、模式匹配、Stream优化等新特性提升代码质量。涵盖容器化部署(Docker)、自动化测试、性能优化及安全加固,全面展示Java最新技术在实际项目中的应用,助力开发者掌握现代化Java开发方法。
338 1
|
7月前
|
IDE Java API
Java 17 新特性与微服务开发的实操指南
本内容涵盖Java 11至Java 17最新特性实战,包括var关键字、字符串增强、模块化系统、Stream API、异步编程、密封类等,并提供图书管理系统实战项目,帮助开发者掌握现代Java开发技巧与工具。
359 1
|
7月前
|
存储 缓存 人工智能
Java int和Integer的区别
本文介绍了Java中int与Integer的区别及==与equals的比较机制。Integer是int的包装类,支持null值。使用==比较时,int直接比较数值,而Integer比较对象地址;在-128至127范围内的Integer值可缓存,超出该范围或使用new创建时则返回不同对象。equals方法则始终比较实际数值。
261 0
|
7月前
|
Java 数据库连接 API
Java 8 + 特性及 Spring Boot 与 Hibernate 等最新技术的实操内容详解
本内容涵盖Java 8+核心语法、Spring Boot与Hibernate实操,按考试考点分类整理,含技术详解与代码示例,助力掌握最新Java技术与应用。
230 2