Java自动装箱(autoboxing)和自动拆箱(autounboxing)介绍

Java自动装箱(autoboxing)和自动拆箱(autounboxing)介绍

先回顾一下 Java 中的基本数据类型和包装类。

基本数据类型(Primitive Data Types): Java 提供了一组基本数据类型,有8种基本数据类型:byte、short、int、long、float、double、char和boolean。

数据类型

取值范围

byte

-128 ~ 127

short

-32786 ~ 32767

int

-4294967296 ~ 4294967295

long

-2^64^ ~ 2^64^ -1

float

3.4e-038 ~ 3.4e+038

double

1.7e-308 ~ 1.7e+308

char

\u0000 ~ \uffff

boolean

true 、false

包装类(Wrapper Classes): 为了使基本数据类型具备面向对象的特性,Java 提供了对应的包装类,Byte、Short、Integer、Long、Float、Double、Character和Boolean。这些包装类用于将基本数据类型封装为对象,以便进行更多的操作。

Java自动装箱和拆箱的意思就是 Java 编译器自动处理基本数据类型与包装类之间的转换,使程序员无需手动编写繁琐的代码。自动装箱和自动拆箱也可以简称为装箱和拆箱。

Java自动装箱(autoboxing)和自动拆箱(autounboxing)介绍_第1张图片

Java中基础数据类型与它们对应的包装类见下表(共8种):

原始类型

包装类型

boolean

Boolean

byte

Byte

char

Character

float

Float

int

Integer

long

Long

short

Short

double

Double

当表格中左边列出的基础类型与它们的包装类有如下几种情况时,编译器会自动帮我们进行装箱或拆箱。

  • 进行 = 赋值操作(装箱或拆箱)
  • 进行+,-,*,/混合运算 (拆箱)
  • 进行>,<,==比较运算(拆箱)
  • 调用equals进行比较(装箱)
  • ArrayList,HashMap等集合类 添加基础类型数据时(装箱)

一个自动拆箱的示例:

Integer i = new Integer(10);

int j = i;

在这个示例中,将一个封装类型的变量i赋值给一个基本类型的变量j,编译器会自动将i转换为int类型的数值10,然后赋值给j。

一个自动装箱的示例:

int i = 10;

Integer j = i;

在这个示例中,将一个基本类型的变量i赋值给一个封装类型的变量j,编译器会自动将i转换为Integer类型的对象,然后赋值给j。

在Java中,自动装箱(Autoboxing)和自动拆箱(Unboxing)是从Java 5开始引入的概念,它们是编译器的特性,使得原始类型(primitive types)和它们对应的包装类(wrapper classes)之间的转换自动化。

public class Demo {
    public static void main(String[] args) {
    //自动装箱
    Integer total = 99;

    //自动拆箱
    int totalprim = total;
    }
}

自动装箱(Autoboxing

自动装箱是指将原始类型自动转换为对应的包装类对象的过程。当编译器遇到一个原始类型的值,而该值需要被当作一个对象来处理时,编译器会自动将原始类型的值转换为对应的包装类对象。这通常发生在:

  1. 将原始类型赋值给对应的包装类变量时。
  2. 将原始类型传递给期望对象的方法时。
  3. 将原始类型添加到集合中,如List或Set,这些集合只能存储对象。

例如:

Integer integerObject = 10; // 自动装箱,int转换为Integer

List listOfIntegers = new ArrayList<>();

listOfIntegers.add(20); // 自动装箱,int转换为Integer

在上面的例子中,数字10和20是原始类型int,它们被自动装箱成为Integer对象,然后被存储在对应的变量和集合中。

自动拆箱(Unboxing

自动拆箱是指将包装类对象自动转换为对应的原始类型值的过程。当编译器遇到一个包装类对象,而该对象需要被当作一个原始类型的值来处理时,编译器会自动将包装类对象转换为原始类型的值。这通常发生在:

  1. 将包装类对象赋值给对应的原始类型变量时。
  2. 将包装类对象传递给期望原始类型的方法时。
  3. 在算术运算或比较运算中使用包装类对象时。

例如:

Integer integerObject = new Integer(30);

int i = integerObject; // 自动拆箱,Integer转换为int

在上面的例子中,integerObject是一个Integer对象,它被自动拆箱成为int原始类型的值i。

注意事项

虽然自动装箱和拆箱使得原始类型和包装类之间的转换变得简单,但它们也可能引入一些问题:

  1. 性能开销:装箱操作涉及到对象的创建,而拆箱操作可能涉及到类型检查和值的提取。频繁的装箱和拆箱可能会对性能产生负面影响,特别是在大量计算的场景中。
  2. 空指针异常(NullPointerException):自动拆箱时如果包装类对象为null,则会抛出空指针异常。
  3. 等价性问题:包装类对象是引用类型,因此在比较时,使用==运算符会比较引用而不是值。为了比较值,应该使用equals()方法。

例如:

Integer a = 1000, b = 1000;

System.out.println(a == b); // false,因为比较的是引用

System.out.println(a.equals(b)); // true,因为比较的是值

但是,对于在-128到127之间的小整数值,Java会缓存这些对象的实例,所以使用==运算符比较这些值时可能会得到true。

Integer c = 100, d = 100;

System.out.println(c == d); // true,因为小整数值的实例被缓存

了解这些细节对于编写正确和高效的Java代码是非常重要的。

进一步学习了解可参见:

如何理解Java中的自动拆箱和自动装箱?https://www.cnblogs.com/niceyoo/p/12977541.html

详解Java的自动装箱与拆箱(Autoboxing and unboxing)https://www.cnblogs.com/wang-yaz/p/8516151.html

深入探究Java自动拆箱与装箱的实现原理https://cloud.tencent.com/developer/article/2361504

附录、C++、Java、Python、JavaScript等语言中都有自动装箱和自动拆箱概念吗?

自动装箱和自动拆箱是编程语言中的两个概念,主要与类型系统有关,尤其是在处理基本数据类型和它们的对象表示(包装类)时出现。

  1. C++:C++中没有自动装箱和自动拆箱的概念。C++是一种静态类型语言,不提供基本数据类型和对象之间的自动转换。C++中有类似的概念,比如构造函数和类型转换运算符,可以用来在对象和基本数据类型之间进行转换,但这些都需要显式定义。
  2. Java:Java中有自动装箱和自动拆箱的概念。从Java 5开始,Java提供了自动装箱和自动拆箱功能,使得基本数据类型和它们的包装类(如int和Integer、double和Double等)之间可以自动转换。
  3. Python:Python中没有自动装箱和自动拆箱的概念,因为Python是一种动态类型语言,它不区分基本数据类型和对象类型。在Python中,数字、字符串等都是对象。
  4. JavaScript:JavaScript也是一种动态类型语言,它有类似自动装箱的行为,但通常不这么称呼。在JavaScript中,基本数据类型(如数字、字符串、布尔值)在需要时会被自动封装为对象(例如,当你调用基本类型的方法时)。然而,这个过程是透明的,开发者通常不需要关心这个自动转换。
  5. C#语言的自动装箱和自动拆箱与Java语言中的这两个概念非常类似。在C#中,装箱和拆箱是用于在值类型(如结构体和基本数据类型)和引用类型(如object或者接口类型)之间转换的过程。

总的来说,自动装箱和自动拆箱主要是Java中的概念,而在在其他编程语言中,这些概念要么不存在,要么以不同的形式存在。

你可能感兴趣的:(java,开发语言)