java中为什么设计包装类,Java 中为什么要设计包装类

最近文章更新频率慢了,因为最近在准备暑期实习,之前寻思着一边复习一边写文章,两全其美。后来发现一篇读起来比较舒服的文章写出来加上配图得花上四五个小时甚至更多,但这个知识点我可能半个小时就能复习完了,春招在即,时间比较紧迫,所以最近文章可能改为一周一更或者一周两更,希望各位理解。另外,有和我一样在准备暑期实习的小伙伴可以联系我互相交流

全文脉络思维导图如下:

e921e7d989ae7fb1fc7fd42b70f5bb84.png

1. 为什么需要包装类

在 Java 中,万物皆对象,所有的操作都要求用对象的形式进行描述。但是 Java 中除了对象(引用类型)还有八大基本类型,它们不是对象。那么,为了把基本类型转换成对象,最简单的做法就是将基本类型作为一个类的属性保存起来,也就是把基本数据类型包装一下,这也就是包装类的由来。

这样,我们先自己实现一个简单的包装类,以包装基本类型 int 为例:// 包装类 MyInt

public class MyInt {

private int number; // 基本数据类型

public Int (int number){ // 构造函数,传入基本数据类型

this.number = number;

}

public int intValue(){ // 取得包装类中的数据

return this.number;

}

}

测试一下这个包装类:public static void main(String[] args) {

MyInt temp = new Int(100); // 100 是基本数据类型, 将基本数据类型包装后成为对象

int result = temp.intValue(); // 从对象中取得基本数据类型

System.out.println(result);

}

当然,我们自己实现的这个包装类非常简单,Java 给我们提供了更完善的内置包装类:基本类型对应的包装类(位于 java.lang 包中)byteByte

shortShort

intInteger

longLong

floatFloat

doubleDouble

charCharacter

booleanBoolean

前 6 个类派生于公共的超类 Number,而 Character 和 Boolean 是 Object 的直接子类。

来看看包装类的声明,以 Integer 为例:

dddd9b73fe8996f9a8ff45d6fb9aeef2.png

被 final 修饰,也就是说 Java 内置的包装类是无法被继承的。

2. 装箱与拆箱

OK,现在我们已经知道了,存在基本数据类型与其对应的包装类,那么,他们之间互相的转换操作就称为装箱与拆箱:装箱:将基本数据类型转换成包装类(每个包装类的构造方法都可以接收各自数据类型的变量)

拆箱:从包装类之中取出被包装的基本类型数据(使用包装类的 xxxValue 方法)

下面以 Integer 为例,我们来看看 Java 内置的包装类是如何进行拆装箱的:Integer obj = new Integer(10);  // 自动装箱

int temp = obj.intValue();  // 自动拆箱

可以看出,和上面我们自己写的包装类使用方式基本一样,事实上,Integer 中的这两个方法其底层实现和我们上述写的代码也是差不多的。

3bb4218fec607084134463ea44ea8218.png

不知道各位发现没,value 被声明为 final 了,也就是说一旦构造了包装器,就不允许更改包装在其中的值。

另外,需要注意的是,这种形式的代码是 JDK 1.5 以前的!!!JDK 1.5 之后,Java 设计者为了方便开发提供了自动装箱与自动拆箱的机制,并且可以直接利用包装类的对象进行数学计算。

还是以 Integer 为例我们来看看自动拆装箱的过程:Integer obj = 10;  // 自动装箱. 基本数据类型 int -> 包装类 Integer

int temp = obj;  // 自动拆箱. Integer -> int

obj ++; // 直接利用包装类的对象进行数学计算

System.out.println(temp * obj);

看见没有,基本数据类型到包装类的转换,不需要像上面一样使用构造函数,直接 = 就完事儿;同样的,包装类到基本数据类型的转换,也不需要我们手动调用包装类的 xxxValue 方法了,直接 = 就能完成拆箱。这也是将它们称之为自动的原因。

804b644453cca996733df1ef50106151.png

我们来看看这段代码反编译后的文件,底层到底是什么原理:Integer obj = Integer.valueOf(10);

