为什么我们在Java中使用自动装箱和拆箱?

72 java autoboxing

自动装箱是Java编译器在基元类型和相应的对象包装类之间进行的自动转换.例如,将int转换为Integer,将double转换为Double,依此类推.如果转换是另一种方式,则称为拆箱.

那么为什么我们需要它呢?为什么我们在Java中使用自动装箱和拆箱?

The*_*kis 153

需要一些背景来充分理解这背后的主要原因.

基元与类

Java中的原始变量包含值(整数,双精度浮点二进制数等).因为这些值可能具有不同的长度,所以包含它们的变量也可能具有不同的长度(考虑float对比double).

另一方面,类变量包含对实例的引用.引用通常在许多语言中实现为指针(或与指针非常相似的东西).这些东西通常具有相同的大小,而不管它们指的是(实例的大小Object,String,Integer,等).

类变量的这个属性使它们包含的引用可以互换(在一定程度上).这允许我们做我们称之为替换的东西:广义上讲,使用特定类型的实例作为另一个相关类型的实例(例如,使用a String作为Object).

原始变量不能以相同的方式互换,也不能彼此互换,也不能互换Object.最明显的原因(但不是唯一的原因)是它们的尺寸差异.这使得原始类型在这方面不方便,但我们仍然需要它们的语言(原因主要归结为性能).

泛型和类型擦除

通用类型是具有一个或多个类型参数类型(确切的数字称为通用arity).例如,泛型类型定义 List<T>有一个类型参数T,可以是Object(生成具体类型 List<Object>),String(List<String>),Integer(List<Integer>)等等.

通用类型比非通用类型复杂得多.当它们被引入Java(在其初始版本之后)时,为了避免对JVM进行根本性更改并可能破坏与旧二进制文件的兼容性,Java的创建者决定以最少侵入性的方式实现泛型类型:所有具体类型的List<T>实际上,编译为(二进制等价物)List<Object>(对于其他类型,绑定可能不是Object,但你明白了).通用arity和类型参数信息在此过程中丢失,这就是我们称之为类型擦除的原因.

把两者放在一起

现在问题是上述现实的结合:如果在所有情况下都List<T>变为现实List<Object>,那么T必须始终是可以直接分配的类型Object.其他任何东西都不允许.因为,正如我们之前所说int,float并且double不能互换Object,所以不能有List<int>,List<float>或者List<double>(除非在JVM中存在明显更复杂的泛型实现).

但是Java提供类型,如Integer,FloatDouble其包装类情况下,这些原语,使他们有效地作为替代Object,从而使泛型类型来间接地与原语的工作,以及(因为你可以List<Integer>,List<Float>,List<Double>等).

创建的过程Integer,从一个int,一个Floatfloat等,被称为拳击.反向称为拆箱.因为每次你想要使用它们时都必须使用原始文件Object,因此有些语言会自动执行此操作 - 这就是所谓的自动装箱.

  • 真正清晰简洁的解释! (3认同)

var*_*run 13

自动拳击用来以原始数据类型转换为自己的包装类对象.包装类提供了对基本类型执行的各种功能.最常见的例子是:

int a = 56;
Integer i = a; // Auto Boxing
Run Code Online (Sandbox Code Playgroud)

这是需要的,因为程序员很容易直接编写代码,JVM将负责Boxing和Unboxing.

当我们使用java.util.Collection类型时,Auto Boxing也派上用场.当我们想要创建一个基本类型的集合时,我们不能直接创建一个基本类型的集合,我们只能创建对象的集合.例如 :

ArrayList<int> al = new ArrayList<int>(); // not supported 

ArrayList<Integer> al = new ArrayList<Integer>(); // supported 
al.add(45); //auto Boxing 
Run Code Online (Sandbox Code Playgroud)

包装类

Java的8个基本类型(byte,short,int,float,char,double,boolean,long)中的每一个都有一个单独的Wrapper类与它们相关联.这些Wrapper类具有预定义的方法,用于对原始数据类型执行有用的操作.

使用包装类

String s = "45";
int a = Integer.parseInt(s); // sets the value of a to 45.
Run Code Online (Sandbox Code Playgroud)

Wrapper类提供了许多有用的功能.在这里查看java文档

拆箱与Auto Boxing相反,我们将包装类对象转换回其原始类型.这是由JVM自动完成的,这样我们就可以使用包装类进行某些操作,然后将它们转换回原始类型,因为原语会导致更快的处理.例如 :

Integer s = 45;
int a = s; auto UnBoxing;
Run Code Online (Sandbox Code Playgroud)

对于使用对象的集合,仅使用自动拆箱.这是如何做 :

ArrayList<Integer> al = new ArrayList<Integer>();
al.add(45);

int a = al.get(0); // returns the object of Integer . Automatically Unboxed . 
Run Code Online (Sandbox Code Playgroud)