对象包装器和自动装箱

对象包装器

有时,需要将基本数据类型转换成对象。所有的基本类型都有一个与之对应的类。
基本数据类型有:byte、short、int、long、float、double、char、boolean,其对应的对象包装器(object wrapper)分别是:Byte,Short,Integer,Long,Float,Double,Character,Boolean。(前6个类派生于公共的超类Number)。

  对象包装器类是不可变的,**即一旦构造了包装器,就不允许更改在其中的值。**同时,对象包装器类还是final,因此不能定义它们的子类。
  假设想定义一个整型数组列表。而尖括号中的类型参数不允许是基本类型,也就是说,不允许写成ArrayList。这里就用到了Integer对象包装器类。我们可以声明一个Integer对象的数组列表:ArrayList list = new ArrayList;
注意:由于每个值分别包装在对象中,所以ArrayList的效率远远低于int[]数组。


自动装箱

其实调用list.add(3),就等同于调用list.add(Integer.valueOf(3));这种变化就成为自动装箱。
相反的,当将一个Integer对象赋给一个int值时,将会自动地拆箱。也就是说,编译器将下列语句:
    int n = list.get(i);
  翻译成:
    int n = list.get(i).intValue();
  甚至在算术表达式中也能够自动地装箱和拆箱。如:
    Integer n = 3;
    n++;
 编译器将自动地插入一条对象拆箱的指令,然后进行自增计算,最后再将结果装箱。

大多数情况下,容易给我们造成一种假象,觉得基本类型与它们的对象包装器是一样的。"=="也可以用于比较对象包装器对象,但是比较的是存储区域。

//下面这种情况并不会成立
Integer a = 1000;
Integer b = 1000;
System.out.println(a==b); //false

//如果a.b改成127,则结果为true。
Integer a = 127;
Integer b = 127;
System.out.println(a==b); //true

**注释:**介于-128~127之间的short和int被包装到固定的对象中。故再此区间内的数字对应的存储地址也是相同的。


自动装箱的几点说明:

  • 由于包装器引用可以为null,所以自动装箱有可能会抛出一个NullPointerException异常
  • 如果在一个条件表达式中混合使用Integer和Double类型,Integer值就会拆箱,int提升为double,再装箱为Double。
  • **装箱和拆箱是编译器认可的,**而不是虚拟机。编译器在生成类的字节码时,插入必要的方法调用。虚拟机只是执行这些字节码。(有待深究)

自动装箱的好处

可以将某些基本方法放置在包装器中,例如:将一个数字字符串转换成数值。
      int x = Integer.parseInt(s);
这里与Integer对象没有任何关系,parseInt是一个静态方法。但Integer类是放置这个方法的好地方。

注意: 包装器类不可以用来实现修改数值再赋予数值本身。Integer 对象是不可变的: 包含在包装器中的内容不会改变: 不能使用这些包装器类创建修改数值参数的方法。如果想编写一个修改数值参数值的方法, 就需要使用在 org.omg.CORBA 包中定义的持有者( holder) 类型, 包括 IntHolder、BooleanHolder 等。每个持有者类型都包含’一个公有 (!)域值,通过它可以访问存储在其中的值。

import org.omg.CORBA.IntHolder;

public class WrapperTest {

    public static void triple(int x) {
        x = 3 * x;
    }

    public static void triple1(Integer x) {
        x = 3 * x;
    }

    public static void triple2(IntHolder x) {
        x.value = 3 * x.value;
    }

    public static void main(String[] args) {
        int x1 = 1;
        triple(x1);
        System.out.println(x1); //1
        System.out.println("=========================");

        int x2 = 1;
        triple1(x2);
        System.out.println(x2); //1
        System.out.println("=========================");

        IntHolder x3 = new IntHolder(1);
        triple2(x3);
        System.out.println(x3.value); //3
    }
    
   /**
     * 结果:
     * 1
     * =========================
     * 1
     * =========================
     * 3
     */
//如果是赋予不同的变量,那自然是可以的,因为赋予给一个新的地址了
 public static int triple4(int x) {
        int y = 3 * x;
        return y;
    }

    public static int triple5(Integer x) {
        int y = 3 * x;
        return y;
    }

public static void main(String[] args) {
        int x4 = 1;
        System.out.println(triple4(x4)); //3
        int x5 = 1;
        System.out.println(triple5(x5)); //3
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值