【Java 温故而知新系列】基础知识-03 基本类型对应之包装类

news/2025/1/7 14:10:19/文章来源:https://www.cnblogs.com/zhulu/p/18630455

1、包装类都有哪些?

基本类型都有对应的包装类型,这些包装类提供了一种面向对象的方式来处理基本数据类型,允许它们被用于需要对象的场景,如集合框架、泛型等。

对应关系:

基本类型包装类型
boolean Boolean
byte Byte
char Character
float Float
int Integer
long Long
short Short
double Double

2、包装类特点

  • 封装性:所有的包装类都是 final 类,这意味着它们不能被继承。这种设计确保了包装类的行为和特性的一致性,从而避免了子类可能引入的不确定性。
  • 不可变性:包装类的实例一旦被创建后,其中保存的基本数据类型数据就不能再被改变。这种不可变性使得包装类在多线程环境中更加安全,避免了因数据被意外修改而导致的错误。
  • 提供方法:包装类封装了许多实用的方法,提供了丰富的功能。例如,它们支持数据类型转换、判断字符串的大小写、以及获取最大值和最小值等。
  • 继承关系:除了 Character 和 Boolean 之外,其他所有的包装类都继承自 Number 类。这种继承关系使得这些包装类能够共享一些通用的功能和特性,例如数字的比较和转换,这为在不同数值类型之间的操作提供了一致的接口。

代码为证(继承Number类并实现intValue方法的类):

 

 3、为什么会出现包装类?

既然有基本类型了,为什么还会出现对应的包装类?

我觉得根本原因还是因为Java是面向对象的语言,基本数据类型不能参与面向对象编程:

对象操作:在Java中,许多集合类和框架方法需要对象作为参数,而不是基本数据类型。为了满足这一需求,包装类提供了将基本数据类型转换为对象的机制。通过使用包装类,我们可以轻松地在这些方法中传递基本数据类型。

Null值处理:基本数据类型无法为null,而包装类则可以。这一特性在某些情况下非常有用,例如在方法参数中,需要表示可选值或缺省值时。通过使用包装类,我们能够更灵活地处理这些场景,确保代码的健壮性和可读性。这种设计使得我们在处理数据时,可以更方便地进行null值检查,并在需要时安全地进行区分,从而提高了代码的灵活性。

 4、装箱与拆箱

装箱(Boxing):是将基本数据类型转换为相应的包装类的过程。

拆箱(Unboxing):是将包装类转换为基本数据类型的过程。

手动装箱、拆箱

手动装箱:使用一个本地类型的值创建一个对应包装类对象的过程

1 int num = 10;
2  
3 Integer int1 = new Integer(num); // 手动装箱方式一
4  
5 Integer int2 = Integer.valueOf(num); // 手动装箱方式二

 

手动拆箱:使用 Integer 类型对象的 intValue() 方法来获取这个对象的 int 值

1 Integer number= new Integer(23);
2 int num = number.intValue(); // 手动拆箱

 

自动装箱、拆箱

Java 5引入了自动装箱(Auto-boxing)和自动拆箱(Auto-unboxing)机制,简化了基本数据类型与包装类之间的转换过程。

自动装箱是将基本数据类型自动转换为其对应的包装类对象的过程。自动装箱的底层原理其实就是通过调用包装类的valueOf()方法来实现的;同理自动拆箱就是通过调用包装类的xxxValue()方法来实现的。

以Integer 与 int 举例:

 Integer x = 2;     // 装箱 调用了 Integer.valueOf(2)int y = x;         // 拆箱 调用了 x.intValue()

5、包装类的缓存池

简要介绍

Java中的包装类缓存机制是为了优化性能和节省内存而设计的。

它为整型(Byte、Short、Integer、Long)、字符型(Character)和布尔型(Boolean)的包装类提供了缓存,确保在这些类型的小范围值之间可以复用对象。而对于浮点数类型的包装类(Float、Double),则没有这种缓存机制,意味着每次都需要创建新的对象。

这样一来,Java在处理常用值时更加高效,但在浮点数处理上则相对简单直接。

缓存范围

对于 Integer 类,Java会缓存范围在 -128 到 127 之间的所有整数。

对于 Byte、Short 和 Character 类,缓存的范围也是类似的。具体范围如下:

Byte:-128 到 127
Short:-128 到 127
Character:0 到 127(即所有的ASCII字符)
Boolean:只有 true 和 false 两个值会被缓存。

如何触发缓存

只有调用 valueOf() 方法时,如果要创建的值已经被缓存,则会触发缓存机制。如果要创建的 Integer 对象的值在预定范围内,则返回缓存的对象,如果不在范围内,则直接新创建一个对象。

