【Java基础】Integer的自动拆箱和享元模式,这次我学到了

如何理解Java中的自动拆箱和自动装箱? 自动将基本数据类型转换为包装器类型。自动将包装器类型转化为基本数据类型。自动拆箱避免了手动调用 intValue()或类似方法来获取基本数据类型的值,使代码更简洁。 自动装箱允许我们将基本数据类型直接赋值给包装类对象,而不需要显式地创建对象。 自动拆箱(Auto-unboxing)和自动装箱(Auto-boxing)的主要目的是为了在基本数据类型(如int、double等)和它们的包装类(如Integer、Double等)之间实现自动转换,以简化编程和提高代码可读性。 阅读详情

前言

前段时间线上报了一个空指针异常,后来多方排查发现是Integer自动拆箱的问题。所以少侠又把Integer源码及一些比较底层的知识学习了一遍,这里记录一下,也分享给大家。

自动拆箱

先看下出问题的代码,业务逻辑我给省去了。要做的事情很简单,就是从表里查询某用户购买商品一共支付的价格。注意,用户可能不存在,即通过SQL的SUM函数可能为null。

Mapper层代码:

/**
 * @author Carson
 * @date 20-9-16 下午7:27
 */
@Mapper
public interface UserOrderMapper {

    String TABLE_NAME = "cps_user_order_detail d";

    @Select("SELECT SUM(price) FROM " + TABLE_NAME + " WHERE d.user_id=#{userId}")
    Integer calPrice(@Param("userId") String userId);
}

业务层代码:

 public Integer calPrice(String userId) {
        int price = userOrderMapper.calPrice(userId);
        Double rate = 0.5;
        return rate * price;
    }

少侠先不说问题,各位在看到这段代码会想到可能的隐患吗?

手动分隔符 +++++++++++++++++++++++++++++++++++++++++

好了,不卖关子了,上述代码极可能出现空指针异常。
事实上线上日志报错就是在业务层代码的int price = userOrderMapper.calPrice(userId);这一行。报了NullPointerException,当时我的第一感觉是难道userOrderMapper没有注入进来?但是业务层该Mapper的其它方法都正常运行,所以立即排查这个可能。但是SQL里面会出错么,即使参数为null,SQL也不会报NPE的。
苦思无果,于是把SQL拿出来手动执行了一遍,发现返回值是null,于是立即想到肯定是这个null的返回值调用了什么方法,但是再一看业务层代码,没有调用直接返回了啊。但是再一看返回值,呦吼,是int,想到可能是自动拆箱(即Integer向int类型转换)的问题。具体是啥问题呢。
看官莫急,且来看一下这段代码:

public class Main {
    public static void main(String[] args) {
        Integer input = null;
        int result = input;
        System.out.println(result);
    }
}

运行完之后进入classes文件夹下执行javap -v Main.class,查看反编译执行结果,这个就很明了了,如下所示,实际上Integer类型的参数用int接收是通过隐式的调用Integer.intValue()实现的。这也解释了上面那段业务代码会出现异常。
在这里插入图片描述

享元模式

还是先来看一段代码。相信参加过在线笔试的小伙伴很多人都做过下面这道题:

public class Main {
    public static void main(String[] args) {
        Integer a1 = new Integer(66);
        Integer b1 = new Integer(66);
        System.out.println(a1 == b1);
        Integer a2 = 128;
        Integer b2 = 128;
        System.out.println(a2 == b2);
        Integer a3 = 127;
        Integer b3 = 127;
        System.out.println(a3 == b3);
    }
}

a1==b1等于false相信大家都没疑问。a2==b2你会想到,声明了两个变量,在内存中开辟了两个地址空间,答案也是false,也没问题。
然后再一看,什么鬼?刚刚是128,a3和b3变成127,同样的问题问我两遍?这出题人水平不行啊!小伙子,这样想说明你还年轻啊。是的,a3==b3答案是true。这是为什么呢?
事实上这是Java源码级的优化,Integer为了提高内存的利用率,内部设置了一个缓冲区,附上源码:

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

这是什么意思呢,就是在[-128,127]的区间内的整数,在内存中始终只会有一份(当然你通过new创建新对象的方式不算)。并且这个就是大名鼎鼎的享元模式。下次再有面试官问你JDK应用了哪些设计模式,把Integer这里的实现甩给他!

小结