int temp = obj.intValue();

可以看见,自动装箱的底层原理是调用了包装类的 valueOf 方法,而自动拆箱的底层调用了包装类的 intValue() 方法。

3. 不简单的 Integer.valueOf

我们上面已经看过了用于自动拆箱的 intValue 方法的源码,非常简单。接下来咱来看看用于自动装箱的 valueOf,其他包装类倒没什么好说的,不过 Integer 中的这个方法还是有点东西的:

7aae1022fb9d461c0aebdfdf3ba35dcb.png

IntegerCache 又是啥,点进去看看:

4283ab11e787700c4db5d6ed8360e106.png

IntegerCache 是 Integer 类中的静态内部类,综合这两段代码,我们大概也能知道,IntegerCache 其实就是个缓存,其中定义了一个缓冲区 cache,用于存储 Integer 类型的数据,缓存区间是 [-128, 127]。

回到 valueOf 的源码:它首先会判断 int 类型的实参 i 是否在可缓存区间内,如果在,就直接从缓存 IntegerCache 中获取对应的 Integer 对象;如果不在缓存区间内,则会 new 一个新的 Integer 对象。

结合这个特性,我们来看一个题目,两种类似的代码逻辑,但是却得到完全相反的结果。:public static void main(String args[]) {

Integer a1 = 127;

Integer a2 = 127;

System.out.println(a1 == a2); // true

Integer b1 = 128;

Integer b2 = 128;

System.out.println(b1 == b2); // false

}

我们知道,== 拥有两种应用场景:对于引用类型来说,判断的是内存地址是否相等

对于基本类型来说,判断的是值是否相等

从 a1 开始看,由于其值在 InterCache 的缓存区间内,所以这个 Integer 对象会被存入缓存。而在创建 a2 的时候,由于其值和 a1 相等,所以直接从缓存中取出值为 127 的 Integer 对象给 a2 使用,也就是说,a1 和 a2 这两个 Integer 的对象引用都指向同一个地址。

8d0e30c9ee4b74bfb9a6f2417e490128.png

对于 b1 和 b2 来说,由于 128 不在 IntegerCache 的缓存区间内,那就只能自己老老实实开辟空间了,所以 b1 和 b2 指向不同的内存地址。

很显然,由于 InterCache 缓存机制的存在,可能会让我们在编程的时候出现困惑,因此最好使用 .equals 方法来比较 Integer 值是否相等。Integer 重写了 .equals 方法:

1f5b97f3dca2197fbdd725629c54a7c9.png

当然,其他包装类虽然没有缓存机制,但是也都重载了 .equals 方法,用于根据值来判断是否相等。因此,得出结论,使用 equals 方法来比较两个包装类对象的值。

4. Object 类可以接收所有数据类型

综上,有了自动拆装箱机制,基本数据类型可以自动的被转为包装类,而 Object 是所有类的父类,也就是说,Object 可以接收所有的数据类型了(引用类型、基本类型)!!!

不信你可以试试,直接用 Object 类接收一个基本数据类型 int,完全是可以的。Object obj = 10;

int temp = (Integer) obj;

解释一下上面这段代码发生了什么,下面这张图很重要,大家仔细看:

48a500b49b3b2343c770e5a9b47581ad.png

5. 包装类在集合中的广泛使用

其实包装类最常见的使用就是在集合中,因为集合不允许存储基本类型的数据,只能存储引用类型的数据。那如果我们想要存储 1、2、3 这样的基本类型数据怎么办?举个例子,我们可以如下声明一个 Integer对象的数组列表:ArrayList list = new ArrayList<>();

往这个列表中添加 int 型数据:list.add(3);

上面这个调用在底层将会发生自动装箱操作:list.add (Integer.valueOf(3));

基本数据类型 int 会被转换成 Integer 对象存入集合中。

我们再来从这个集合中根据某个下标 i 获取对应的 Integer 对象,并用基本数据类型 int 接收:int n = list.get(i);

上面这个调用在底层将会发生自动拆箱操作:int n = list.get(i).intValue();