我们来查看 Integer 类的 valueOf() 方法的源代码(valueOf() 方法就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容,不存在就创建一个新对象,跟上面我们所说的逻辑是一致):

 1     /**2      * Returns an {@code Integer} instance representing the specified3      * {@code int} value.  If a new {@code Integer} instance is not4      * required, this method should generally be used in preference to5      * the constructor {@link #Integer(int)}, as this method is likely6      * to yield significantly better space and time performance by7      * caching frequently requested values.8      *9      * This method will always cache values in the range -128 to 127,
10      * inclusive, and may cache other values outside of this range.
11      *
12      * @param  i an {@code int} value.
13      * @return an {@code Integer} instance representing {@code i}.
14      * @since  1.5
15      */
16     public static Integer valueOf(int i) {
17         if (i >= IntegerCache.low && i <= IntegerCache.high)
18             return IntegerCache.cache[i + (-IntegerCache.low)];
19         return new Integer(i);
20     }

  编译器会在自动装箱过程调用 valueOf() 方法,因此多个值相同且值在缓存池范围内的 Integer 实例使用自动装箱来创建,那么就会引用相同的对象。

1 Integer m = 123;
2 Integer n = 123;
3 System.out.println(m == n); // true

在 Java 8 中,Integer 缓存池的大小默认为 -128~127。

在 jdk 1.8 所有的数值类缓冲池中,Integer 的缓冲池 IntegerCache 很特殊,这个缓冲池的下界是 - 128,上界默认是 127,但是这个上界是可调的,在启动 jvm 的时候,通过 -XX:AutoBoxCacheMax=<size> 来指定这个缓冲池的大小,该选项在 JVM 初始化的时候会设定一个名为 java.lang.IntegerCache.high 系统属性,然后 IntegerCache 初始化的时候就会读取该系统属性来决定上界。

下面是IntegerCache的源码(其中红色部分正是获取系统属性重新设置上界的逻辑)

 1     private static class IntegerCache {
 2         static final int low = -128;
 3         static final int high;
 4         static final Integer cache[];
 5 
 6         static {
 7             // high value may be configured by property
 8             int h = 127;
 9             String integerCacheHighPropValue =
10                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
11             if (integerCacheHighPropValue != null) {
12                 try {
13                     int i = parseInt(integerCacheHighPropValue);
14                     i = Math.max(i, 127);
15                     // Maximum array size is Integer.MAX_VALUE
16                     h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
17                 } catch( NumberFormatException nfe) {
18                     // If the property cannot be parsed into an int, ignore it.
19                 }
20             }
21             high = h;
22 
23             cache = new Integer[(high - low) + 1];
24             int j = low;
25             for(int k = 0; k < cache.length; k++)
26                 cache[k] = new Integer(j++);
27 
28             // range [-128, 127] must be interned (JLS7 5.1.7)
29             assert IntegerCache.high >= 127;
30         }
31 
32         private IntegerCache() {}
33     }

 

验证包装类的缓存池(以Integer为例)

 

1 Integer x = new Integer(123);
2 Integer y = new Integer(123);
3 System.out.println(x == y);    // false
4 Integer z = Integer.valueOf(123);
5 Integer k = Integer.valueOf(123);
6 System.out.println(z == k);   // true

 

 

6、补充

基本类型与包装类如何选择

  • 内存占用和性能:基本数据类型直接在栈中分配内存,占用空间较少,性能更高。而包装类是对象类型,需要在堆中分配内存,GC管理,因此会稍微影响性能
  • 使用场景:一般来说,在性能要求较高的代码中,我们优先使用基本数据类型。而在需要面向对象的场景下(例如集合类中需要使用对象类型),我们会选择包装类。包装类还提供了一些静态方法和常量,比如Integer.parseInt()、Double.NaN等,这些方法和属性是基本数据类型所不具备的

基本类型与包装类==比较:

只要判断中有基本数据类型,则判断的就是值是否相等,也就是说包装类在这时会自动拆箱。

 

1 public class Example {
2     public static void main(String[] args) {
3         Integer i1 = 10;
4         int i2 = 10;
5  
6         System.out.println(i1 == i2);
7     }
8 }

 

基本类型与包装类存储区别(基本类型(primitive types)和包装类的存储位置取决于它们是在哪里声明): 

 

局部变量(Local Variables)

栈(Stack):如果基本类型是作为方法中的局部变量声明的,那么它们会被存储在栈中。栈用于管理方法调用和局部变量,具有后进先出(LIFO)的行为。自动分配和释放:当方法被调用时,其局部变量会在栈上分配空间,并且在方法执行完毕后自动释放。

成员变量(Instance Variables)

堆(Heap):如果基本类型是类的成员变量(即实例变量),那么它们会随着对象一起被存储在堆中。每个对象都有自己的成员变量副本,这些数据与对象本身一同存放在堆内存中。生命周期依赖于对象:成员变量的生命周期与所属的对象相同,只要对象存在,成员变量就存在;对象被垃圾回收时,成员变量也会被回收。

静态变量(Static Variables)

方法区/元空间(Method Area/Metaspace):静态变量(无论是否为基本类型)属于类的一部分,而不是某个特定的对象实例。它们通常存储在方法区(Java 7及之前)或元空间(Java 8及之后)。不过,在某些实现中,静态变量也可能直接存放在堆中,因为方法区本身可以被视为堆的一部分。
共享性:静态变量由所有对象实例共享,因此它们不是随单个对象创建而创建,而是随着类加载到 JVM 时初始化 。

