一篇读懂128陷阱

128陷阱

  • 128陷阱的概念
    • 包装器类
    • 自动装箱
    • 自动拆箱
    • 128陷阱
  • Intager源码
  • equals

128陷阱的概念

首先想要清楚什么是128陷阱,需要了解一些概念

包装器类

包装器类(Wrapper classes)是Java中的一组类,它们允许将基本数据类型(如int、char、boolean等)封装为对象。这些包装器类提供了许多有用的方法,用于在基本数据类型和对象之间进行转换和操作。这里给出两个例子

基本类型包装器类
intInteger
doubleDouble

自动装箱

自动装箱(Autoboxing)是Java中的一种特性,它允许在基本数据类型和对应的包装器类之间进行自动的转换。当你使用基本数据类型的值赋给一个对应的包装器类对象时,编译器会自动将其转换为包装器类对象。
当把一个int类型的值赋给一个Integer对象时,自动装箱就会发生:

int number = 42; // 基本数据类型
Integer wrappedNumber = number; // 自动装箱
System.out.println("Wrapped Number: " + wrappedNumber);

上述代码将int类型的值42赋给一个Integer对象wrappedNumber,编译器会自动将其转换为Integer对象。这样,我们就可以像操作对象一样操作基本数据类型

自动拆箱

自动拆箱(Unboxing)是Java中的另一个特性,它与自动装箱相反。自动拆箱允许将包装器类对象自动转换为对应的基本数据类型。
当你将一个包装器类对象赋给一个基本数据类型变量时,编译器会自动进行拆箱操作。

Integer wrappedNumber = Integer.valueOf(42); // 创建一个Integer对象
int unwrappedNumber = wrappedNumber; // 自动拆箱
System.out.println("Unwrapped Number: " + unwrappedNumber);

128陷阱

在Java中,对于范围在-128到127之间的整数值,自动装箱后的包装器类对象会被缓存起来以提高性能。这意味着对于这个范围内的整数值,每次装箱得到的包装器类对象都是同一个对象。
然而,当我们超过这个范围时,就会遇到所谓的"128陷阱"。这是因为超过范围的整数值会导致自动装箱时创建新的包装器类对象,而不是使用缓存中的对象。

Integer num1 = 100;
Integer num2 = 100;
System.out.println(num1 == num2); // 输出: true

Integer num3 = 200;
Integer num4 = 200;
System.out.println(num3 == num4); // 输出: false

Intager源码

我们从源码的角度来分析一下为什么会产生128陷阱

 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() {}
    }

首先,这个类定义了两个静态常量low和high,low的值为-128,high的值在静态初始化块中被设置为127。这两个常量定义了缓存的整数值的范围,即[-128, 127]。
静态初始化块中的代码首先尝试通过读取系统 java.lang.Integer.IntegerCache.high来获取用户配置的缓存上限值。如果该属性存在且能够被解析为一个整数值,将该值与127进行比较,并确保不超过整数数组的最大容量。接下来,代码创建了一个大小为(high - low) + 1的整数数组cache,用于存储缓存的整数对象。使用low的初始值,从low递增到high的范围,通过循环创建了缓存数组中的每个整数对象。最后,通过断言(assert)语句,确保high的值至少为127,以满足Java语言规范(JLS 7 5.1.7)对范围[-128, 127]的整数值必须被缓存的要求。
当使用一个超过范围的整数值进行自动装箱时,循环创建缓存数组cache的过程会创建一个新的整数对象,而不是使用缓存中的对象。这就是为什么超过范围的整数值会导致自动装箱后产生新的对象的原因。

equals

当我们调用equals()方法时,它会在包装器类中执行特定的逻辑来比较两个对象的值是否相等。为了实现这个逻辑,包装器类会重写equals()方法。

在Java中,equals()方法的默认实现是比较对象的引用,即使用==运算符。但是,包装器类(如Integer、Double等)对equals()方法进行了重写,以便比较它们所包装的值是否相等。

当我们调用equals()方法时,它会首先检查传入的对象是否为同一类型的包装器类对象。如果不是,它会立即返回false,因为不同类型的对象不可能具有相等的值。

