Java中八大包装类举例详解(通俗易懂)

2025-02-16 05:50

本文主要是介绍Java中八大包装类举例详解(通俗易懂),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Java中八大包装类举例详解(通俗易懂)》:本文主要介绍Java中的包装类,包括它们的作用、特点、用途以及如何进行装箱和拆箱,包装类还提供了许多实用方法,如转换、获取基本类型值、比较和类型检测,...

一、包装类(Wrapper Class)

1、简要介绍

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

以下是 Java 中基本数据类型及其对应的包装类:

基本数据类型对应的包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

2、包装类特点

  • 封装性:所有的包装类都是 final 类,这意味着它们不能被继承。这种设计确保了包装类的行为和特性的一致性,从而避免了子类可能引入的不确定性。

  • 不可变性:包装类的实例一旦被创建后,其中保存的基本数据类型数据就不能再被改变。这种不可变性使得包装类在多线程环境中更加安全,避免了因数据被意外修改而导致的错误。

  • 提供方法:包装类封装了许多实用的方法,提供了丰富的功能。例如,它们支持数据类型转换、判断字符串的大小写、以及获取最大值和最小值等。

  • 继承关系:除了 Characphpter 和 Boolean 之外,其他所有的包装类都继承自 Number 类。这种继承关系使得这些包装类能够共享一些通用的功能和特性,例如数字的比较和转换,这为在不同数值类型之间的操作提供了一致的接口。

    Java中八大包装类举例详解(通俗易懂)

3、包装类用途

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

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

二、装箱和拆箱

1、装箱和拆箱

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

手动装箱就是使用一个值创建一个 Integer 对象:

int num = 50000;
Integer boxedInt1 = new Integer(num); // 手动装箱方式一
Integer boxedInt2 = Integer.valueOf(num); // 手动装箱方式二

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

Integer boxedInt = new Integer(5);
int num = boxedInt.intValue(); // 手动拆箱

2、自动装箱和自动拆箱

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

自动装箱是将基本数据类型自动转换为其对应的包装类对象的过程。

int num = 50000;
Integer boxedInt = num; // 自动装箱

自动拆箱则是将包装类对象自动转换为其对应的基本数据类型。

Integer boxedInt = new Integer(50000);
int num = boxedInt; // 自动拆箱

3、自动装箱和自动拆箱的底层实现

1)自动装箱的底层实现

自动装箱是通过调用包装类的valueOf()方法来实现的。

我们可以通过调试来验证这一结论,在要发生自动装箱的地方打上断点,然后直接跳到这个断点处,然后强制进入(force step into),就会进入到 valueOf() 方法中。

2)自动拆箱的底层实现

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

我们可以通过调试来验证这一结论,在要发生自动拆箱的地方打上断点,然后直接跳到这个断点处,然后强制进入(force step into),就会进入到 xxxValue() 方法中。

三、包装类的缓存机制

1、简要介绍

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

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

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

2、缓存范围

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

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

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

3、触发缓存机制

只有调用 valueOf() 方法时,如果要创建的值已经被缓存,则会触发缓存机制。

我们可以查看 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);
    }

如果要创建的 Integer 对php象的值在预定范围内,则返回缓存的对象,如果不在范围内,则直接新创建一个对象。

4、测试缓存机制

我们可以通过使用 valueOf() 方法创建两个值一样且值在范围内的对象,然后比较它们的引用是否相等,如果相等,则能证明缓存机制的存在。

public class Example {
	pubhttp://www.chinasem.cnlic static void main(String[] args) {
		Integer i1 = Integer.valueOf(1);
		Integer i2 = Integer.valueOf(1);

		System.out.println(i1 == i2);
	}
}

运行结果:

Java中八大包装类举例详解(通俗易懂)

这样就能证明缓存机制的存在。

四、包装类的方法

1、基本转换方法

parseInt(String s), parseDouble(String s), parseBoolean(String s) 等:将字符串转换为相应的基本类型。

valueOf(String s): 返回对应类型的包装类实例,例如 Integer.valueOf("123") 返回一个 Integer 对象。

2、获取基本类型值

intValue(), doubleValue(), charValue(), booleanValue() 等: 返回包装类中封装的基本类型值。

示例:

Integer num = new Integer(5);
int value = num.intValue();

3、常量字段

MAX_VALUE, MIN_VALUE: 返回该包装类所表示的基本类型的最大值和最小值。

例如:

Integer.MAX_VALUE 返回 2147483647,

Double.MIN_VALUE 返回 4.9E-324。

4、比较方法

compareTo(T another): 用于比较两个包装类对象的大小。

equals(Object obj): 判断两个对象是否相等。

示例:

Integer.compare(x, y) 方法比较两个 Integer 对象的值。

5、类型检测

isNaN(), isInfinite(): 用于 Double 和 Float 以检测是否为非数字或无穷大。

isLetter(char ch):检查指定的字符是否为字母(包括大写和小写字母)。

char c = 'A';
boolean isLetter = Character.isLetter(c); // 返回 true

isDigit(char ch)检查指定的字符是否为数字。

