【✅Java中有了基本类型为什么还需要包装类?】

news2024/10/5 16:32:57

在这里插入图片描述

✅Java中有了基本类型为什么还需要包装类?

  • ✅Java中有了基本类型为什么还需要包装类
    • ✅Java的8中基本数据类型
  • ✅知识拓展
    • ✅基本类型和包装类型的区别
    • ✅如何理解自动拆装箱?
      • ✅拆箱与装箱
      • ✅自动拆装箱
      • ✅自动拆装箱原理
    • ✅哪些地方会自动拆装箱?
      • 🍁场景一:将基本数据类型放入集合类
      • 🍁场景二:包装类型和基本类型的大小比较
      • 🍁场景三:包装类型的运算
      • 🍁场景四:三目运算符的使用
      • 🍁场景五:函数参数与返回值
    • ✅自动拆装箱与缓存

✅Java中有了基本类型为什么还需要包装类

✅Java的8中基本数据类型

Java中的8中基本数据类型,这些基本类型又都有对应的包装类。看一下表格:

数据类型分类描述取值范围示例包装类对应长度
byte整数类型8位有符号二进制整数-128 到 127byte a = -50;Byte1字节
short整数类型16位有符号二进制整数-32768 到 32767short b = 10000;Short2字节
int整数类型32位有符号二进制整数-2^31 到 2^31-1int c = -20000;Integer4字节
long整数类型64位有符号二进制整数-2^63 到 2^63-1long d = 1000000000L;Long8字节
float小数类型单精度浮点数(32位IEEE 754)由IEEE 754标准定义,约±3.4E±38Ffloat e = 3.14f;Float4字节(IEEE 754单精度浮点数)
double小数类型双精度浮点数(64位IEEE 754)由IEEE 754标准定义,约±1.7E±308Ddouble f = 2.71828D;Double8字节(IEEE 754双精度浮点数)
char字符类型16位Unicode字符(UTF-16编码)U+0000 到 U+FFFF(包括Unicode字符和特殊字符)char g = ‘A’; char h = ‘\u0041’;Character2字节(UTF-16编码)
boolean布尔类型布尔类型,只能取两个值:true和falsetrue 或 falseboolean i = true; boolean j = false;Boolean-(布尔类型的长度不固定)

因为Java是一种面向对象语言,很多地方都需要使用对象而不是基本数据类型。比如,在集合类中,我们是无法将int、double等类型放进去的。因为集合的容器要求元素是Obiect类型。


为了让基本类型也具有对象的特征,就出现了包装类型,它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,主富了基本类型的操作。

✅知识拓展

✅基本类型和包装类型的区别

基本类型和包装类型在Java中有着明显的区别。以下是一些主要的差异:

基本类型

  • 它们是简单的数据类型,用于存储基础值,如整数、浮点数、字符等。
  • 它们的值直接存储,不包含任何额外的信息。
  • 它们是原始数据类型,没有方法,只有一些预定义的操作。

包装类型:

  • 包装类型是基本类型的类表示。
  • 包装类型提供了对基本类型的封装,可以防止数据的直接访问和修改。
  • 包装类型可以包含方法,扩展了基本类型的功能。

总而言之:
1.默认值不同,基本类型的默认值为0,false或 u0000等,包装类默认为null
2.初始化方式不同,一个需要new,一个不需要
3.存储方式不同,基本类型保存在栈上,包装类对象保存在堆上(成员变量的话,在不考虑川T优化的栈上分配时,都是随着对象一起保存在堆上的)