一个小小的Integer就含有很有讲究,虽然读代码、找问题的过程比较苦涩,但是掌握之后还是会觉得充实。做开发最需要的就是技术提升,而阅读源码就是一个绝佳的方式!
我是少侠露飞,爱技术,爱分享。

点点关注,不会迷路

二阶FLL辅助三阶PLL环路的代码解读 今天对GNSS接收机里面的载波跟踪环路代码进行了解读 以下是个人的一点见解 % 载波环第二步:环路滤波器 二阶FLL辅助三阶PLL环路 carrLoopS0 = lastCarrLoopS0 + (phaseErr*tau0PLL + freqErr*tau1FLL) * PDIcarr; carrLoopS1 = lastCarrLoopS1 + (tau1PLL*phaseErr + carrLoopS0 + tau2FLL*freqErr) * PD 阅读详情

相关推荐

2025.1.16——五、LoveSQL1 sqlmap文件类|万能密码

题目来源:BUUCTF[极客大挑战2019]LoveSQL1。

2402_87387800的博客 1067

Integer类自动拆箱,装箱解析

Integer类自动拆箱,装箱解析 1.自动拆箱 例1: int i1 = 10; Integer i2 = new Integer(10); System.out.println(i1 == i2); 这个结果是true i1为基本数据类型值为10,i2为Integer类对象value属性值为10,在进行比较运算时,i2会自动拆箱成int类型然后再与i1进行比较所以结果是true。 所以我们来看一下自动拆箱里面发生了什么,其实非常简单, 在执行i1 == i2时由于i2是包装类和基本数据类型进行比较所

weixin_46120888的博客 2263

pgsql行列转换

‌是PostgreSQL中的一个函数,用于将一个字符串根据正则表达式进行分割,并将结果返回为一个表格,每个分割后的部分作为一行‌‌。string_agg() 函数是 PostgreSQL 中的一个聚合函数,用于将一个列中的值连接成一个字符串。

chimchim66的博客 3503

【源码分析设计模式 7】Integer中的享元模式

一、基本概念 说到享元模式,第一个想到的应该就是池技术了,String常量池、数据库连接池、缓冲池等等都是享元模式的应用,所以说享元模式是池技术的重要实现方式。 比如我们每次创建字符串对象时,都需要创建一个新的字符串对象的话,内存开销会很大,所以如果第一次创建了字符串对象“Flyweight”,下次再创建相同的字符串“Flyweight”时,只要把它的引用指向“Flyweight”,这样就实现了“Flyweight”字符串在内存中的共享。 举个最简单的例子,网络联机下棋的时候,一台服务器连接了多个客户

学Java,找哪吒 6185

告别测序污染:手把手教你用Decontam+SCRUB+FEAST完成微生物组数据清洗全流程

本文详细解析了使用Decontam、SCRUB和FEAST三大工具完成微生物组数据清洗的全流程。从环境准备、数据导入到污染物识别、样本间污染校正及溯源分析,提供了一套可复用的污染校正工作流,帮助研究者提升数据质量,确保后续分析的可靠性。

weixin_33462927的博客 317

【软件逆向学习记录】x64dbg调试器入门2:主调试窗口功能及字符串搜索功能介绍

在x64dbg中, ​​CPU视图 是调试过程中最核心的界面,通常被称为​​主调试窗口​​或​​调试视图​​,总体分为四个区域,代码区(反汇编),数据区(内存窗口),寄存器区和堆栈区,详细位置如下图:示例数据代码区最左侧为内存地址,第二块区域为程序代码值,原始程序代码经编译和汇编后变为二进制机器码存储在计算机中,调试器将其展示为易于阅读的十六进制,第三块区域是机器码反汇编后的汇编代码,最右侧为代码的注释窗口,有一些原始的注释,也可以自己添加注释PS:汇编和反汇编解释。

tusikong的博客 2923

Integer和int的区别(装箱和拆箱)

Integer的自动装箱和自动拆箱、与int的区别Integer的自动装箱和自动拆箱Integer和int的区别 第一次写博客,因为偶尔看到一道题,自己做错了,所以话了写时间研究了一下,或许存在错误,希望大家指出,相互学习。当是我的笔记,存在博客,以后可以翻看。 Integer的自动装箱和自动拆箱 Integer类包装一个对象中的原始类型int的值。 类型为Integer的对象包含一个单一字段,其...

hjx154954264的博客 1943

【ArcGIS Add-in编程】如何创建ArcMap的下拉菜单插件

