自动装箱和拆箱**
*java的基本数据类型
1字节:byte和boolean
2字节:short和char
4字节:int和float
8字节:long和double
*基本数据类型对应的包装类分别是Byte,Boolean,Short,Character,Integer,Float,Long,Double
*自动装箱
类的实例化一般
Object obj=new Object();
Integer类
Integer i=5;
实际上是Integer类自动调用了Integer i=Integer.ValueOf(5);
基本数据类型装箱完成
*自动拆箱
Integer i=new Integer(5);
int it=i; 这里进行了自动拆箱,调用了i.intValue();把包装类拆成基本数据类型
*自动装拆箱的注意事项
`
Integer i1=10;
Integer i2=10;
Integer i3=128;
Integer i4=128;
Integer i5=new Integer(7);
Integer i6=new Integer(7);
int k1=10;
int k2=128;
System.out.println(i1==i2); //true
System.out.println(i3==i4); //false
System.out.println(i5==i6); //false
System.out.println(i1==k1); //true
System.out.println(i3==k2); //true`
由以上代码可以分析:
*1.结果第一行打印true,i1和i2被包装后,==比较的是两者的内存地址。相当于分别new了两个对象,应该是false.但是返回是true,为什么呢?
因为在自动装箱的时候调用了ValueOf()方法,那么我们查看以下该方法的源码:
` public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}`
static final int low = -128;
static final int high = 127;
-由源码可以ValueOf()源码可以看出,当传入基本数据类型在 -128~127之间返回的是缓存数组里面的数据。第一次声明则将i1放入缓存中,第二次i2直接从缓存数组中取值,没有重新new一个对象。所以两者地址相同,返回true.
-除了Integer类外,还有Byte、Short、Long、Character也使用了缓存,而Flot、Double没有使用缓存。
*2.由第一行分析的结果分析,自然可得出第二行结果是false.因为128超出了缓存范围,直接new对象,i3和i4都是新new的对象,放在堆中不同位置。所以==返回false.
*3.由第二行结果分析,自然可得出第三行结果是false.虽然是在low~hight的范围内,但是直接用的new,手动包装,没有调用ValueOf()方法自然没有放缓存和从缓存中取的说法。i5和i6是不同地址
*4.Integer(无论new否)和int比较,Integer会自动拆箱。两个基本数据类型,==比较的是数值。
*5.与4同理
`Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
System.out.println(c == d); //true
System.out.println(e == f); //false
System.out.println(c == (a + b));//true
System.out.println(c.equals((a+b))); //true
System.out.println(g == (a+b));
System.out.println(g.equals(a+b));
System.out.println(g.equals(a+h));`
*1.由之前的分析可知返回true.
*2.同之前的缓存分析知返回false.
*3.右边a+b包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),==比较符又将左边的自动拆箱,因此它们比较的是数值是否相等。
反编译 :c.intValue()==a.intValue()+b.intValue();
*4.看看Integer中的equals源码
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
由此可知,Integer的equals被重写。equals会把同一类型的转化为数值比较。
因此结果返回true.
*5.g == (a+b),首先计算 a+b,也是先调用各自的intValue方法,得到数值之后,==运算符能将隐含的将小范围的数据类型转换为大范围的数据类型,也就是int会被转换成long类型,由于前面的g是Long类型的,也会自动拆箱为long,两个long类型的数值进行比较。因此结果返回true.
*6.a+b得到的是Integer类型的。Long类中的equals方法和4中的同理,判断括号内的数值是否是Long类型的实例。不是就返回false,不会进行类型转换。因此返回false.
*7.g.equals(a+h),运算符+会进行类型转换,转为大范围的数据类型。a+h各自拆箱之后是int+long,结果是long,然后long进行自动装箱为Long,两个Long进行equals判断。结果是true.