public class DataTypeMain {  
    public static void main(String[] args) {  
        // 基本类型  
        int basicInt = 10;  
        System.out.println("基本类型的值: " + basicInt);  
          
        // 包装类型  
        Integer wrappedInt = new Integer(10);  
        System.out.println("包装类型的值: " + wrappedInt);  
          
        // 包装类型的方法  
        wrappedInt = wrappedInt + 5; // 使用包装类型的加法方法  
        System.out.println("包装类型的新值: " + wrappedInt);  
          
        // 基本类型不能直接进行加法操作,需要手动转换包装类型为基本类型,再执行加法操作  
        basicInt = basicInt + (int) wrappedInt;  
        System.out.println("基本类型的新值: " + basicInt);  
          
        // 装箱和拆箱操作  
        Integer boxedInt = basicInt; // 装箱操作,将基本类型转换为包装类型  
        System.out.println("装箱后的值: " + boxedInt);  
          
        int unboxedInt = (int) boxedInt; // 拆箱操作,将包装类型转换为基本类型  
        System.out.println("拆箱后的值: " + unboxedInt);  
    }  
}

✅如何理解自动拆装箱?

✅拆箱与装箱

包装类是对基本类型的包装,所以,把基本数据类型转换成包装类的过程就是装箱,反之,把包装类转换成基本数据类型的过程就是拆箱

看一段代码:

// 装箱  
Integer boxedInt = 10; // 将基本类型int转换为包装类Integer  
  
// 拆箱  
int unboxedInt = boxedInt; // 将包装类Integer转换为基本类型int

在这个例子中,我们将一个基本类型int的值10赋值给一个包装类Integer的变量boxedInt。由于Java的类型转换机制,我们可以将基本类型的值直接赋值给包装类的变量,这就是装箱过程。

接下来,我们将一个包装类Integer的变量boxedInt赋值给一个基本类型int的变量unboxedInt。由于Java的类型转换机制,我们可以将包装类的值直接赋值给基本类型的变量,这就是拆箱过程。

需要注意的是,在进行装箱和拆箱操作时,Java会自动进行类型转换。但是,如果基本类型的值超出了包装类所能表示的范围,那么会发生溢出或下溢的情况。因此,在进行装箱和拆箱操作时,需要注意数据类型的范围和溢出问题。

✅自动拆装箱

在Java SE5中,为了减少开发人员的工作作,Java提供了自动拆箱与自动装箱功能。


自动装箱 : 就是将基本数据类型自动转换成对应的包装类。

自动拆箱: 就是将包装类自动转换成对应的基本数据类型。

看一段代码:

import java.util.Scanner;  
  
public class AdvancedCalculator {  
    public static void main(String[] args) {  
        Scanner scanner = new Scanner(System.in);  
          
        System.out.print("请输入第一个数字:");  
        Integer num1 = scanner.nextInt(); // 自动装箱  
          
        System.out.print("请输入第二个数字:");  
        Integer num2 = scanner.nextInt(); // 自动装箱  
          
        System.out.println("请选择运算:");  
        System.out.println("1. 加法");  
        System.out.println("2. 减法");  
        System.out.println("3. 乘法");  
        System.out.println("4. 除法");  
          
        int operation = scanner.nextInt(); // 自动装箱  
          
        switch (operation) {  
            case 1: // 加法  
                Integer result = add(num1, num2); // 自动拆箱,将Integer对象转换为int值进行加法运算  
                System.out.println("加法结果为:" + result); // 自动装箱,将int值转换为Integer对象输出  
                break;  
            case 2: // 减法  
                result = subtract(num1, num2); // 自动拆箱,将Integer对象转换为int值进行减法运算  
                System.out.println("减法结果为:" + result); // 自动装箱,将int值转换为Integer对象输出  
                break;  
            case 3: // 乘法  
                result = multiply(num1, num2); // 自动拆箱,将Integer对象转换为int值进行乘法运算  
                System.out.println("乘法结果为:" + result); // 自动装箱,将int值转换为Integer对象输出  
                break;  
            case 4: // 除法  
                result = divide(num1, num2); // 自动拆箱,将Integer对象转换为int值进行除法运算  
                System.out.println("除法结果为:" + result); // 自动装箱,将int值转换为Integer对象输出  
                break;  
            default:  
                System.out.println("无效的运算选择!");  
                break;  
        }  
    }  
      