step1. VS2010中创建一个空的解决方案step2.创建一个项目 直接点击finish。step3 为该项目创建项目,选择Menu,作为根菜单,而后修改xml中的items项,添加需要放在下拉菜单中的项目,例如一个按钮; step4 现在可以创建项目,作为菜单中的项目。为该项目添加新的项目,选择button 此时 xml文件中,多了该button的项目,将该项目添加到items

吃货小跟班的博客 4431

Integer自动拆箱装箱及Integer如何实现常量池源码解析

Integer自动拆箱装箱及Integer如何实现常量池源码解析

efggfxfvhh的博客 918

2024年11月架构设计师综合知识真题回顾,附参考答案、解析及所涉知识点(一)

软考高级考试包含三个科目:信息系统综合知识、系统架构设计案例分析和系统架构设计论文。考试形式为机考。本文主要回顾2024年下半年(2024-11-10)系统架构设计师考试上午综合知识科目的选择题,同时附带参考答案、解析和所涉知识点。由于机考时题目顺序是打乱的,本文题目所标序号只为区分不代表实际顺序。综合知识。

一几文的编程学习笔记。 9280

【知识分享】车载以太网PCB布局设计指南

本文将深入探讨在设计车载以太网设备的印刷电路板(PCB)时需要着重考虑的若干关键主题。这些主题广泛涵盖了数据布线设计,以确保其符合信号完整性(SI)和电磁兼容性(EMC)标准;外部元器件的合理摆放;以及采取有效的抗电磁干扰(EMI)布局策略等方面。通过全面且细致地处理这些关键环节,能够显著提升车载以太网设备的性能与可靠性。

一只豌豆象的博客 1352

Integer装箱拆箱、参数传递

