Java Integer 装箱 && 拆箱 && 相等性比较 && NULLPointerException

装箱与拆箱

		//手动装箱
		Integer a=Integer.valueOf(10);
		System.out.println("手动装箱"+a.intValue());
		
		//自动装箱
		Integer b=10;   //自动调用valueof(10)方法
		System.out.println("自动装箱"+b.intValue());
		
		//手动拆箱
		int c=a.intValue();
		System.out.println("手动拆箱"+c);
		
		//自动拆箱
		int d=a;        //自动调用a.intValue();
		System.out.println("自动拆箱"+d);

结果

手动装箱10
自动装箱10
手动拆箱10
自动拆箱10

在算式表达式中

		Integer n=3;
		n++;
		System.out.println("n="+n);
		//编译器自动插入一条对象拆箱的指令,然后进行自增计算,最后再将结果装箱 

结果

n=4

在条件表达式中混合使用Integer和Double

		Integer s=1;
		Double  x=2.0;
		System.out.println("条件表达式中s = "+(s<x?s:x));  
		//混合使用Integer和Double
		//在条件表达式中,Integer值会拆箱,提升为Double,再装箱为Double

结果

条件表达式中s = 1.0

NULLPointerException

		Integer n=null;
		System.out.println(n+1);//throws NULLPointerException
		//计算n+1中,n会自动拆箱(调用n.intValue())
		//但是n为空,调用空对象的方法会抛出空指针异常(NULLPointerException)

结果
空引用
Integer相等性比较
例1

		Integer n=128;    //等价于 Integer n=Integer.valueOf(128);
		Integer s=128;    //等价于 Integer s=Integer.valueOf(128);
		System.out.println(" n == s "+(n==s));
		System.out.println(" n equals s "+n.equals(s));		

结果

 n == s false
 n equals s true

例2

		Integer n1=127;    //等价于 Integer n1=Integer.valueOf(128);
		Integer s1=127;    //等价于 Integer s1=Integer.valueOf(128);
		System.out.println(" n1 == s1 "+(n1==s1));
		System.out.println(" n1 equals s1 "+n1.equals(s1));

结果

 n1 == s1 true
 n1 equals s1 true

原因分析
object类的equals方向比较的地址

	public boolean equals(Object obj)  
	   {  
	       return this == obj;  
	   }

Integer类的equals重新object类,比较的是值

 	public boolean equals(Object obj) 
 	{
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

所以例一和例二的equals都为true,但是比较地址时,127为true,128为false
因为Integer装箱时,会自动调用Integer.valueof方法。

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

所以如果ii >= IntegerCache.low && i <= IntegerCache.high 则会调用IntegerCache.cache

private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

cache用来节省内存和提高性能。整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用。
Integerl类第一次使用时,会初始化一个IntegerCache.cache的数组,数组里面存储-128 到 127之间的数字。
之后调用valueOf(i)方法时,如果i在-128 到 127之间,就会从IntegerCache.cache取出i对应的Integer对象;如果不在这个区间,就会返回new Integer(i)
注意事项

		Integer s1=127;    
		Integer s2=new Integer(127);
		System.out.println(" s1 == s2 "+(s1==s2));
		System.out.println(" s1 equals s2 "+s1.equals(s2));

结果

 s1 == s2 false
 s1 equals s2 true

因为s1为IntegerCache.cache中的对象,s2为new 的新对象,所以二者地址不同

你可能感兴趣的:(Java)