    public static Integer add(Integer a, Integer b) {  
        return a + b; // 自动拆箱,将输入的两个Integer对象转换为int值进行加法运算  
    }  
      
    public static Integer subtract(Integer a, Integer b) {  
        return a - b; // 自动拆箱,将输入的两个Integer对象转换为int值进行减法运算  
    }  
      
    public static Integer multiply(Integer a, Integer b) {  
        return a * b; // 自动拆箱,将输入的两个Integer对象转换为int值进行乘法运算  
    }  
      
    public static Integer divide(Integer a, Integer b) {  
        if (b == 0) { // 检查除数是否为零,避免出现异常情况  
            System.out.println("除数不能为零!");  
            return null; // 返回null表示除法运算失败  
        } else {  
            return a / b; // 自动拆箱,将输入的两个Integer对象转换为int值进行除法运算,并返回结果  
        }  
    }  
}

在上面的示例中,使用Java的自动装箱和拆箱机制,将用户输入的int值转换为Integer对象,并在计算结果时将Integer对象转换为int值输出。在add、subtract、multiply和divide方法中,我们将输入的两个Integer对象转换为int值进行相应的运算,并返回结果。在divide方法中,我们还需要检查除数是否为零,以避免出现异常情况。这个过程就是自动拆箱的过程。



✅自动拆装箱原理

自动装箱都是通过包装类的 value0f() 方法来实现的自动拆箱都是通过包装类对象的 xxxValue()来实现的。


如: int的自动装箱都是通过 Integer.value0f() 方法来实现的,Integer的自动拆箱都是通过 nteger.intValue()来实现的。

✅哪些地方会自动拆装箱?


我们了解过原理之后,在来看一下,什么情况下,Java会帮我们进行自动拆装箱。前面提到的变量的初始化和赋值的场景就不个绍了,那是最简单的也最容易理解的。
我们主要来看一下,那些可能被忽略的场景。

🍁场景一:将基本数据类型放入集合类


我们知道,Java中的集合类只能接收对象类型,那么以下代码为什么会不报错呢?
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i ++){
	li.add(i);
}

将上面代码进行反编译,可以得到以下代码:

List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50, i ++){
	li.add(Integer.value0f(i));
}

以上,我们可以得出结论,当我们把基本数据类型放入集合类中的时候,会进行自动装箱。

🍁场景二:包装类型和基本类型的大小比较


有没有人想过,当我们对Integer对象与基本类型进行大小比较的时候,实际上比较的是什么内容呢? 看以下代码:
Integer a=1;
System.out.println(a==1?"等于":"不等于");
Boolean bool=false;
System.out.printIn(bool?"真":"假");

对以上代码进行反编译,得到以下代码:

Integer a=1;
System.out.println(a.intValue()==1?"等于":"不等于");
Boolean bool=false;
Svstem.out.println(bool.booleanValue?"真":"假");

可以看到,包装类与基本数据类型进行比较运算,是先将包装类进行拆箱成基本数据类型,然后进行比较的。

🍁场景三:包装类型的运算


有没有人想过,当我们对Integer对象进行四则运算的时候,是如何进行的呢? 看以下代码:
Integer i = 10;
Integer j = 20;

System.out.println(i+j);

反编译以后:

Integer i= Integer.value0f(10);
Integer j = Integer.valueOf(20);
System.out.println(i.intValue() + j.intValue());

我们发现,两个包装类型之间的运算,会被自动拆箱成基本类型进行。

🍁场景四:三目运算符的使用


这是很多人不知道的一个场景,作者也是一次线上的血淋淋的Bug发生后才了解到的一种案例。看一个简单的三目运算符的代码:

boolean flag = true; //设置成true,保证条件表达式的表达式二一定可以执行
boolean simpleBoolean = false; //定义一个基本数据类型的boolean变量
Boolean nullBoolean = null;//定义一个包装类对象类型的Boolean变量,值为null


boolean x = flag ? nullBoolean : simpleBoolean; //使用三目运算符并给x变量赋值