char c = '5';
boolean isDigit = Character.isDigit(c); // 返回 true

isWhitespace(char ch):检查指定的字符是否为白空格字符(如空格、制表符等)。

char c = ' ';
boolean isWhitespace = Character.isWhitespace(c); // 返回 true

五、补充

1、精度提升

public class Example {
	public static void main(String[] args) {
		Object obj = true ? new Integer(1) : new Double(2.0);
		System.out.println(obj);
	}
}

输出结果是:

Java中八大包装类举例详解(通俗易懂)

这是因为由于 Double 精度高,而且这里使用的是三元运算符,所以 Integer 会被提升精度为 Double,所以最终输出的是一个浮点数。

实际上的具体操作应该是:

创建一个 Integer 对象,然后这个对象自动拆箱得到一个 int 类型的值,然后由于后面是 Double 类型,这个 int 类型的值提升为 double 类型的值,然后通过自动装箱得到一个 Double 类型的对象。

我们也可以通过 instanceof 操作符测试一下:

public class Example {
	public static void main(String[] args) {
		Object obj = true ? new Integer(1) : new Double(2http://www.chinasem.cn.0);
		System.out.println(obj instanceof Double);
	}
}

输出结果:

Java中八大包装类举例详解(通俗易懂)

所以说这里的 obj 指向的对象确实是一个 Double 类的对象。

2、包装类与字符串相互转换

1)包装类转换为字符串

		Integer i = 10000;
		
		// 方式一
		String str1 = i + "";
		
		// 方式二
		String str2 = i.toString();
		
		// 方式三
		String str3 = String.valueOf(i);

这里对于方法三,实际上内部也是调用 toString() 方法的。

2)字符串转换为包装类

		String str = "10000";

		// 方式一
		Integer i1 = Integer.parseInt(str);

		// 方式二
		Integer i2 = Integer.valueOf(str);
		
		// 方式三
		Integer i3 = new Integer(str);

这里看似通过字符串创建 Integer 类对象有三种方法,实际上就一种方法,对于方法二和方法三内部实际上都是调用js parseInt() 方法来将字符串转换为整型的。

3、缓存机制

上面提到的缓存机制只可能在调用 valueOf() 方法时触发,所以对于直接调用构造方法则不会触发缓存机制。

我们知道自动装箱底层调用的也是 valueOf() 方法,所以说自动装箱也可以触发缓存机制。

我们还知道缓存机制是有范围的,超出范围的值创建的对象都是新创建的。

所以我们就能很自然的得到以下代码的运行结果:

public class Example {
	public static void main(String[] args) {
		Integer i1 = new Integer(1);
		Integer i2 = new Integer(1);

		System.out.println(i1 == i2); // false

		Integer i3 = 1;
		Integer i4 = 1;

		System.out.println(i3 == i4); // true

		Integer i5 = 128;
		Integer i6 = 128;

		System.out.println(i5 == i6); // false
	}
}

运行结果:

Java中八大包装类举例详解(通俗易懂)

4、判断值是否相等

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

public class Example {
	public static void main(String[] args) {
		Integer i1 = 128;
		int i2 = 128;

		System.out.println(i1 == i2);
	}
}

运行结果:

Java中八大包装类举例详解(通俗易懂)

总结 

到此这篇关于Java中八大包装类的文章就介绍到这了,更多相关Java八大包装类内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于Java中八大包装类举例详解(通俗易懂)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153458

相关文章

Go路由注册方法详解

《Go路由注册方法详解》Go语言中,http.NewServeMux()和http.HandleFunc()是两种不同的路由注册方式,前者创建独立的ServeMux实例,适合模块化和分层路由,灵活性高... 目录Go路由注册方法1. 路由注册的方式2. 路由器的独立性3. 灵活性4. 启动服务器的方式5.

springboot将lib和jar分离的操作方法

《springboot将lib和jar分离的操作方法》本文介绍了如何通过优化pom.xml配置来减小SpringBoot项目的jar包大小,主要通过使用spring-boot-maven-plugin... 遇到一个问题,就是每次maven package或者maven install后target中的ja

如何利用Java获取当天的开始和结束时间

《如何利用Java获取当天的开始和结束时间》:本文主要介绍如何使用Java8的LocalDate和LocalDateTime类获取指定日期的开始和结束时间,展示了如何通过这些类进行日期和时间的处... 目录前言1. Java日期时间API概述2. 获取当天的开始和结束时间代码解析运行结果3. 总结前言在J

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J

Spring AI Alibaba接入大模型时的依赖问题小结

《SpringAIAlibaba接入大模型时的依赖问题小结》文章介绍了如何在pom.xml文件中配置SpringAIAlibaba依赖,并提供了一个示例pom.xml文件,同时,建议将Maven仓... 目录(一)pom.XML文件:(二)application.yml配置文件(一)pom.xml文件:首

SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤

《SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤》本文主要介绍了SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤,文中通过示例代码介绍的非常详... 目录 目标 步骤 1:确保 ProxySQL 和 mysql 主从同步已正确配置ProxySQL 的