jdk1.5新特性之自动装箱与拆箱

来源:互联网 发布:2016网络经典小说 编辑:程序博客网 时间:2024/05/21 20:21

Jdk1.5新特性之自动装箱与拆箱

Jdk1.5出现了很多新特性,其中一个是自动装箱与拆箱。

谈到自动装箱和拆箱,就不得不说java基本类型的包装类。

1.基本类型的包装器类

 我们都知道java是面向对象的编程语言,不过它包含8种基本数据类型,8个基本数据类型不支持面向对象编程机制,不具备“对象”的特性;没有属性、方法可以被调用。有些时候基本数据类型就有一些制约,例如所有引用类型的变量都继承Object类,都可以当成Object类型变量来用。但是基本类型就不可以,如果有个方法需要Object类型的参数,但实际需要的值却是2、3等数值,这可能就比较难处理。为了解决这个问题,java提供了包装类的概念,为8个基本数据类型分别定义了相应的引用类型,并称之为基本数据类型的包装类。

基本数据类型

包装类

byte

Byte

short

Short

int

Integer

long

Long

char

Character

float

Float

double

Double

boolean

Boolean

每个包装类都提供了以相应基本类型作为参数的构造函数。可以向包装类中存储基本类型,例如:Integer i=new Integer(6);,并且包装类提供访问基本类型的getter方法。如果希望获得包装类对象中包装的基本类型变量,则可以使用包装类提供的xxxValue()实例方法,比如对于包装类Integer,您可以通过向包装类发送消息inValue来访问原始的整型数值。

    int it=9;

      Integer itObj=new Integer(it);

      //取出Integer对象里的int变量

      inti=itObj.intValue();

对象的包装器类是不可变的,即一旦构造了包装器,就不能更改包装在其中的值。同时,对象包装器还是final,因此不能定义它们的子类。

 假设想要定义一个整型数组列表。而尖括号中的类型参数不允许是基本类型,也就是说不允许写成ArrayList<int>,这里就用到了Integer对象包装器类,即 ArrayList<Integer> list = new ArrayList<>();

但需要注意的是:由于每一个值分别包装在对象中,所以ArrayList<Integer>的效率远远低于int[]数组。因此,应该用它构造小型集合,此时程序员操作的方便性要比执行效率更加重要。

2.自动装箱

 自动装箱的意思是:编译器自动调用相应的包装类,对基本类型进行封装,说的简单一点就是把基本类型转换为包装类型。当java发现类型不匹配的时候就会进行自动装箱,类型匹配意味着方法调用及其参数和类定义中的完全一致,其中如果方法调用的参数是类定义中参数的子类型,也被认为类型匹配。

如果java发现没有直接的类型匹配,那么就试图寻找基于包装类的类型匹配。

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

list.add(30);

Java自动在幕后为整型数值创建相应的Integer实例。

3.自动拆箱

 自动拆箱是和自动装箱相反的一个操作,是把包装类型转换为基本类型。

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

list.add(30);

int n=list.get(0);//自动拆箱

甚至在算数表达式中也能够自动拆箱和装箱。如:

Integer n=3;

n++;

编译器自动插入一条对象拆箱的指令,然后进行自增运算,最后将结果自动装箱。

值得注意的是:在很多情况下,容易有一种假象,即基本类型和它们的对象包装器是一样的,只是相等性不同,我们都知道 ==运算符也可以用于包装器对象中,是用于比较地址是否相等。所以,下面比较一般不会成立:

      Integer a=100;

      Integer b=100;

      System.out.println(a==b);

但是,这里打印的却是true

而    Integer a=1000;

      Integer b=1000;

      System.out.println(a==b);

这里打印的是false;

为什么呢?

这里需要注意的是,自动装箱规范要求boolean、byte、char小于等于127,介于-128到127之间的short和int被包装固定的对象中。

4.自动装箱和拆箱的原理:

 其实自动装箱和自动拆箱都是编译器为我们做的额外操作。也就是说装箱和拆箱是编译器认可的,而不是虚拟机。编译器在生成类的字节码时,插入必要的方法调用的,虚拟机只是执行这些字节码而已。

下面代码:

     Integer ii = 100;

      ii += 200;

      System.out.println("ii:" + ii);

对于这段代码,大家应该都不会陌生,现在我们通过反编译来看看代码是怎样的呢?

 Integer ii = Integer.valueOf(100); //自动装箱

ii = Integer.valueOf(ii.intValue() + 200); //自动拆箱,再动装箱

System.out.println((new StringBuilder("ii:")).append(ii).toString());

我们可以看到编译器帮我们做了一些事,帮我们调用了一些方法。

 

0 0
原创粉丝点击