如果传入的对象是同一类型的包装器类对象,equals()方法会进一步比较两个对象所包装的值。这种比较是按照数值的逻辑进行的,而不是比较引用。

例如,当我们调用num3.equals(num4)时,equals()方法会比较num3和num4所包装的整数值。如果这两个值相等,equals()方法将返回true;否则,它将返回false。

这样,通过重写equals()方法,包装器类可以实现对值的比较,从而正确判断两个对象是否相等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/784186.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Django QuerySet对象,all()方法

all()方法 在Django中&#xff0c;all()方法是QuerySet对象的一个方法&#xff0c;用于获取模型的所有实例。 当你调用ModelName.objects.all()时&#xff0c;Django会生成一个SQL查询&#xff0c;从数据库中获取该模型的所有记录&#xff0c;并返回一个QuerySet对象&#xf…

【产品运营】Saas的核心六大数据

国内头部软件公司的一季度表现惨不忍睹&#xff0c;为啥美国的还那么赚钱呢&#xff1f;其实核心是&#xff0c;没几个Saas产品经理是看数据的&#xff0c;也不知道看啥数据。 SaaS 行业&#xff0c;天天抛头露面、名头叫的响的 SaaS 产品&#xff0c;真没有几个赚钱的。 那为…

中国计量大学理学院访问赛氪网:共探校企合作新篇章来

2024年7月5日&#xff0c;中国计量大学理学院代表团莅临环球赛乐&#xff08;北京&#xff09;科技有限公司&#xff0c;进行了一场深入的调研交流活动。代表团成员包括中国计量大学理学院副院长王义康教授、数据科学系副主任刘学艺副教授以及金世举老师。此次访问旨在进一步强…

江洲的《家书》,岂止抵万金

题记 今晨6点钟&#xff0c;像往日一样的背上鱼具包&#xff0c;欲驾乘清凉舒适的晨风&#xff0c;前往味江河堤享受钓翁乐趣。孰料开门一看&#xff0c;朦胧的天空竟下着淅淅沥沥的小雨。 今年的天气异常&#xff0c;是笔者寄居“西川第一天”古镇5年来所未见&#xff1a;再…

stm32——外部中断EXTI

上回书说到定时器的级联&#xff0c;今天来谈谈外部中断EXTI。我使用的是STM32F103C8T6的学习板。仅供大家参考。 什么是中断呢&#xff1f;中断是指计算机在执行程序的过程中&#xff0c;当出现某些异常情况或特殊事件&#xff08;例如外部设备请求、定时时间到达、程序错误等…

YOLOV8花朵实例分割实战

原文:YOLOV8花朵实例分割实战 - 知乎 (zhihu.com) 一、代码: https://github.com/ultralytics/ultralytics​github.com/ultralytics/ultralytics 与先前几个版本相比,YOLOv8 模型更快、更准确,同时为训练模型提供统一框架,以执行以下基本任务: 目标检测;实例分割;图…

奇安信20240513笔试

题目一 解题思路 n转为字符串&#xff0c;如果位数为偶数&#xff0c;取前一半设为x&#xff0c;后一段为y&#xff0c;从x最低位开始&#xff0c;9&#xff0c;9*10&#xff0c;9*10*10。。。 到最高位&#xff0c;加x&#xff0c;如果x大于或等于y&#xff0c;加1. 位数为奇数…

武汉免费 【FPGA实战训练】 Vivado入门与设计师资课程

一&#xff0e;背景介绍 当今高度数字化和智能化的工业领域&#xff0c;对高效、灵活且可靠的技术解决方案的需求日益迫切。随着工业 4.0 时代的到来&#xff0c;工业生产过程正经历着前所未有的变革&#xff0c;从传统的机械化、自动化逐步迈向智能化和信息化。在这一背景下&…

全志A527 T527 cat /proc/cupinfo没有Serial问题

1.前言 我们有些客户是使用cpuinfo节点去获取系统的cpuid的,如下: cat /proc/cupinfo processor : 0 BogoMIPS : 48.00 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp CPU impleme…

代码随想录-Day51

