JAVA Integer的一点注意事项

来源:互联网 发布:清华软件学院排名 编辑:程序博客网 时间:2024/05/16 09:49

        用==比较2个Integer对象时,有些小细节需要注意的。Integer,Short,Long和String都是常量类,用final修饰class,声明时可以直接赋值,也可以new,他们之间有什么区别呢?关于String,可以看我的另一篇博文http://blog.csdn.net/dream_broken/article/details/8759616,在这就不多说了。下面就拿Integer说说,Short,Long都是差不多的(Double不是).

       好了,先直接上源码。

public class TestInt {public static void main(String[] args){Integer c=100,d=100;Integer e=1000,f=1000;Integer g=new Integer(100);Integer h=new Integer(100);Integer j =new Integer(1000);Integer k =new Integer(1000);System.out.println(c==d);System.out.println(e==f);System.out.println(g==h);System.out.println(j==k);System.out.println(e==j);}}

  如果你都对了,并且知道理由,那你可以关闭该网页了。

   运行结果:

true
false
false
false
false

       我做的时候,错了e==f的判断。其它的使用了new的,相信大家也不会错,因为==比较的是引用值,而使用了new说明在堆(Eden区)创建一个新对象。那么为什么c==d成立,而e==f不成立呢。

      我第一件事就是用javap -verbose查看class文件。

public static void main(java.lang.String[]);  Code:   Stack=3, Locals=9, Args_size=1   0:bipush100   2:invokestatic#16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   5:astore_1   6:bipush100   8:invokestatic#16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   11:astore_2   12:sipush1000   15:invokestatic#16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   18:astore_3   19:sipush1000   22:invokestatic#16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   25:astore4   27:new#17; //class java/lang/Integer   30:dup   31:bipush100   33:invokespecial#22; //Method java/lang/Integer."<init>":(I)V   36:astore5   38:new#17; //class java/lang/Integer   41:dup   42:bipush100   44:invokespecial#22; //Method java/lang/Integer."<init>":(I)V   47:astore6   49:new#17; //class java/lang/Integer   52:dup   53:sipush1000   56:invokespecial#22; //Method java/lang/Integer."<init>":(I)V   59:astore7   61:new#17; //class java/lang/Integer   64:dup   65:sipush1000   68:invokespecial#22; //Method java/lang/Integer."<init>":(I)V   71:astore8   73:getstatic#25; //Field java/lang/System.out:Ljava/io/PrintStream;   76:aload_1   77:aload_2


    发现:对于Integer x=500这形式的声明并赋值,都调用了Integer类中的静态方法Integer.valueOf(int i);对于Integer x=new Integer(500)这形式的,直接调用构造器.

   再把class文件反编译看看源码。

public class TestInt{  public static void main(String[] args)  {    Integer c = Integer.valueOf(100); Integer d = Integer.valueOf(100);    Integer e = Integer.valueOf(1000); Integer f = Integer.valueOf(1000);    Integer g = new Integer(100);    Integer h = new Integer(100);    Integer j = new Integer(1000);    Integer k = new Integer(1000);    System.out.println(c == d);    System.out.println(e == f);    System.out.println(g == h);    System.out.println(j == k);    System.out.println(e == j);  }}


            到了这,非常明白了,原来是编译器做了处理。那么对于c==d成立,e==f不成立的原因应该就在Integer.valueOf(int i)这个方法里面了。好,继续跟踪,看看Integer.valueOf(int i)做了什么见不得人的事.

 

public static Integer valueOf(int i) {final int offset = 128;if (i >= -128 && i <= 127) { // must cache     return IntegerCache.cache[i + offset];}        return new Integer(i);    }


    看到这源码,相信大家都OK了,如果-128<=i<=127就从IntegerCache.cache[]数组中获得Integer对象,如果不是就直接new,那么再看看IntegerCache.cache[]数组是什么。继续追踪.......

private static class IntegerCache {private IntegerCache(){}static final Integer cache[] = new Integer[-(-128) + 127 + 1];static {    for(int i = 0; i < cache.length; i++)cache[i] = new Integer(i - 128);}    }

       追踪到这,终于松了口气了,原来加载IntegerCache类是就初始化了Integer类型的cache[]数组,并将数值位于-128到127之间的Integer对象保存到数组中。如果Integer.valueOf(int i)中的i如果位于该范围,就直接把数组内对应的对象引用值返回,所以Integer c=100,d=100;c==d是成立的,因为他们都指向同一个对象,而对于Integer e=1000,f=1000;e==f不成立,因为他们都不在范围内,直接new了。
        对于Short,Long都是一样,Double就不一样了,呵呵,大家可以查看源码,这样更清晰原因。

         

 

原创粉丝点击