很多人不知道,boolean x = flag ? nullBoolean : simpleBoolean ;这一行,会发生自动拆箱。反编译后代码如下:

boolean flag = true;
boolean simpleBoolean = false;
Boolean nu11Boolean = null;
boolean x = flag ? nullBoolean.booleanValue() : simpleBoolean;

这其实是三目运算符的语法规范。当第二,第三位操作数分别为基本类型和对象时,其中的对象就会拆箱为基本类型进行操作。
可以看到,反编译后的代码的最后一行,编译器帮我们做了一次自动拆箱,而就是因为这次自动拆箱,导致代码出现对于一个null对象 (nullBoolean.booleanValue0) 的调用,导致了NPE。

🍁场景五:函数参数与返回值


这个比较容易理解,这季节上代码哈。
//自动拆箱
public int getNum1(Integer num) {
	return num;
}

//自动装箱
public Integer getNum2(int num) {
	return num;
}

✅自动拆装箱与缓存


Java SE的自动拆装箱还提供了一个和缓存有关的功能,我们先来看以下代码,猜测一下输出结果:
public static void main(String... strings) {
	
	Integer integer1 = 3;
	Integer integer2 = 3;

	if (integer1 == integer2)//这里省略了大括号是可以的
		System.out.println("integer1 == integer2") ;
	else
		System.out.println("integer1 != integer2");

	Integer integer3 = 300;
	Integer integer4 = 300;

	if (integer3 == integer4)
		System.out.println("integer3 == integer4");
	else
		System.out.println("integer3 != integer4");
	
}

我们普遍认为上面的两人判新的结果都是talse。虽然比较的值是相等的,但是由于比较的是对象,而对象的引用不一样,所以会认为两个i判断都是false的。在Java中,==比较的是对象用,而equals比较的是值。所以,在这个例子中,不同的对象有不同的引用,所以在进行比较的时候都将返回false。奇怪的是,这里两个类似的i条件判断返回不同的布尔值。

上面这段代码真正的输出结果:
在这里插入图片描述
原因就和Integer中的缓存机制有关。在Java 5中,在nteger的操作上引入了一个新功能来节省内存和提高性能。
整型对象通过使用相同的对象引用实现了缓存和重用。

适用于整数值区间 -128 至 +127





只适用于自动装箱,使用构造函数创建对象不适用。

我们只需要知道,当需要进行自动装箱时,如果数字在-128至127之间时,会直接使用缓存中的对象,而不是重新创建个对象。


其中的javadoc详细的说明了缓存支持-128到127之间的自动装箱过程。最大值127可以通过 -XX:AutoBoxCacheMax=size 修改。


实际上这个功能在Java 5中引入的时侯;范围是固定的-128至 +127。后来在Java 6中,可以通过 java.lang.Integer.IntegerCache.high 设置最大值。


这使我们可以根据应用程序的实际情况灵活地调整来提高性能。到底是什么原因选择这个-128到127范围呢?因为这个范围的数字是最被广泛使用的。在程序中,第一次使用Integer的时候也需要一定的额外时间来初始化这个缓
存。


在Boxing Conversion部分的Java语言规范(LS)规定如下:


如果一个变量p的值是:

-128127之间的整数(S3.19.1)

truefalse的布尔值 (s3.10.3)

'\u8808''\u897F'之间的字符(§3.19.4)

范围内的时,将p包装成a和b两个对象时,可以直接使用a==b判断a和b的值是否相等。

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

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

相关文章

10-高并发-应用级缓存

缓存简介 缓存&#xff0c;是让数据更接近于使用者&#xff0c;目的是让访问速度更快。 工作机制是先从缓存中读取数据&#xff0c;如果没有&#xff0c;再从慢速设备上读取实际数据并同步到缓存。 那些经常读取的数据、频繁访问的数据、热点数据、I/O瓶颈数据、计算昂贵的数…

算法基础之约数个数