115. 不同的子序列 给你两个字符串 s 和 t &#xff0c;统计并返回在 s 的 子序列 中 t 出现的个数&#xff0c;结果需要对 109 7 取模。 示例 1&#xff1a; 输入&#xff1a;s “rabbbit”, t “rabbit” 输出&#xff1a;3 解释&#xff1a; 如下所示, 有 3 种可以从 …

基于 LlamaIndex、Claude-3.5 Sonnet 和 MongoDB,构建具有超级检索能力的智能体

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型技术趋势、算法项目落地经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。 总结链接如…

Day1--每日一练

&#x1f341; 个人主页&#xff1a;爱编程的Tom&#x1f4ab; 本篇博文收录专栏&#xff1a;每日一练-算法篇&#x1f449; 目前其它专栏&#xff1a;c系列小游戏 c语言系列--万物的开始_ Java专栏等 &#x1f389; 欢迎 &#x1f44d;点赞✍评论⭐收藏&…

Java之父James Gosling宣布正式退休 创造无数人的饭碗

编程语言Java的创始人&#xff0c;被誉为“Java之父”的James Gosling&#xff0c;近日在社交媒体上宣布了自己正式退休的消息。Gosling表示&#xff1a;“我终于退休了。做了这么多年的软件工程师&#xff0c;现在是时候享受人生了。”他透露&#xff0c;在亚马逊的过去7年是非…

代码随想录算法训练营第四十七天|1143.最长公共子序列、 1035.不相交的线、53. 最大子序和、392.判断子序列

1143.最长公共子序列 题目链接&#xff1a;1143.最长公共子序列 文档讲解&#xff1a;代码随想录 状态&#xff1a;一开始没想明白为啥要 max(dp[i - 1][j], dp[i][j - 1]) 思路&#xff1a; 如果text1[i - 1] 与 text2[j - 1]相同&#xff0c;那么找到了一个公共元素&#xff…

GitLab介绍,以及add an SSH key

GitLab GitLab 是一个用于仓库管理系统的开源项目&#xff0c;现今并在国内外大中型互联网公司广泛使用。 git,gitlab,github区别 git 是一种基于命令的版本控制系统&#xff0c;全命令操作&#xff0c;没有可视化界面&#xff1b; gitlab 是一个基于git实现的在线代码仓库…

K8s驱逐场景以及规避方案参考 —— 筑梦之路

Pod 驱逐分为两种情况&#xff1a; 较安全驱逐 & 提高稳定性的良性驱逐 API 发起驱逐&#xff0c;典型案例&#xff1a;kubectl drain Node Not Ready 时&#xff0c;Controller Manager 发起的驱逐 有风险的驱逐 节点压力驱逐 节点磁盘空间不足、内存不足 或 Pid 不足&…

简易Qt串口助手

界面显示如下 关于串口类 初始化 设置串口号 设置波特率 打开串口 发送按钮功能实现 接收数据显示在控件中 关闭串口

Vortex GPGPU的硬件设计和代码结构分析

文章目录 前言一、GPGPU是什么&#xff1f;1.1 GPU和GPGPU之间的差异1.2 GPU和CPU之间的集成方式1.3 GPU包含什么&#xff08;列举和VMIPS向量体系结构的差异&#xff09; 二、Vortex GPGPU是什么&#xff1f;2.1 Vortex GPGPU的技术边界和验证环境2.2 Vortex GPGPU的指令集设计…

30万的剧本杀店 被“好色”店长玩死了

文&#xff5c;琥珀食酒社 作者 | 朱珀 对开店搞钱的人来讲 什么才是最苦逼的&#xff1f; 不是一开始生意就不行 而是刚开始好到不行 最后只剩下不行 本期投稿的主人公糊糊 就是这样的 苦逼大BOSS 30万开剧本杀店 短短几个月 从巅峰跌到谷底 被捞钱又好色的猪队友…

C++ 类和对象 拷贝构造函数

一 拷贝构造函数的概念&#xff1a; 拷贝构造函数是一种特殊的构造函数&#xff0c;用于创建一个对象是另一个对象的副本。当需要用一个已存在的对象来初始化一个新对象时&#xff0c;或者将对象传递给函数或从函数返回对象时&#xff0c;会调用拷贝构造函数。 二 拷贝构造函…