深入理解Java包装类:自动装箱拆箱与缓存池机制
深入理解Java包装类:自动装箱拆箱与缓存池机制
对象包装器
Java中的数据类型可以分为两类:基本类型和引用类型。作为一门面向对象编程语言, 一切皆对象是Java语言的设计理念之一。但基本类型不是对象,无法直接参与面向对象操作,为了解决这个问题,Java让每个基本类型都有一个与之对应的包装器类型。
Java中有8种不可变的基本类型,分别为:
- 整型:
byte
、short
、int
、long
- 浮点类型:
float
、double
- 字符类型:
char
- 布尔类型:
boolean
类型 | 大小 | 默认值 | 示例 |
---|---|---|---|
byte | 1字节 | 0 | byte b = 10 |
short | 2字节 | 0 | short s = 200 |
int | 4字节 | 0 | int i = 1000 |
long | 8字节 | 0L | long l = 5000L |
float | 4字节 | 0.0f | float f = 3.14f |
double | 8字节 | 0.0d | double d = 2.718 |
char | 2字节 | ‘\u0000’ | char c = 'A' |
boolean | 未明确定义 | false | boolean flag = true |
这八种基本类型都有对应的包装类分别为:Byte
、Short
、Integer
、Long
、Float
、Double
、Character
、Boolean
(前6个派生于公共的超类Number
)。包装器类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值。同时,包装器类还是final
,因此不能派生它们的子类。
Java不是“一切皆对象”吗,为什么还要保留基本数据类型?
包装类是引用类型,对象的引用存储在栈中,对象本身存储在堆中;而对于基本数据类型,变量对应的内存块直接存储数据本身(栈中)。因此,基本数据类型读写效率更高效。在64位JVM上,在开启引用压缩的情况下,一个Integer对象占用16个字节的内存空间,而一个int类型数据只占用4字节的内存空间,前者对空间的占用是后者的4倍。也就是说,不管是读写效率还是存储效率,基本类型都更高效。尽管Java强调面向对象,但为了性能做了妥协。
自动装箱与拆箱
装箱和拆箱是实现基本数据类型与包装类之间相互转换的特性。Java 5引入自动装箱/拆箱功能,进一步简化了包装类的使用。
- 装箱:将基本数据类型转化为对应的包装类对象。
- 拆箱:将包装类对象转化为对应的基本数据类型值。
示例:
Integer a = 100; // 自动装箱 -> Integer.valueOf(100)int b = a; // 自动拆箱 -> a.intValue()// 自动装箱和拆箱也适用于算术表达式
Integer n = 3;
n++; // 编译器将自动插入一条对象拆箱的指令,然后进行自增运算,最后再将结果装箱
装箱其实就是调用了包装类的valueOf()
方法,拆箱其实就是调用了 xxxValue()
方法。
API
java.lang.Integer
int intValue()
将这个
Integer
对象的值作为一个int
返回(覆盖Number
类中的intValue
方法)。
static Integer valueOf(String s)
返回一个新的
Integer
对象,用字符串s
表示的整数初始化。指定字符串必须表示一个十进制整数。
关于自动装箱还有几点需要注意:
高频装箱拆箱(如循环)会产生大量临时对象,消耗内存和GC资源:
// 错误示例:每次循环触发装箱 Long sum = 0L; for (long i = 0; i < 1e6; i++) {sum += i; // sum = Long.valueOf(sum.longValue() + i) }// 正确优化:使用基本类型 long sum = 0L; for (long i = 0; i < 1e6; i++) {sum += i; }
由于包装器类引用可以为
null
,所以自动装箱有可能会抛出一个NullPointerException
异常:Integer n = null; System.out.println(2 * n) // throws NullPointerException
如果在一个表达式中混合使用
Integer
和Double
类型,Integer
值就会拆箱,提升为double
,再装箱为Double
:Integer n = 1; Double x = 2.0; System.out.println(true ? n : x); // 1.0
装箱和拆箱是编译器要做的工作,而不是虚拟机。编译器在生成类的字节码时会插入必要的方法调用。虚拟机只是执行这些字节码。
缓存池机制
缓存池是 Java 为优化包装类对象创建和内存消耗而设计的核心机制,通过预创建和复用常用数值的包装类对象,减少重复对象创建的开销。Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。
Byte
,Short
,Integer
,Long
这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character
创建了数值在 [0,127] 范围的缓存数据,Boolean
直接返回 TRUE
or FALSE
。
示例:
Integer a = 100; // Integer.valueOf(100)
Integer b = 100; // Integer.valueOf(100)
Integer c = 200; // Integer.valueOf(200)
Integer d = 200; // Integer.valueOf(200)System.out.println(a == b); // true
System.out.println(c == d); // false
System.out.println(c.equals(d)); //true
Integer.valueOf()
的缓存逻辑:
public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i); // 超出缓存范围时创建新对象
}
缓存池机制:Java对
-128 ~ 127
范围内的Integer
对象预先生成并缓存,a
和b
指向同一个缓存对象,a == b
比较对象地址,返回true
。200
超出默认缓存范围(-128 ~ 127
),Integer.valueOf(200)
每次会创建新对象,c
和d
指向不同对象,c == d
比较对象地址,返回false
。
对于 Integer
,可以通过 JVM 参数 -XX:AutoBoxCacheMax=<size>
修改缓存上限,但不能修改下限 -128。实际使用时,并不建议设置过大的值,避免浪费内存,甚至是 OOM(全称Out Of Memory, 即内存溢出)。
- 内存溢出:申请的内存超出了JVM能提供的内存大小,此时称之为溢出。
- 内存泄漏:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了,因为申请者不用了,而又不能被虚拟机分配给别人用。
对于Byte
,Short
,Long
,Character
没有类似 -XX:AutoBoxCacheMax
参数可以修改,因此缓存范围是固定的,无法通过 JVM 参数调整。Boolean
则直接返回预定义的 TRUE
和 FALSE
实例,没有缓存范围的概念。
Character
的缓存逻辑:
public static Character valueOf(char c) {if (c <= 127) { // must cachereturn CharacterCache.cache[(int)c];}return new Character(c);
}
Boolean
的缓存逻辑:
public static Boolean valueOf(boolean b) {return (b ? TRUE : FALSE);
}
两种浮点数类型的包装类 Float
,Double
并没有实现缓存机制:
Float a = 3f;
Float b = 3f;
System.out.println(a == b);// 输出 falseDouble c = 1.2;
Double d = 1.2;
System.out.println(c == d);// 输出 false
下面这段代码的输出结果是什么?
Integer a = 40;
Integer b = new Integer(40);
System.out.println(a == b);
Integer a = 40
自动装箱等价于Integer a = Integer.valueOf(40)
,40
在默认缓存范围内,所以a
直接使用的是缓存中的对象,而Integer b = new Integer(40)
会直接创建新的对象。因此,答案是false
。
相关文章:
深入理解Java包装类:自动装箱拆箱与缓存池机制
深入理解Java包装类:自动装箱拆箱与缓存池机制 对象包装器 Java中的数据类型可以分为两类:基本类型和引用类型。作为一门面向对象编程语言, 一切皆对象是Java语言的设计理念之一。但基本类型不是对象,无法直接参与面向对象操作&…...
Linux中的信号量
目录 信号量概念 定义 操作 类型 应用 信号量封装 一、创建信号量 头文件 函数原型 参数说明 返回值 示例 二、设置信号量初始值 头文件 函数原型 参数解释 返回值 示例 三、信号量的P操作 头文件 函数原型 参数解释 返回值 示例 四、信号量的V操作 示…...
深入理解linux操作系统---第15讲 Web 服务器 Nginx
15.1 Nginx 概述 核心特性与历史背景 Nginx由俄罗斯工程师Igor Sysoev于2002年开发,2004年正式发布,旨在解决传统服务器(如Apache)的C10K问题(即单机万级并发连接处理)。其采用事件驱动(Event…...
深度解析算法之前缀和
25.【模版】一维前缀和 题目链接 描述 输入描述 输出描述 输出q行,每行代表一次查询的结果. 示例 输入: 3 2 1 2 4 1 2 2 3 复制 输出: 3 6 这个题的话就是下面的样子,我们第一行输入 3 2的意思即是这个数组是3个元素大小的数组&…...
混合精度训练中的算力浪费分析:FP16/FP8/BF16的隐藏成本
在大模型训练场景中,混合精度训练已成为降低显存占用的标准方案。然而,通过NVIDIA Nsight Compute深度剖析发现,精度转换的隐藏成本可能使理论算力利用率下降40%以上。本文基于真实硬件测试数据,揭示不同精度格式的计算陷阱。…...
6.8 Python定时任务实战:APScheduler+Cron实现每日/每周自动化调度
Python定时任务实战:APScheduler+Cron实现每日/每周自动化调度 实现每日和每周定时任务 关键词:定时任务调度、Python 原生调度器、Cron 脚本、异常重试机制、任务队列管理 1. 定时任务架构设计 采用 分层调度架构 实现灵活的任务管理: #mermaid-svg-PnZcDOgOklVieQ8X {f…...
[Android] 豆包爱学v4.5.0小学到研究生 题目Ai解析
[Android] 豆包爱学 链接:https://pan.xunlei.com/s/VOODT6IclGPsC7leCzDFz521A1?pwdjxd8# 拍照解析答案 【应用名称】豆包爱学 【应用版本】4.5.0 【软件大小】95mb 【适用平台】安卓 【应用简介】豆包爱学,一般又称河马爱学教育平台app,河马爱学。 关…...
swift-12-Error处理、关联类型、assert、泛型_
一、错误类型 开发过程常见的错误 语法错误(编译报错) 逻辑错误 运行时错误(可能会导致闪退,一般也叫做异常) 2.1 通过结构体 第一步 struct MyError : Errort { var msg: String } 第二步 func divide(_ …...
每日定投40刀BTC(14)20250409 - 20250419
定投 坚持 《磨剑篇》浮生多坎壈,志业久盘桓。松柏凌霜易,骅骝涉险难。砺锋临刃缺,淬火取金残。但使精魂在,重开万象端。...
【刷题Day20】TCP和UDP(浅)
TCP 和 UDP 有什么区别? TCP提供了可靠、面向连接的传输,适用于需要数据完整性和顺序的场景。 UDP提供了更轻量、面向报文的传输,适用于实时性要求高的场景。 特性TCPUDP连接方式面向连接无连接可靠性提供可靠性,保证数据按顺序…...
大数据建模与评估
文章目录 实战案例:电商用户分群与价值预测核心工具与库总结一、常见数据挖掘模型原理及应用(一)决策树模型(二)随机森林模型(三)支持向量机(SVM)模型(四)K - Means聚类模型(五)K - Nearest Neighbors(KNN)模型二、运用Python机器学习知识实现数据建模与评估(一…...
Python语法系列博客 · 第6期[特殊字符] 文件读写与文本处理基础
上一期小练习解答(第5期回顾) ✅ 练习1:字符串反转模块 string_tools.py # string_tools.py def reverse_string(s):return s[::-1]调用: import string_tools print(string_tools.reverse_string("Hello")) # 输出…...
Pandas取代Excel?
有人在知乎上提问:为什么大公司不用pandas取代excel? 而且列出了几个理由:Pandas功能比Excel强大,运行速度更快,Excel除了简单和可视化界面外,没有其他更多的优势。 有个可怕的现实是,对比Exce…...
《解锁图像“高清密码”:超分辨率重建之路》
在图像的世界里,高分辨率意味着更多细节、更清晰的画面,就像用高清望远镜眺望远方,一切都纤毫毕现。可现实中,我们常被低分辨率图像困扰,模糊的监控画面、老旧照片里难以辨认的面容……不过别担心,图像超分…...
杨校老师课堂之C++入门练习题梳理
采用C完成下列题目,要求每题目的时间限制:1秒 内存限制:128M 1. 交换个位与十位的数字 时间限制:1秒 内存限制:128M 题目描述 试编写一个程序,输入一个两位数,交换十位与个位上的数字并输出。 …...
基于springboot的老年医疗保健系统
博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了六年的毕业设计程序开发,开发过上千套毕业设计程序,没有什么华丽的语言࿰…...
数据分析与挖掘
一 Python 基本语法 变量与数据类型 : Python 中变量无需声明,直接赋值即可。 常见的数据类型有数值型(整型 int、浮点型 float、复数型 complex)、字符串型(str,用单引号、双引号或三引号括起来ÿ…...
RoBoflow数据集的介绍
https://public.roboflow.com/object-detection(该数据集的网址) 可以看到一些基本情况 如果我们想要下载,直接点击 点击图像可以看到一些基本情况 可以点击红色箭头所指,右边是可供选择的一些yolo模型的格式 如果你想下载…...
大模型Rag - 两大检索技术
一、稀疏检索:关键词匹配的经典代表 稀疏检索是一种基于关键词统计的传统检索方法。其基本思想是:通过词频和文档频率来衡量一个文档与查询的相关性。 核心原理 文档和查询都被表示为稀疏向量(如词袋模型),只有在词…...
【T型三电平仿真】SVPWM调制
目录 仿真模型分析 克拉克变换 大扇区判断编辑 小区域判断 计算基本电压矢量作用时间 确定基本电压矢量的作用顺序 作用时间和矢量作用顺序对应 七段式化生成阶梯图 矢量状态分布 本人学习过程中提出的问题和解释 SVPWM调制实现了什么功能 SVPWM的算法步骤是什么…...
树莓派5-开发应用笔记
0.树莓派系统目录 /home:用户目录。 除了root用户外,其他所有的使用者的数据都存放在这个目录下,在树莓派的系统中,/home目录中有一个pi的子目录,这个就是pi用户的默认目录。 /bin: 主要放置系统的必备执行文件目录。 …...
[Java实战经验]异常处理最佳实践
一些好的异常处理实践。 目录 异常设计自定义异常为异常设计错误代码(状态码)设计粒度全局异常处理异常日志信息保留 异常处理时机资源管理try-with-resources异常中的事务 异常设计 自定义异常 自定义异常设计,如业务异常定义BusinessExce…...
AOSP的Doze模式-LightIdle初识
前言 从Android 6.0开始,谷歌引入了Doze模式(打盹模式)的省电技术延长电池使用时间。根据第三方测试显示,两台同样的Nexus 5,开启的Doze的一台待机能达到533小时,而未开启Doze的一台待机只能达到200小时。Doze省电效果十分明显。…...
QML动画--ParticleSystem
ParticleSystem 是 QML 中用于创建和管理粒子系统的组件,可以制作各种粒子效果如火焰、烟雾、爆炸等。 基本用法 qml import QtQuick.Particles 2.15ParticleSystem {id: particleSystemImageParticle {source: "particle.png"color: "red"a…...
Win 11 重装 Ubuntu 双系统方法
有时候 Ubuntu 环境崩溃了,或者版本过低,需要卸载重装。本文介绍重装的方法,默认已经有一个双系统。 1. 删除原先 Ubuntu 分区 首先打开 Win 的磁盘管理,找到 Ubuntu 的分区,右键删除分区(注意不要错删 wi…...
单例模式:懒汉式的两种优化写法
单例模式:全局唯一实例 懒汉式:获取时才初始化 ①静态局部变量实现(Meyer’s Singleton)【推荐】 /* 类内创建自身实例的可行性分析:在C中,类可以通过静态成员函数创建自身实例。这种机制的核心在于&…...
详细解释浏览器是如何渲染页面的?
渲染流程概述 渲染的目标:将HTML文本转化为可以看到的像素点 当浏览器的网络线程收到 HTML 文档后,会产生一个渲染任务,并将其传递给渲染主线程的消息队列。在事件循环机制的作用下,渲染主线程取出消息队列中的渲染任务࿰…...
高速系统设计简介
1.1 PCB 设计技术回顾 1981 年 8 月 12 日,IBM 正式发布了历史上第一台个人电脑,自此之后,个人电脑融入了人们生活和工作的各个角落,人类从此进入了个人电脑时代。个人电脑的出现,不仅促进了电子产品在消费领域的发展…...
不规则曲面上两点距离求取
背景 在CT中求皮肤上两点间的弧长。由于人体表面并不是规则的曲面,不可能用圆的弧长求取方法来计算出两点间的弧长。 而在不规则的曲面上求两点的距离,都可以用类似测地线距离求取的方式来求取(积分),而转化为搜索路…...
用usb网卡 虚拟机无法开到全双工的解决办法
今天突发奇想 给unraid宿主机插了两个一摸一样的usb网卡 2.5g的 直通给不同的虚拟机 这里unraid需要安装"USB Manager" 请给unraid自备环境 直通的时候 第一次还没生效 看不到网卡 我又在unraid的管理界面 顶部可以看到多出来一个 "usb"页面 打开可…...
webpack 中 chunks详解
webpack 中 chunks详解 在 Webpack 项目中,webpack.config.js 是核心配置文件,而非 webpack.json。chunks 的概念与 Webpack 的代码分割(Code Splitting)功能密切相关,通过 optimization.splitChunks 配置项可以实现对…...
Java @Serial 注解深度解析
Java Serial 注解深度解析 1. 注解本质 Serial 是 Java 14 引入的编译时校验注解,用于标记序列化相关成员,帮助开发者避免常见的序列化错误。 2. 核心作用 (1) 主要用途 标记序列化相关的特殊方法/字段 提供编译时检查 替代传统的命名约定验证 (…...
齐次坐标变换+Unity矩阵变换
矩阵变换 变换(transform):指的是我们把一些数据,如点,方向向量甚至是颜色,通过某种方式(矩阵运算),进行转换的过程。 变换类型 线性变换:保留矢量加和标量乘的计算 f(x)…...
Python语法系列博客 · 第9期[特殊字符] 函数参数进阶:*args、**kwargs 与参数解包技巧
上一期小练习解答(第8期回顾) ✅ 练习1:整数转字符串列表 nums [1, 2, 3, 4, 5] str_list list(map(str, nums))✅ 练习2:筛选回文字符串 words ["madam", "hello", "noon", "python&qu…...
Python语法系列博客 · 第4期[特殊字符] 函数的定义与使用:构建可复用的模块
上一期小练习解答(第3期回顾) ✅ 练习1:创建一个列表,添加5个名字,并用循环打印 names ["Alice", "Bob", "Charlie", "David", "Eva"] for name in names:print…...
6547网:2025年3月 Python编程等级考试一级真题试卷
2025年3月青少年软件编程Python等级考试(一级)真题试卷 题目总数:37 总分数:100 选择题 第 1 题 单选题 下列哪个软件不能运行Python程序?( ) A.JupyterNotebook B.Pycharm C.原版…...
微前端框架Module Federation
以下是 Module Federation 的核心知识点,并结合微前端架构的设计思想,帮助我们构建完整的知识体系: 一、Module Federation 基础概念 1. 什么是 Module Federation? 定义:Webpack 5 引入的一项革命性功能,允许在运行时动态加载其他独立构建的应用模块(微前端),实现跨…...
AUTOSAR图解==>AUTOSAR_SWS_IntrusionDetectionSystemManager
AUTOSAR 入侵检测系统管理器 (IdsM) 详解 AUTOSAR安全框架的核心组件 1. 概述 AUTOSAR 入侵检测系统管理器(Intrusion Detection System Manager, IdsM)是AUTOSAR标准中安全防护框架的关键组成部分,专门负责处理车载安全事件。IdsM模块提供了…...
Alan AI - 面向Web的生成式AI SDK
本文翻译整理自:https://github.com/alan-ai/alan-sdk-web 文章目录 一、关于 Alan AI相关链接资源关键功能特性Alan AI StudioAlan AI SDKAlan AI Cloud 二、为什么选择Alan AI?三、快速开始四、下载安装五、示例应用六、其他平台SDK七、获取帮助 一、关…...
递归下降 ll(1) 型文法 识别二元组文法分析
#include <stdio.h> #include <string.h>FILE* fp; FILE* fa2;char* str new char[1200]; // 循环读取文件,分200字节读取char* peek;// 表格 typedef struct table {char* sign;char* kind;char* message; } signtable;signtable* list; // 数…...
Qt unknown module(s) in qt:serialport解决方法
在Ubuntu和CentOS系统中,若使用Qt时遇到Unknown module(s) in QT: serialport错误,通常是由于未正确安装Qt的串口模块(QSerialPort)或项目配置不当导致。以下是针对两种系统的解决方案: 一、安装Qt串口模块 1. Ubuntu/Debian系列 安装开发包: 执行以下命令安装Qt5串口模…...
金融数学专题6 证券问题与资本利得税
一、固定利息证券 特点:利息固定,且可以在证券名字中体现。 发行价格:公司公开发行证券的价格。 固定利率证券通常在其名称中包括应付利率,例如,8% Treasury Stock 2021 或 5% Treasury Gilt 2018。每位持有人应得的年利息是通…...
XGBoost
XGBoost 假设一共有 m m m个基模型,分别为 f 1 ( x ) , f 2 ( x ) , … , f m ( x ) f_1(x),f_2(x),\dots,f_m(x) f1(x),f2(x),…,fm(x), n n n个样本, x 1 , x 2 , … , x n x_1,x_2,\dots,x_n x1,x2,…,xn,则XGBoo…...
Kubernetes 多主多从集群部署完整文档
好久不见呀!今天给大家整点干货尝尝(其实是自己的总结),主打的就是全程无尿点。 Kubernetes 多主多从集群部署完整文档 1. 机器列表 PS: master,lb,nfs机器均为CentOS 7,其他为Ubuntu 22.04 L…...
使用Spring Validation实现参数校验
引入Spring Validation 起步依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId> </dependency>参数校验失败异常处理 所有的http请求异常都会被拦截处理 exception…...
用思维导图解锁计算机科学导论的知识宝库
引言 在计算机科学的浩瀚海洋中,“计算机科学导论” 如同开启宝藏的钥匙,是众多学习者踏入这片领域的第一步。今天,我将借助思维导图这一强大工具,带大家梳理计算机科学导论的关键知识点,同时也希望能为大家在学习的道…...
软件架构分层策略对比及Go项目实践
一、水平分层 vs 功能划分 vs 组件划分 维度水平分层功能划分组件划分核心思想按垂直层次划分职责(如表示层、业务层、数据层)按业务功能模块划分(如用户管理、订单服务、支付模块)按技术或业务能力划分独立组件(如数…...
Python学习之Seaborn
Python学习之Seaborn 如果说Matplotlib试图让简单的事情变得容易,让困难的事情成为可能,那么Seaborn试图让一组定义明确的复杂的事情变得简单. Seaborn是在Matplotlib的基础上开发的高级可视化库, 它更专注于数据可视化的美学设计和统计图形的绘制. Matplotlib需要大量的代码创…...
【树莓派Pico FreeRTOS】-中断服务与二值信号量
中断服务与二值信号量 RP2040 由 Raspberry Pi 设计,具有双核 Arm Cortex-M0+ 处理器和 264KB 内部 RAM,并支持高达 16MB 的片外闪存。 广泛的灵活 I/O 选项包括 I2C、SPI 和独特的可编程 I/O (PIO)。 FreeRTOS 由 Real Time Engineers Ltd. 独家拥有、开发和维护。FreeRTO…...
QT采用cmake编译时文件解析
CMakeLists.txt # 设置版本要求 cmake_minimum_required(VERSION 3.16) # 设置项目名 project(QtWidgetsApplication3 LANGUAGES CXX)#设置C版本 set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON)find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) fi…...