约数个数 核心思想&#xff1a; 用哈希表存每个质因数的指数 然后套公式 #include <iostream>#include <algorithm>#include <unordered_map>#include <vector>using namespace std;const int N 110 , mod 1e9 7;typedef long long LL; //long l…

移动安全APP--Frida+模拟器,模拟器+burp联动

最近测APP被通报了&#xff0c;问题点测得比较深&#xff0c;涉及到frida和burp抓包&#xff0c;一般在公司可能会有网络的限制&#xff0c;手机没办法抓包&#xff0c;我就直接在模拟器上试了&#xff0c;就在这记录一下安装过程。 目录 一、Frida安装 二、burp与逍遥模拟器…

MySQL是如何保证数据不丢失的?

文章目录 前言Buffer Pool 和 DML 的关系DML操作流程加载数据页更新记录 数据持久化方案合适的时机刷盘双写机制日志先行机制日志刷盘机制Redo Log 恢复数据 总结 前言 上篇文章《InnoDB在SQL查询中的关键功能和优化策略》对InnoDB的查询操作和优化事项进行了说明。但是&#…

STM32F4的DHT11初始化与实例分析

STM32—— DHT11 本文主要涉及STM32F4 的DHT11的使用以及相关时序的介绍&#xff0c;最后有工程下载地址。 文章目录 STM32—— DHT11一、 DHT11的介绍1.1 DHT11的经典电路 二、DHT11的通信2.1 DHT11的传输数据格式2.2 DHT11 通信分步解析 三、 DHT11 代码3.1 引脚图3.2 电路图…

污水处理厂可视化:让环保与科技共舞

随着科技的飞速发展&#xff0c;我们的生活环境变得越来越美好。然而&#xff0c;随着城市化进程的加快&#xff0c;污水处理问题也日益凸显。如何有效、高效地处理污水&#xff0c;成为了一个亟待解决的问题。而“污水处理厂可视化”技术的出现&#xff0c;为这个问题提供了一…

隐藏通信隧道技术——防御DNS隧道攻击

隐藏通信隧道技术——防御DNS隧道攻击 DNS协议 ​ DNS协议是一种请求/应答协议&#xff0c;也是一种可用于应用层的隧道技术。虽然激增的DNS流量可能会被发现&#xff0c;但是基于传统Socket隧道已经濒临淘汰及TCP、UDP通信大量被防御系统拦截的状况&#xff0c;DNS、ICMP、H…

第二十二章 : Spring Boot 集成定时任务(一)

第二十二章 &#xff1a; Spring Boot 集成定时任务&#xff08;一&#xff09; 前言 本章知识点&#xff1a; 介绍使用Spring Boot内置的Scheduled注解来实现定时任务-单线程和多线程&#xff1b;以及介绍Quartz定时任务调度框架&#xff1a;简单定时调度器&#xff08;Simp…

QT中网络编程之发送Http协议的Get和Post请求

文章目录 HTTP协议GET请求POST请求QT中对HTTP协议的处理1.QNetworkAccessManager2.QNetworkRequest3.QNetworkReply QT实现GET请求和POST请求Get请求步骤Post请求步骤 测试结果 使用QT的开发产品最终作为一个客户端来使用&#xff0c;很大的一个功能就是要和后端服务器进行交互…

使用代理服务器和Beautiful Soup爬取亚马逊

概述 Beautiful Soup 是一个用于解析 HTML 和 XML 文档的 Python 库&#xff0c;它能够从网页中提取数据&#xff0c;并提供了一些简单的方法来浏览文档树、搜索特定元素以及修改文档的内容。在本文中&#xff0c;我们将介绍如何使用代理服务器和Beautiful Soup库来爬取亚马逊…

nginx 离线安装 https反向代理

这里写自定义目录标题 安装步骤1.安装nginx所需依赖1.1 安装gcc和gcc-c1.1.1下载依赖包1.1.2 上传依赖包1.1.3安装依赖 1.2 安装pcre1.2.1 下载pcre1.2.2 上传解压安装包1.2.3 编译安装 1.3 下载安装zlib1.3.1 下载zlib1.3.2 上传解压安装包1.3.3 编译安装 1.4 下载安装openssl…

