为什么在Java中使用自动装箱和取消装箱?
自动装箱是Java编译器进行的自动转换 在基元类型及其相应的对象包装器之间 上课。例如,将int转换为整数,将double转换为 双倍,等等。如果转换方向相反,则这是 叫做拆箱为什么在Java中使用自动装箱和取消装箱?,java,autoboxing,Java,Autoboxing,自动装箱是Java编译器进行的自动转换 在基元类型及其相应的对象包装器之间 上课。例如,将int转换为整数,将double转换为 双倍,等等。如果转换方向相反,则这是 叫做拆箱 那么为什么我们需要它,为什么我们要在Java中使用自动装箱和取消装箱呢?因为它们是不同的类型,并且是为了方便起见。性能可能是拥有基元类型的原因。某些数据结构只能接受对象,不能接受基元类型 示例:HashMap中的键 有关更多信息,请参见此问题: 还有其他很好的理由,例如数据库中的“int”字段也可以为NULL。 Java
那么为什么我们需要它,为什么我们要在Java中使用自动装箱和取消装箱呢?因为它们是不同的类型,并且是为了方便起见。性能可能是拥有基元类型的原因。某些数据结构只能接受对象,不能接受基元类型 示例:HashMap中的键 有关更多信息,请参见此问题: 还有其他很好的理由,例如数据库中的“int”字段也可以为NULL。 Java中的int不能为null;可以使用整数引用。自动装箱和取消装箱提供了一种工具,以避免在转换过程中来回写入无关代码。我们为什么要(取消)装箱? 使编写混合了原语及其面向对象(OO)替代方案的代码更加舒适/不那么冗长 为什么我们有原语和它们的OO替代品? 基元类型不是类(与C#不同),因此它们不是
对象的子类,不能被重写
出于性能原因,我们使用了int
等原语;出于面向对象编程的好处,我们使用了Object
等可选的Integer
,作为次要的一点,我们为实用常量和方法(Integer.MAX_值和Integer.toString(int)
)提供了一个良好的位置
使用泛型(List
)最容易看到OO的好处,但不限于此,例如:
Number getMeSome(boolean wantInt) {
if (wantInt) {
return Integer.MAX_VALUE;
} else {
return Long.MAX_VALUE;
}
}
自动装箱用于将基本数据类型转换为其包装类对象。
包装器类提供了一系列要在基元类型上执行的函数。最常见的例子是:
int a = 56;
Integer i = a; // Auto Boxing
这是需要的,因为程序员很容易直接编写代码,JVM将负责装箱和拆箱
当我们使用java.util.Collection类型时,自动装箱也很方便。当我们想要创建一个基本类型的集合时,我们不能直接创建一个基本类型的集合,我们只能创建一个对象的集合。例如:
ArrayList<int> al = new ArrayList<int>(); // not supported
ArrayList<Integer> al = new ArrayList<Integer>(); // supported
al.add(45); //auto Boxing
Integer s = 45;
int a = s; auto UnBoxing;
包装器类提供了许多有用的函数。查看java文档
取消装箱与自动装箱相反,在自动装箱中,我们将包装器类对象转换回其原始类型。这是由JVM自动完成的,这样我们就可以为某些操作使用包装器类,然后将它们转换回原语类型,因为原语导致更快的处理。例如:
ArrayList<int> al = new ArrayList<int>(); // not supported
ArrayList<Integer> al = new ArrayList<Integer>(); // supported
al.add(45); //auto Boxing
Integer s = 45;
int a = s; auto UnBoxing;
对于使用对象的集合,仅使用自动取消装箱。以下是方法:
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(45);
int a = al.get(0); // returns the object of Integer . Automatically Unboxed .
ArrayList al=new ArrayList();
加(45);
int a=al.get(0);//返回整数的对象。自动取消装箱。
需要一些上下文才能完全理解这背后的主要原因
原语与类
Java中的基本变量包含值(整数、双精度浮点二进制数等)。因为,包含它们的变量也可能具有不同的长度(考虑float
与double
)
另一方面,类变量包含对实例的引用。在许多语言中,引用通常被实现为指针(或非常类似于指针的东西)。这些东西通常具有相同的大小,而不管它们引用的实例大小(对象
,字符串
,整数
,等等)
类变量的这个属性使得它们包含的引用在一定程度上可以互换。这允许我们做我们称之为替换的事情:广义上讲,(例如,使用字符串作为对象)
基本变量不能以相同的方式互换,既不能彼此互换,也不能与对象互换。最明显的原因(但不是唯一的原因)是它们的尺寸差异。这使得基元类型在这方面很不方便,但我们在语言中仍然需要它们(原因主要归结为性能)
泛型和类型擦除
泛型类型是具有一个或多个类型参数的类型(确切数字称为泛型arity)。例如,泛型类型定义List
有一个类型参数T
,它可以是对象
(生成具体类型列表
)、字符串
(列表
)、整数
(列表
)等等
泛型类型比非泛型类型复杂得多。当它们被引入Java时(在最初发布之后),为了避免对JVM进行根本性的更改,并可能破坏与旧二进制文件的兼容性,Java的创建者决定以最小侵入性的方式实现泛型类型:事实上,列表的所有具体类型都编译为(二进制等价物)列表
(对于其他类型,边界可能不是对象
,但您明白了这一点)。通用算术和类型参数信息在此过程中丢失,这就是我们称之为它的原因
把两者结合起来
现在的问题是上述现实的结合:如果List
在所有情况下都变成List
,那么T
必须始终是一种可以直接分配给对象的类型。其他任何东西都是不允许的。因为,正如我们前面所说,int
、float
和double>代码>不能与对象互换<
ArrayList<String> strArrayList = new ArrayList<String>(); // is accepted.
ArrayList<int> intArrayList = new ArrayList<int>(); // not accepted.
ArrayList<Integer> intArrayList = new ArrayList<Integer>(); // is accepted.
strArrayList.add("Hello");
intArrayList.add(54);
intArrayList.add(Integer.valueOf(54));
// Java program to illustrate the concept
// of Autoboxing and Unboxing
import java.io.*;
class GFG
{
public static void main (String[] args)
{
// creating an Integer Object
// with value 10.
Integer i = new Integer(10);
// unboxing the Object
int i1 = i;
System.out.println("Value of i: " + i);
System.out.println("Value of i1: " + i1);
//Autoboxing of char
Character gfg = 'a';
// Auto-unboxing of Character
char ch = gfg;
System.out.println("Value of ch: " + ch);
System.out.println("Value of gfg: " + gfg);
}
}