(1)JAVA里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递。 (2)Integer作为参数传递时引用传递。 举个栗子: public class test{ public void add3(Integer i){ System.out.println("i赋值前的地址:"+System.identityHashCode(i)); i=3...

军威兄的博客 3730

告别传统RAG的痛点!Agent Skills让知识库检索更智能(本地知识库搭建新思路:用Agent Skills实现渐进式检索)

传统RAG在知识库检索中存在文档结构丢失、Token消耗大等问题 📚 Agent Skills通过分层索引、渐进式检索等设计,实现了更智能的本地知识库检索方案 🤖 本文详细介绍了Agent Skills的核心设计理念、与传统RAG的对比以及实践建议,帮助你搭建高效的知识库系统 ✅

XiaoqiangClub的博客 693

Java基础之int和Integer有什么区别

1 int与Integer的基本使用对比 (1)Integer是int的包装类;int是基本数据类型; (2)Integer变量必须实例化后才能使用;int变量不需要; (3)Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ; (4)Integer的默认值是null;int的默认值是0。 2 int与Integer的深入对比 (1)由于In...

chenliguan的博客 16万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

int和Integer的区别与联系:包装类、自动拆箱装箱、享元模式

1、基本数据类型和引用数据类型 1.1、 基本数据类型: java提供了8中基本数据类型: boolean、byte、int、char、long、short、double、float; java提供诸如:类、接口等引用数据类型,其中Integer就是一种引用数据类型,常被称为包装类。 1.2、int和Integer的区别 int是基本数据类型,Integer是int包装类。 Integer变量必须实例化后才能使用,int可以直接使用 Integer的默认值是null,int默认值是0 Integer变量实际

weixin_43157935的博客 730

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

int和Integer自动装箱和拆箱

1、int和Integer的区别: int是基本数据类型,直接存储的数值,默认是0 Integer 是int的包装类,是个对象,存放的是对象的引用,必须实例化之后才能使用,默认是null 2、int和Integer比较的特性 == 地址比较 数值类型int自动装箱成对象Integer,实际上是调用了Integer.valueOf(),如果数值范围在-128到127会默认从常量池获取对象,...

just Go! 1065

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java中Integer类的自动装箱和自动拆箱与享元模式

所谓自动装箱,就是把基本数据类型用他们对应的引用类型包装起来,使他们可以具有对象的特质。例如我们可以把int类型包装成Integer类型的,把double类型的包装成Double类型的。 所谓拆箱,就是进行与自动装箱相反的操作。 自动装箱的过程:当需要一种类型的对象时,这种基本数据类型就自动封...

chiwangzuan0717的博客 205

享元模式(下):剖析享元模式在Java Integer、String中的应用

上一节课,我们通过棋牌游戏和文本编辑器这样两个实际的例子,学习了享元模式的原理、实现以及应用场景。用一句话总结一下,享元模式中的“享元”指被共享的单元。享元模式通过复用对象,以达到节省内存的目的。 今天,我再用一节课的时间带你剖析一下,享元模式在 Java Integer、String 中的应用。如果你不熟悉 Java 编程语言,那也不用担心看不懂,因为今天的内容主要还是介绍设计思路,跟语言本身关系不大。 话不多说,让我们正式开始今天的学习吧! 享元模式在 Java Integer 中的应用 我们先来看下面

liyf2的博客 388

Java进阶(三十七)java 自动装箱与拆箱

Java进阶(三十七)java 自动装箱与拆箱前言 这个是jdk1.5以后才引入的新的内容。java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装称为装箱,解包装称为拆箱); 其实按照我自己的理解自动装箱就可以简单的理解为将基本数据类型封装为对象类型,来符合java的面向对象;例如用int来举例: //声明一个Integer对象 In

IT全栈 华强工作室 4万+

Java类型浅析、自动拆箱、享元模式

在Java中,万物皆对象,但是仍可以分为基本类型和非基本类型。 因为对于int 这些数据对象,并不需要多大的空间,为了提高效率,就将这些int、double、float、bool等基本类型直接按值存放在栈中。而非基本类型的实际值则是存放在堆中。 下面我们结合上面提到的数据类型再讨论一下==和equals的问题。 我们知道Java中都是以引用方式来操作实际对象的,而引用则是存在于栈中。而对于基本类型...

JustKian的博客 227

55 | 享元模式(下):剖析享元模式在Java Integer、String中的应用

本文讨论了享元模式在Java中的实际应用,尤其是在Integer和String类中的体现。通过缓存常用的对象,Integer类在-128到127范围内避免了频繁创建新对象,提升了内存效率;而String类通过字符串常量池实现了相同字符串的复用,减少了内存占用。然而,享元模式对垃圾回收不友好,享元对象在没有使用时可能无法被及时回收。文章建议开发者在实际项目中合理使用享元模式,避免过度使用,尤其在确保其能带来显著内存优化的场景下。最后,文章还提出了一些改进思路,帮助更好地管理和回收不再使用的享元对象。

想起来就更新 912

Integer 享元模式

  装箱: 自动将基本数据类型转换为包装器类型;Integer.valueOf(i); 拆箱: 自动将包装器类型转换为基本数据类型。Integer.intValue(); 例子: Integer i1 = 100; Integer i2 = 100; Integer i3 = 200; Integer i4 = 200;           System.out.println(i1=...

mayongbo19的博客 1133

java自动装箱和拆箱

java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装成为装箱,解包装称为拆箱) 基本数据类型与对象的差别 基本数据类型不是对象,也就是使用int、double、boolean等定义的变量、常量。 基本数据类型没有可调用的方法。 eg:  int t = 1;      t.  后面是没有方法滴。           Integer t =1; t.

liuxigiant的专栏 795

double float区别_int和Integer的区别与联系:包装类、自动拆箱装箱、享元模式

1、基本数据类型和引用数据类型1.1、 基本数据类型:java提供了8种基本数据类型:boolean、byte、int、char、long、short、double、float;java提供诸如:类、接口等引用数据类型,其中Integer就是一种引用数据类型,常被称为包装类。1.2、int和Integer的区别int是基本数据类型,Integer是int包装类。Integer变量必须实例...

weixin_39815879的博客 338

Java基础:int与Integer区别

int与Integer的基本使用对比 Integer是int的包装类;int是基本数据类型; Integer变量必须实例化后才能使用;int变量不需要; Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ; Integer的默认值是null;int的默认值是0。 int与Integer的深入对比 (1)由于Integer变量实际上是对一个Integer对...

TuT 5380

包装类 -- 自动拆箱和自动装箱 -- 享元模式

文章目录包装类包装类有哪些为什么要使用包装类Integer方法自动装箱和自动拆箱享元模式 包装类 包装类有哪些 基本数据类型 其对应的包装类(可以在API文档中查询到) byte Byte short Short int Integer long Long float Float double Double char Character boolean ...

风华流沙君莫笑的博客 349
上一篇: MySQL深度分页的问题及优化方案:千万级数据量如何快速分页
下一篇: 【搞定面试官】系列:如何保证缓存与数据库的双写一致性
少侠露飞
博客等级 码龄9年 214粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值