代码举例:

 1 public class Example {
 2     // 成员变量,存储在堆中
 3     int instanceVar;
 4 
 5     // 静态变量,存储在方法区或元空间
 6     static int staticVar;
 7 
 8     public void method() {
 9         // 局部变量,存储在栈中
10         int localVar = 10;
11     }
12 }

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[深度学习] 大模型学习1-大语言模型基础知识

大语言模型(Large Language Model,LLM)是一类基于Transformer架构的深度学习模型,主要用于处理与自然语言相关的各种任务。简单来说,当用户输入文本时,模型会生成相应的回复或结果。它能够完成许多任务,如文本续写、分类、摘要、改写、翻译等。常见的LLM包括GPT、LLaMA等…

昆明理工大学材料调剂参考书-材料测试

昆明理工大学材料调剂昆明理工大学材料调剂

小程序信息收集

引子:本章对常见的小程序信息收集方式做一介绍。免责声明:本文章仅用于交流学习,因文章内容而产生的任何违法&未授权行为,与文章作者无关!!! 附:完整笔记目录~ ps:本人小白,笔记均在个人理解基础上整理,若有错误欢迎指正! 四、小程序信息收集引子:本章对常见的…

2025 胜券在握

这两天我看了一部电影《胜券在握》,这是一部年末由刘循子墨执导,邓超、邓家佳等主演的电影,讲述了一个关于35岁裁员后,通过人工智能创业的故事。该片讲述了在科技公司工作了十年的元老级员工白胜被暴力开除,手握高期权却无法兑现的他暗设骗局,试图重回公司,只为苟住100天…

2024总结与展望--Empirefree

26岁的今年总是惊喜与遗憾伴随我的一年目录🔥1. 年终总结1.1.学习计划1.2. 生活计划1.3 个人总结🔥2. 未来展望 🔥1. 年终总结 1.1.学习计划 ​ 今年没有学习,在弄公司业务,感觉自己涉及的业务面还是很浅,熟悉了不少的业务。 1.2. 生活计划身体锻炼:拉胯,今年身体锻…

某某书主页参数加密分析

主页:aHR0cHM6Ly93d3cueGlhb2hvbmdzaHUuY29tL2V4cGxvcmU= 打开某某书主页,打开浏览器开发者工具,随便点击一个主页tab栏,如影视,找到相关接口为: aHR0cHM6Ly9lZGl0aC54aWFvaG9uZ3NodS5jb20vYXBpL3Nucy93ZWIvdjEvaG9tZWZlZWQ= 根据测试,需逆向请求头中的 X-S 参数,全局搜…

Gamma阶段——第15周Scrum Meeting记录

Gamma阶段——第15周Scrum Meeting记录 1.目前进度: (1)完成游戏整体开发,修复部分BUG,可以初步实现面向玩家的使用; (2)进行集成测试,查找不足; (3)邀请部分玩家参与测试以更好的优化软件 2.目前团队中存在的问题: (1)未能及时同步工作进度,导致需要额外花时间…

MQTT不同ClientID订阅同一个topic消息独立接收

EMQX 使用宝塔安装的docker版本的emqx(Docker应用) 1.0.1 方案一(弃用):mountpoint 旧版本中的配置项,用于为客户端的 MQTT 消息主题动态添加前缀(如客户端 ID)。这一功能在 EMQX 4.x 版本中有效,但在 EMQX 5.x 中被废弃,原因是 EMQX 5.x 的架构和配置方式全面升级,不…

AppGallery编辑推荐:带来应用探索新风尚

近日,原生鸿蒙应用市场发布的“AppGallery Awards 年度影响力应用与游戏”近日隆重揭晓,标志着原生鸿蒙应用市场在用户体验、视觉设计、创新实践等方面迈出了重要一步。 此次年度奖项的评选与发布,依托于AppGallery全新推出的“编辑推荐”机制,即由编辑团队从专业视角精选优…

Web 前端面试指南与高频考题解析

Web 前端面试指南与高频考题解析 准备:简历编写和面试前准备 一般来说,跳槽找工作要经历投递简历、准备面试、面试和谈 offer 四个阶段。其中面试题目会因你的等级和职位而异,从入门级到专家级,广度和深度都会有所增加。不过,不管什么级别和职位,面试题目一般都可以分类为…

内华达大地测量实验室gnss数据半自动化下载

内华达大地测量实验室GNSS数据半自动化下载 前言目的:继上篇GNSS时序形变位移数据下载,介绍了内华达网站GNSS位移数据如何手动交互进行下载。后面发现若自己需要下载很多站点的数据,我要通过手动一个个去点击下载不太方便。为此自己设计了一个根据站点名字文本文件进行批量下…

促销系统:促销业务详解

大家好,我是汤师爷~ 促销活动的核心价值在于利用价格优势吸引贪便宜的消费者。许多用户会积极寻找各类优惠,看到红包或折扣时容易产生购买冲动。 对商家而言,促销是快速清理库存的有效工具。特别是对于季节性商品或临期产品,促销能加快出货速度。同时,促销也能提升销售额,…