• java中Integer常量池


        我们先看一个关于Integer的例子

    public static void main(String[] args) {
    		// TeODO Auto-generated method stu
            Integer i1 = 40;
            Integer i2 = 40;
            Integer i3 = 0;
            Integer i4 = new Integer(40);
            Integer i5 = new Integer(40);
            Integer i6 = new Integer(0);
            
            System.out.println("i1=i2	" + (i1 == i2));
            System.out.println("i1=i2+i3	" + (i1 == i2 + i3));
            System.out.println("i4=i5	" + (i4 == i5));
            System.out.println("i4=i5+i6	" + (i4 == i5 + i6));    
            
            System.out.println();     
    	}
    }
    

     结果:

    i1=i2     true
    i1=i2+i3  true
    i4=i5  false
    i4=i5+i6  true

     再看一个例子

    public static void main(String[] args) {
    	// TeODO Auto-generated method stu
            Integer i1 = 400;
            Integer i2 = 400;
            Integer i3 = 0;
            Integer i4 = new Integer(400);
            Integer i5 = new Integer(400);
            Integer i6 = new Integer(0);
            
            System.out.println("i1=i2	" + (i1 == i2));
            System.out.println("i1=i2+i3	" + (i1 == i2 + i3));
            System.out.println("i4=i5	" + (i4 == i5));
            System.out.println("i4=i5+i6	" + (i4 == i5 + i6));    
            
            System.out.println();     
    	}
    }
    

     结果

    i1=i2     false
    i1=i2+i3  true
    i4=i5  false
    i4=i5+i6  true

     比较上面两个例子,我们发现:两个例子代码几乎一样,就是值不一样,40和400的区别怎么会造成如此大的结果差别呢??

    我们用上篇博客的方法,用javap看他们的反编译结果

    public class com.study.main.Test extends java.lang.Object{
    public com.study.main.Test();
      Code:
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
       4:   return
    
    public static void main(java.lang.String[]);
      Code:
       0:   sipush  400 //40时我们用cipush(下同)  cipush(char 类型)的值范围是-128——127,sipush(short 类型)的值范围是2^15——2^15-1,
    3: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int eger; 6: astore_1 7: sipush 400 10: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int eger; 13: astore_2 14: iconst_0 15: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int eger; 18: astore_3 19: new #3; //class java/lang/Integer 22: dup 23: sipush 400 26: invokespecial #4; //Method java/lang/Integer."<init>":(I)V 29: astore 4 31: new #3; //class java/lang/Integer 34: dup 35: sipush 400 38: invokespecial #4; //Method java/lang/Integer."<init>":(I)V 41: astore 5 43: new #3; //class java/lang/Integer 46: dup 47: iconst_0 48: invokespecial #4; //Method java/lang/Integer."<init>":(I)V 51: astore 6 53: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream; 56: new #6; //class java/lang/StringBuilder 59: dup 60: invokespecial #7; //Method java/lang/StringBuilder."<init>":()V 63: ldc #8; //String i1=i2 65: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/ String;)Ljava/lang/StringBuilder; 68: aload_1 69: aload_2 70: if_acmpne 77 73: iconst_1 74: goto 78 77: iconst_0 78: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 81: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 84: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 87: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream; 90: new #6; //class java/lang/StringBuilder 93: dup 94: invokespecial #7; //Method java/lang/StringBuilder."<init>":()V 97: ldc #13; //String i1=i2+i3 99: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/ String;)Ljava/lang/StringBuilder; 102: aload_1 103: invokevirtual #14; //Method java/lang/Integer.intValue:()I 106: aload_2 107: invokevirtual #14; //Method java/lang/Integer.intValue:()I 110: aload_3 111: invokevirtual #14; //Method java/lang/Integer.intValue:()I 114: iadd 115: if_icmpne 122 118: iconst_1 119: goto 123 122: iconst_0 123: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 126: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 129: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 132: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream; 135: new #6; //class java/lang/StringBuilder 138: dup 139: invokespecial #7; //Method java/lang/StringBuilder."<init>":()V 142: ldc #15; //String i4=i5 144: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/ String;)Ljava/lang/StringBuilder; 147: aload 4 149: aload 5 151: if_acmpne 158 154: iconst_1 155: goto 159 158: iconst_0 159: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 162: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 165: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 168: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream; 171: new #6; //class java/lang/StringBuilder 174: dup 175: invokespecial #7; //Method java/lang/StringBuilder."<init>":()V 178: ldc #16; //String i4=i5+i6 180: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/ String;)Ljava/lang/StringBuilder; 183: aload 4 185: invokevirtual #14; //Method java/lang/Integer.intValue:()I 188: aload 5 190: invokevirtual #14; //Method java/lang/Integer.intValue:()I 193: aload 6 195: invokevirtual #14; //Method java/lang/Integer.intValue:()I 198: iadd 199: if_icmpne 206 202: iconst_1 203: goto 207 206: iconst_0 207: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 210: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 213: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 216: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream; 219: invokevirtual #17; //Method java/io/PrintStream.println:()V 222: return }

     比较后我们惊人的发现,两者其实没有什么区别

    只有这里:

     0:   sipush  400 //40时我们用cipush(下同)  cipush(char 类型)的值范围是-128——127,sipush(short 类型)的值范围是2^15——2^15-1

    我们看到第12行: 3:   invokestatic    #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int

    在Integer中是调用Integer.valueOf初始化对象的

    Integer.valueOf函数

     public static Integer valueOf(int i) {
            if(i >= -128 && i <= IntegerCache.high)
                return IntegerCache.cache[i + 128];
            else
                return new Integer(i);
        }
    

    IntegerCache

      private static class IntegerCache {
            static final int high;
            static final Integer cache[];
    
            static {
                final int low = -128;
    
                // high value may be configured by property
                int h = 127;
                if (integerCacheHighPropValue != null) {
                    // Use Long.decode here to avoid invoking methods that
                    // require Integer's autoboxing cache to be initialized
                    int i = Long.decode(integerCacheHighPropValue).intValue();
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - -low);
                }
                high = h;
    
                cache = new Integer[(high - low) + 1];
                int j = low;
                for(int k = 0; k < cache.length; k++)
                    cache[k] = new Integer(j++);
            }
    
            private IntegerCache() {}
        }
    

    通过研究发现:Integer.valueOf()中有个内部类IntegerCache(类似于一个常量数组,也叫对象池),它维护了一个Integer数组cache,长度为(128+127+1)=256;Integer类中还有一个Static Block(静态块),如上所示。

    从这个静态块可以看出,Integer已经默认创建了数值【-128-127】的Integer缓存数据。所以使用Integer i1=40时,JVM会直接在该在对象池找到该值的引用。

    也就是说这种方式声明一个Integer对象时,JVM首先会在Integer对象的缓存池中查找有木有值为40的对象,如果有直接返回该对象的引用;如果没有,则使用New keyword创建一个对象,并返回该对象的引用地址。因为Java中【==】比较的是两个对象是否是同一个引用(即比较内存地址),i2和i2都是引用的同一个对象,So i1==i2结果为”true“;而使用new方式创建的i4=new Integer(40)、i5=new Integer(40),虽然他们的值相等,但是每次都会重新Create新的Integer对象,不会被放入到对象池中,所以他们不是同一个引用,输出false。

      对于i1==i2+i3、i4==i5+i6结果为True,是因为,Java的数学计算是在内存栈里操作的,Java会对i5、i6进行拆箱操作,其实比较的是基本类型(40=40+0),他们的值相同,因此结果为True。

    但是但为400时,这个时候已经超过了cache的范围,所以都得重新初始化对象

  • 相关阅读:
    vmware 连网问题
    js控制表单非法输入时提交
    简单的jsp&servlet 购物车项目
    html引入css不显示问题
    每天学点java_反射作用
    java选择特定的值2--抽象enum
    java选择特定的值
    1 小时 SQL 极速入门(一)
    460004600146002MNCMCCIMSI
    网络中存在2台DHCP服务器问题
  • 原文地址:https://www.cnblogs.com/fjsnail/p/3473791.html
Copyright © 2020-2023  润新知