Integer.valueOf(int i)与自动拆箱与装箱

来源:互联网 发布:淘宝怎么赚钱兼职工作 编辑:程序博客网 时间:2024/05/07 22:35

查了一下Api,valueOf(int i),返回的是i值的Integer对象,Integer.valueOf()基于减少对象的创建次数和节省内存的考虑,[-128,127]之间的数字会被缓存,当valueOf()方法传入的参数在这个范围之内,将直接返回缓存中的对象。

我们来看一下一个例子

public static void main(String[] args) {        Integer a=Integer.valueOf(1);        Integer b=Integer.valueOf(1);        int     c=1;        Integer d=1;        long    e=1L;        Integer f=Integer.valueOf(321);        Integer g=Integer.valueOf(321);        Long    i=2L;        System.out.println(a==b);          //1        System.out.println(a==c);          //2        System.out.println(a==d);          //3        System.out.println(a==e);          //4        System.out.println(c==e);          //5        System.out.println(f==g);          //6        System.out.println(i==(a+b));      //7        System.out.println(i.equals(a+b)); //8    }

结果为:
true
true
true
true
true
false
true
false

我们来看1,a,b都是Integer的对象,由于Integer.valueOf()缓存[-128,127]之间的数,因为传入的参数一样,所以返回的对象是一样的。与//6,即可以得到结果

对于2,因为c是数值,进行的是数值比较,a会自动拆箱,进行比较,故结果是正确的

对于3,Integer d=1和Integer d=Integer.valueOf(1)的效果是一样的,所以返回了同一个对象

对于4,e为数值,故为数值比较,a先自动拆箱为int数值,再转化为long型与e进行比较

对于5,则为c转化为long型,与e进行比较

对于7,因为a+b是算术运算,故a+b是一个值,“==”运算在遇到算术运算时会自动拆箱,成为int型的值,再转型成long型,与i的自动拆箱进行比较

对于8,因为Long型的equals()方法不处理数据转型的关系,故比较是错误的。

下面的内容摘自《effective java》第49条:基本类型优先于装箱基本类型

我们知道Java有一个类型系统由两个部分组成,包括基本类型,例如int,double和boolean,和引用类型,如String和List,每个基本类型对应于一个引用类型,称作装箱基本类型。即装箱基本类型中对应于int,double和boolean的是Integer,Double和Boolean。

下面我们来看一个很有趣的例子:

public static void main(String[] args) {        // TODO Auto-generated method stub        Integer a=new Integer(1);        Integer b=new Integer(1);        System.out.println(a<b?-1:(a==b?0:1));    }

在上面的例子中,如果我们不注意的话,我们得到的结果就是0,但是运行之后我们得到的结果是1;

根据《effective java》书上的解释,首先先比较a < b,执行这个计算会使得a,b进行自动拆箱,变成基本类型(此时基本类型就只有值),第一个比较不正确,则进行第二个比较,对于“==”的比较,则比较他的同一性,即这是装箱基本类型(引用类型)的比较,即比较它们的同一性,如果a和b引用表示同一个int值的不同Integer实例,则这个比较操作返回的值是false,故上面的程序返回的是1。

对于基本类型和装箱基本类型的区别有三点:

一、基本只有值,而装箱基本类型具有与它们的值不同的同一性,换句话说,就是两个装箱基本类型可以具有相同的值而有不同的同一性。(还是很生涩,照我的理解是,虽然它们的值相同,但是a和b是两个不相同的对象,它们在创建时地址是不一样的)

二:基本类型只有功能完备的值,而每个装箱基本类型除了它有对应的基本类型的所有功能之外,还有个非功能值:null

三:基本类型通常比装箱基本类型更节省时间和空间

现在我们来看看反编译的结果

import java.io.PrintStream;public class Autoboxing{    public Autoboxing()    {    }    public static void main(String args[])    {        Integer a = new Integer(1);        Integer b = new Integer(1);        System.out.println(a.intValue() >= b.intValue() ? ((int) (a != b ? 1 : 0)) : -1);    }}

从上面的结果可以看出,在编译时,系统先给类添加了一个无参构造器,我们着重看下输出的比较部分,

首先先对对象a和b进行同一性的比较,比较的结果为true,故结果返回1,再对a>=b进行比较,首先先对a和b进行自动拆箱,用到intValue()方法进行拆箱,此时a和b都是基本类型,故单纯比较它们值是相等的,比较的结果为true,故结果返回1。所以整个程序的返回的结果是1。

下面我们再来看看例子:

public static void main(String[] args) {        Integer a=1;        Integer b=1;        Integer c=Integer.valueOf(1);        Integer d=2;        Long    e=2L;        System.out.println(a==b);        System.out.println(a==c);        System.out.println(b==c);        System.out.println(d==(a+b));        System.out.println(d.equals(a+b));        System.out.println(e.equals(d));    }

上面程序的结果为:
true
true
true
true
true
false

下面我们用反编译的程序解释上面的结果

public class Autoboxing2{    public Autoboxing2()    {    }    public static void main(String args[])    {        Integer a = Integer.valueOf(1);        Integer b = Integer.valueOf(1);        Integer c = Integer.valueOf(1);        Integer d = Integer.valueOf(2);        Long e = Long.valueOf(2L);        System.out.println(a == b);        System.out.println(a == c);        System.out.println(b == c);        System.out.println(d.intValue() == a.intValue() + b.intValue());        System.out.println(d.equals(Integer.valueOf(a.intValue() + b.intValue())));        System.out.println(e.equals(d));    }}

首先对a,b进行自动装箱,用到valueOf()方法,这个方法在上面已经介绍过,故我们知道a,b和c具有同一性,故前三个比较返回的是true。

对于第四个比较,a+b,则先对a和b用intValue()方法进行自动拆箱,相加得到2这个值,再用对象d和值2进行”==”比较,对象d再用intValue()方法进行自动拆箱,得到2这个值,故结果返回的是true。

第五个比较则是先对a和b用intValue()方法进行自动拆箱,相加得到2这个值,再进行自动装箱,变成与对象d具有同一性,故返回的是true。

第六个比较,两个对象为不同的对象,故用equals方法比较返回的是false。

总结:
1、反编译的代码用了Integer.intValue()和Integer.valueOf()方法进行自动拆箱和自动装箱

2、在范围[-128,127]内的数值,自动装箱方法Integer.valueOf()会缓存,当valueOf()方法传入的参数在这个范围之内,将直接返回缓存中的对象,基于减少创建对象的次数和节省内存的考虑

3、通过”==”比较两个自动装箱的Integer实例时,只要两者表示的数值相等,结果就是相等的,因此他们的同一性是相同的

4、通过equals来比较的时候,只要同类型(包括自动装箱和拆箱)代表的数值相同的,就是相等的

0 0
原创粉丝点击