6. 数据类型转换

另外,除了在集合中的广泛应用,包装类还包含一个重要功能,那就是提供将String型数据变为基本数据类型的方法,使用几个代表的类做说明:

Integer:

30498cf0a2e4f4c7e86d53bf74c62995.png

Double:

de2b6d72a0a83b428907d8f5f633f69c.png

Boolean:

c008c3bd0179f3d188b78b7ae3773ab0.png

这些方法均被 static 标识,也就是说它们被各自对应的所有对象共同维护,直接通过类名访问该方法。举个例子:String str = "10";

int temp = Integer.parseInt(str);// String -> int

System.out.println(temp * 2); // 20

需要特别注意的是:Character 类里面并不存在字符串变为字符的方法,因为 String 类中已经有一个 charAt()的方法可以根据索引取出字符内容。

b7fdcdae9f89f1b263b9e1ed9534ae01.png

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

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

相关文章

bfc

BFC 已经是一个耳听熟闻的词语了&#xff0c;网上有许多关于 BFC 的文章&#xff0c;介绍了如何触发 BFC 以及 BFC 的一些用处&#xff08;如清浮动&#xff0c;防止 margin 重叠等&#xff09;。虽然我知道如何利用 BFC 解决这些问题&#xff0c;但当别人问我 BFC 是什么&…

Python语法异常 Exception

常见异常&#xff1a;Exception 所有异常的基类AttributeError 特性应用或赋值失败时引发IOError 试图打开不存在的文件时引发IndexError 在使用序列中不存在的索引时引发KeyError …

Python的Django框架中forms表单类的使用方法详解

Form Form的验证思路 前端&#xff1a;form表单 后台&#xff1a;创建form类&#xff0c;当请求到来时&#xff0c;先匹配&#xff0c;匹配出正确和错误信息。 Django的Form验证实例&#xff1a; 创建project&#xff0c;进行基础配置文件配置 settings.py settings.py之…

java读取gpx文件,从Leaflet导出GPX文件

我想要做的是让用户通过选择Leaflet中的一些GeoJson功能来创建GPX文件 . 我这样做的方法是创建一个新的GeoJson图层来存储所选的特征&#xff0c;然后用一个名为togpx(https://github.com/tyrasd/togpx)的插件将其转换为gpx . 现在我有一个gpx文件&#xff0c;但我没有t know h…

Mono Compatibility

The easiest way to describe what Mono currently supports is:Everything in .NET 4.5 except WPF, WWF, and with limited WCF and limited ASP.NET 4.5 async stack. System.Web and WCF are candidates for ‘almost immediate’ porting from the .NET reference source …

Python的Django框架中forms表单类的使用方法详解2

用户表单是Web端的一项基本功能,大而全的Django框架中自然带有现成的基础form对象,本文就Python的Django框架中forms表单类的使用方法详解。 Form表单的功能 自动生成HTML表单元素检查表单数据的合法性如果验证错误&#xff0c;重新显示表单&#xff08;数据不会重置&#xf…

生动形象的理解API是如何工作的!

API(Application Programming Interface,应用程序编程接口) 简单来说&#xff0c;就是其他人开发出来一块程序&#xff0c;你想用&#xff0c;他会告诉你调用哪个函数&#xff0c;给这个函数传什么参数&#xff0c;然后又会返回给你一个什么样的结果&#xff0c;你不需要知道他…

ann matlab,人工神经网络ann及其matlab仿真.ppt

人工神经网络ann及其matlab仿真人工神经网络 的研究方法及应用刘 长 安2004. 12. 31 引 言 利用机器模仿人类的智能是长期以来人们认识自然、改造自然和认识自身的理想。 研究ANN目的&#xff1a; (1)探索和模拟人的感觉、思维和行为的规律&#xff0c;设计具有人类智能的计算机…

字符串与树的结合

https://leetcode.com/problems/scramble-string/?tabDescription 虽然题目不常见&#xff0c;但是里面关于字符串调转和递归的思路&#xff0c;还是很有代表性的。 https://discuss.leetcode.com/topic/14337/share-my-4ms-c-recursive-solution/2 这个解法也把里面关于递归的…