UG扫掠体与部件导航器的使用

扫掠体命令的本质在我看来&#xff0c;就是用一个道具沿着轨迹线在选中的实体中进行加工&#xff0c;切除相应部分&#xff1b; 有如下原则 扫掠体&#xff1a; 引导线必须光顺相切&#xff0c;不能有尖角 工具体&#xff1a; 1、必须为单个的实体&#xff0c;不能有孔或内…

[NISACTF 2022]babyserialize

[NISACTF 2022]babyserialize 题目做法及思路解析&#xff08;个人分享&#xff09; 题目平台地址&#xff1a;NSSCTF | 在线CTF平台 一、题目代码 查看分析代码&#xff0c;寻找漏洞点&#xff08;题目中注释为个人思路标注&#xff0c;实际代码中没有&#xff09; …

每日一题,二维平面

给你 二维 平面上两个 由直线构成且边与坐标轴平行/垂直 的矩形&#xff0c;请你计算并返回两个矩形覆盖的总面积。 每个矩形由其 左下 顶点和 右上 顶点坐标表示&#xff1a; 第一个矩形由其左下顶点 (ax1, ay1) 和右上顶点 (ax2, ay2) 定义。 第二个矩形由其左下顶点 (bx1, …

牛客小白月赛78(C: 第K小表示数)

C-第K小表示数_牛客小白月赛78 (nowcoder.com) 问题&#xff1a; 分析: k的极限是1e6,因此要几乎O(n)的时间复杂度给求出来&#xff0c;还需要每插入一个元素我都要去排序&#xff0c;这个时候set就派上用场了&#xff0c;自带排序和去重,集合里面最小和第二小的一定是min(a…

LeetCode 647回文子串 517最长回文子序列 | 代码随想录25期训练营day57

动态规划算法14 LeetCode 647 回文子串 2023.12.20 题目链接代码随想录讲解[链接] int countSubstrings(string s) {//暴力搜索&#xff0c;前两层遍历确定子字符串的起始和末尾位置//第三层循环判断当前子字符串是否为回文串/*int result 0;for (int i 0; i < s.size…

【hadoop】解决浏览器不能访问Hadoop的50070、8088等端口?!

【hadoop】解决浏览器不能访问Hadoop的50070、8088等端口&#xff1f;&#xff01;&#x1f60e; 前言&#x1f64c;【hadoop】解决浏览器不能访问Hadoop的50070、8088等端口&#xff1f;&#xff01;查看自己的配置文件&#xff1a;最终成功访问如图所示&#xff1a; 总结撒花…

Best script for images porter 【容器镜像搬运最佳脚本】

文章目录 1. 简介2. 功能3. 代码4. 示例4.1 拉取 kube-prometheus-stack 55.4.1 版本的镜像 1. 简介 很多情况下&#xff0c;针对一个项目会有很多镜像需要搬运&#xff0c;打包&#xff0c;解压&#xff0c;打标签&#xff0c;推送入库。该项目将针对多个镜像进行管理操作。方…

vscode配置node.js调试环境

node.js基于VSCode的开发环境的搭建非常简单。 说明&#xff1a;本文的前置条件是已安装好node.js(具体安装不再赘述&#xff0c;如有需要可评论区留言)。 阅读本文可掌握&#xff1a; 方便地进行js单步调试&#xff1b;方便地查看内置的对象或属性&#xff1b; 安装插件 C…

GEE:如何解决随机森林分类器的确定性伪随机性?使得每次运行结果(OA、Kappa和混淆矩阵等)不一样

作者:CSDN @ _养乐多_ 在使用 Google Earth Engine(GEE)平台进行土地利用分类时,我们采用了随机森林分类器。理论上,由于该算法的随机性,每次运行后的分类结果应该是不同的。然而,我们在实际应用中却观察到每次运行后总体精度OA值和Kappa值都呈现出完全相同的结果。 这…