Java中对象包装器(包装类)与自动装箱、自动拆箱

  • Post author:
  • Post category:java




对象包装器与自动装箱

Java是一门非常纯粹的面向对象的编程语言,其设计理念是“一切皆对象”。**但8种基本数据类型却不具备对象的特性。**据说Java之所以提供8种基本数据类型,主要是为了照顾程序员的传统习惯。这8种基本数据类型的确带来了一定的方便性,但在某些时候也会受到一些制约。比如,所有的引用类型的变量都继承于Object类,都可以当做Object类型的变量使用,但基本数据类型却不可以。

如果某个方法需要Object类型的参数

,但实际需要传入的值却是数字的话,就需要做特殊的处理了。

这时我们需要将int这样的基本类型转换为对象。所有的基本类型都有一个与之对应的类。

eg:

Integer

类对应基本类型为

int

。通常,这些与基本类型对应的类称为包装器(wrapper)。


包装器是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值。

同时,包装器类还是

final

,因此不能派生它们的子类。

假设我们想要定义一个整型数组列表。但是尖括号中的类型参数不允许是基本类型,

ArrayList<int>

是不允许的。这时我们就可以用到Integer包装器类。

ArrayList<> list = new ArrayList<Integer>();

这样,我们在向list中添加数据时,就应该添加

Integer

对象,但是,Java中有一个很有用的特性,

可以很简单的向

ArrayList<Integer>

中添加int类型的元素

list.add(3);

自动的变换成

list.add(Integer.valueOf(3));

这种变换称为

自动装箱(autoboxing)

“装箱”(boxing)这个词来源于C#

相反的,当将一个

Integer

对象赋给一个int值时,将会

自动的拆箱。

也就是说,

编译器

将以下语句:

int n = list.get(i)

转换成:

int n = list.get(i).intValue();



自动的装箱与拆箱也适用于算术表达式。

例如自增运算符:

Integer n = 3;
n++; // 编译器自动插入一条对象拆箱的指令,运算完成后再装箱。

大多数情况下容易有一种假象,认为基本类型与它们的对象包装器是一样的。但它们有一点有很大不同:同一性。

​ == 运算符运用于对象时检测的是对象是否有相同的内存位置。

  • 不同包装类不能直接进行比较不能用==进行直接比较。
  • 不能使用

    compareTo

    方法进行比较,虽然它们都有

    compareTo

    方法,但该方法只能对相同类型进行比较

所以

Integer a = 1000;
Integer b = 1000;
if(a == b)...
    //此语句通常会失败;



自动装箱规范要求


boolean、byte、char <= 127

介于-128和127之间的short和int被包装到固定的对象中。

即如果在此范围内的short/int值的==运算比较结果一定成功。



自动装箱注意的点:

  1. 包装器类引用可以为

    null

    ,若没有值,则可能会

    NullPointerException

    Integer n = null;
    System.out.println(2*n); // throws NullPointerException
    
  2. 若在一个条件表达式中混合使用

    Integer



    Double

    类型,

    Integer

    值就会拆箱,提升转换为

    double

    ,再装箱为

    Double

    .

    Integer n = 1;
    Double x = 2.0;
    System.out.println(true? n : x);
    // prints 1.0
    
  3. 装箱和拆箱是编译器要做的工作,而不是虚拟机。

    编译器在生成类的字节码文件时就会插入必要的方法调用(自动的拆箱和装箱),虚拟机只是执行这些代码。


使用数值包装器通常还有一个原因:

可以将某些基本方法放在包装器中,会很方便

—> API文档。

// 将一个数字字符串转换成数值
int x = Integer.parseInt(s);
// 这里,parseInt与Integer对象没关系,它是一个static静态方法(工具方法),只是Integer类是一个放它的好地方。

其它数值类也实现了一些有用的方法。


Warning:

有些人认为包装器类可以用来实现修改数值参数的方法,然而这是错误的。

Java方法的参数总是按值传递,所以不可能编写一个能够增加整型参数值的Java方法。

因为Integer对象是

不可变的

,包含在包装器中的内容不会改变。不能使用这些包装器类创建会修改数值参数的方法。

如果确实向别写一个修改数值参数值的方法,可以使用

org.omg.CORBA

包中定义的某个持有者(holder)类型,包括

IntHolder



BooleanHolder

等。



版权声明:本文为qq_55977327原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。