ubuntu 安装过程所需软件

ubuntu 开发过程好用的软件 Remarkable 一个用于书写文档的好工具&#xff0c;包括方便书写数学公式。安装过程 点击上面“remarkable”下载.deb文件&#xff0c;然后双击会跳转到ubuntun的软件安装中心&#xff0c;点击install进行安装。 sublime text3 配置 自定义快捷键Pref…

Day05-循环和列表字符串、元组和字典

一、字符串 字符串就是由若干个不同的unicode字符组成的不可变序列 1 .字符串创建 #单引号字符串 str1 天要下雨&#xff0c;娘要嫁人&#xff0c;由他去吧 str2 str() #空串 str3 str([10,20,30]) ​ #双引号字符串 str2 "天要下雨&#xff0c;娘要嫁人&#xff…

@查看MySQL版本的方法

1.在终端下:mysql -V. [rootlocalhost bin]# mysql -V; mysql Ver 14.14 Distrib 5.6.21, for Linux (x86_64) using EditLine wrapper [rootlocalhost bin]# mysql -v; ERROR 1045 (28000): Access denied for user rootlocalhost (using password: NO) 注意&#xff0c;这…

echarts 柱状图 ,颜色和显示设置

最近在使用echart开发图标&#xff0c;api里面虽然有些设置&#xff0c;但是如果想让柱状图每个柱的颜色都不相同&#xff0c;简单的通过color设置是没有作用的&#xff0c;这里&#xff0c;就要用到其他的方式了 下面只是列举下我认为比较常用的&#xff0c;其他的比较简单&am…

Pycharm 专业版 导入系统pip安装的包

Pycharm 专业版 导入系统pip安装的包 在setting 中找到project interpeter ,点击设置图标&#xff0c;点击Add&#xff0c;得到如图所示选择 System Interpreter即可,这样 用pip安装的包都加再进来了

nodejs express

2019独角兽企业重金招聘Python工程师标准>>> 创建express服务器 //app.js文件 var express require(express); var app express(); //指定更目录显示的内容 app.get(/, function(req, res){ res.send(Hello World); }); //指定监听端口 var server app.listen(…

JS常见知识点

1、写一个按照下面方式调用都能正常工作的 sum 方法 console.log(sum(2,3)); // Outputs 5 console.log(sum(2)(3)); // Outputs 5 解决方案 function sum() {var fir arguments[0];if (arguments.length 2) {return arguments[0] arguments[1]} else {return function (sec…

格雷码 matlab,基于格雷码的结构光重建代码(MATLAB版本)

【实例简介】该代码为brown university相关技术人员编写&#xff0c;旨在用于学习研究3D结构光的原理、算法实现和应用。由于原有的网站( http://mesh.brown.edu/byo3d/index.html )近期无法访问&#xff0c;为了便于3D爱好者可以方便学习相关内容&#xff0c;特将该网站部分代…

Day06-函数

函数 一、集合&#xff08;set) 特点:不允许有重复元素&#xff0c;如果添加重复元素&#xff0c;则会自动过滤&#xff0c;可以进行交集、并集的运算。 本质&#xff1a;无序且无重复元素的数据结构 1 创建集合 s1 set() #空集合 不能是{}&#xff0c;这是字典 s2 {1…

在TextView中实时显示数据

//下面实时更新显示在textView中的数据handler new Handler();runnable new Runnable(){Overridepublic void run(){// TODO Auto-generated method pushupTextView.setText(Integer.toString(Number.pushup_number)); handler.postDelayed(this, 1000); }}; handle…

DuangDuangDuang!码云项目的 Readme.md 特殊技能

为什么80%的码农都做不了架构师&#xff1f;>>> 我们在 码云 上创建新项目的时候&#xff0c;常常会看到默认使用 README 文件初始化该项目&#xff08;如图1 所示&#xff09;&#xff0c;然后在新建项目的根目录下就会生成一个 README.md 文件&#xff08;如图2 …