首页 > 编程语言 >Java中128陷阱源码剖析(一看就懂)

Java中128陷阱源码剖析(一看就懂)

时间:2024-03-26 10:29:19浏览次数:22  
标签:Java int cache 源码 static 127 128 Integer

文章目录

128陷阱

例子

现在有这样的程序,相同的值判断相等,不同的值大小下,得出的结果却不同。

public class Main {
    public static void main(String[] args) {
        Integer a= 123;
        Integer b = 123;
        int c = 123;
        int d = 123;

        System.out.println(a == b); // T
        System.out.println(c == d); // T
        System.out.println(a == c); // T
    }
}
public class Main {
    public static void main(String[] args) {
        Integer a= 128;
        Integer b = 128;
        int c = 128;
        int d = 128;

        System.out.println(a == b); // F
        System.out.println(c == d); // T
        System.out.println(a == c); // T
    }
}

问题一:a,b为什么不同值下判断相等的结果不同?
问题二:c,d为什么相同?
问题三:a,c为什么一直相同?

解析

问题一

这就是Integer的128陷阱。

在Integer创建时,其实就是走的Integer.valueOf()返回了一个对象,例如:

Integer a = 100;
相当于
Integer a = Integer.valueOf(100);

我们看ValueOf这个方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

先翻译一下注释:

Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
返回一个 Integer 实例,该实例表示指定的 int 值。如果不需要新的 Integer 实例,则通常应优先使用此方法,而不是构造函数 Integer(int),因为此方法可能会通过缓存频繁请求的值来产生显著更好的空间和时间性能。此方法将始终缓存 -128 到 127(含)范围内的值,并可能缓存此范围之外的其他值。

我们再看代码:
它其实是判断了一下数是否在IntegerCache.low和IntegerCache.high之间。

所以我们再看IntegerCache这个静态内部类,静态内部类在被调用时加载。

他是创建了一个Integer的cache数组,大小为127-(-128)+ 1,并且都new了出来(对应初值也赋值了),所以映射关系就很明显了,就是用来存放[-128, 127]之间的数,上面调用的low和high就是这两个数。

  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) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

所以如果我们赋值的数i在[-128, 127]之间,他就会返回cache[i - (-128)]中已经创建好的对应Integer对象。
如果不在之间,就会返回一个新new的Integer对象。

也就是说在[-128, 127]之间,是同一个对象,而不在范围内,则是不同的对象。

回到我们最初的问题,==对应引用类型,其实对比的是否为同一引用,范围内,同一对象返回true,不在范围内,是不同对象返回false。

问题二

这个就不用解释了吧,基本类型比较值,肯定相同。

问题三

而对于Integer 和 int 相同值进行比较为什么一直相等的原理,是这样的:

public class Main {
    public static void main(String[] args) {
        Integer a= 128;
        int c = 128;
        System.out.println(a == c); // T
    }
}

在==时候,jvm其实调用的是

a.intValue() == c

那我们来看一下intValue这个方法的代码:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个value是什么呢?

在这里插入图片描述

就是Integer的构造方法,给value赋的int值,对应我们真实的int,无论你是否是在cache缓存内,Integer对象都是new出来的,这个value就是真实的记录的int值。

那这个==不就变成了问题二了么,就是值的对比,很显然无论什么情况都是true。

over!

标签:Java,int,cache,源码,static,127,128,Integer
From: https://blog.csdn.net/Cosmoshhhyyy/article/details/137030772

相关文章

  • How to get the client IP address with Javascript only
    LearnhowtogettheclientIPaddress(localandprivate)usingonlyjavascript.​​Javascriptisunabletoget(norstoressomewhere)theclientIP,howeverjavascriptisabletocreateHttprequests,andserversidelanguagesareabletoretrievetheu......
  • Java中的流和IO操作及底层实现原理
    Java中的流和IO操作是Java编程中非常基础和重要的概念,它们主要用于处理数据的输入和输出。下面我会详细解释这两个概念。流(Stream)在Java中,流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输......
  • 「Java开发指南」如何从WSDL搭建一个Spring服务?
    本教程的重点是如何从现有的WSDL构建Web服务,实现的WSDL是来自ApacheCXF文档的HelloWorldWSDL协议 的简化版本。在本教程中,您将学习如何:导入WSDL协议部署并运行web服务注意:自定义Spring代码生成需要MyEclipseSpring或Bling授权。MyEclipsev2023.1.2离线版下载MyEclipse......
  • Java面试必问题18:线程安全的集合类和有序的集合类
         精华篇:  极致精简解释有序的集合类包括:TreeMap-基于红黑树实现的有序Map。LinkedHashMap-基于哈希表和双向链表实现的有序Map。TreeSet-基于红黑树实现的有序Set。LinkedHashSet-基于哈希表和双向链表实现的有序Set。示例:有序Map:TreeMap有序Li......
  • java毕业设计房产销售管理小程序[附源码]
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:在当今数字化时代,房产销售行业正经历着前所未有的变革。随着信息技术的飞速发展,传统的房产销售模式已经无法满足市场的需求。购房者越来越倾向于通过网络......
  • 如何使用 JavaScript 导入和导出 Excel
    前言在现代的Web应用开发中,与Excel文件的导入和导出成为了一项常见而重要的任务。无论是数据交换、报告生成还是数据分析,与Excel文件的交互都扮演着至关重要的角色。本文小编将为大家介绍如何在熟悉的电子表格UI中轻松导入Excel文件,并以编程方式修改表格或允许用户进行编辑,最......
  • 【Cesium源码系列】Cesium的相机(1)
    Cesium相机内部保存着相机的基本信息,主要有以下几个属性:_transform:对外只读,变换矩阵_invTransform:对外只读,变换矩阵的逆_actualTransform:对内,实际变换矩阵_actualInvTransform:对内,实际变换矩阵的逆position:对外,相机的位置_position:对内,相机的位置_positionWC:对外只读,相机......
  • Java服务器开发的日志:日志的作用和使用方法;日志文件的定期归档、清理和滚动策略;ELK(又
    Java服务器开发的日志Java服务器开发,为什么要使用日志?应该怎样使用日志?在Java服务器开发中使用日志是非常关键的一个实践,原因如下:本文所说的“日志”,主要是指程序运行时生成的技术日志;它在Java服务器开发中的作用和使用方法如下:故障诊断:技术日志主要用于记录程序运......
  • JAVA中CAS原理
    在Java中,CAS(Compare-and-Swap)是一种无锁算法,通过JNI(JavaNativeInterface)调用本地方法来利用处理器提供的原子指令实现。它可以保证在多线程环境下的原子性和可见性,而无需使用传统的锁机制。以下是一个简单的Java示例,通过java.util.concurrent.atomic包下的AtomicInteger类来......
  • 【附源码】java毕业设计生活旅行分享网站的设计与实现
    本系统(程序+源码)带文档lw万字以上 文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着经济的发展和生活水平的提高,旅行已经成为现代人休闲放松的一种重要方式。人们不仅希望在旅行中体验不同的文化、风光和生活,还愿意通过互联网与他人分......