基本 | boolean | char | byte | short | int | long | float | double |
包装 | Boolean | Character | Byte | Short | Integer | Long | Float | Double |
1、“==”比较两个变量值的字节组合模样,当 “==”运算符的两个操作数都是包装器类型的引用时,则是比较指向的是否是同一个对象;equals()判断两个对象的内容是否在意义上相等,是对象之间的比较,因为equals()本身就是对象的方法,不会对包装类型进行转换
Integer x = new Integer (0);
Integer y = new Integer (0);
System.out.println( x==y ); //false。操作数都是包装,不拆箱,比较是否为同一对象
System.out.println( x.equals(y)); //true。对象的内容(值)相等
当“==”有一个操作数是基本类型或者表达式(即含算术运算)则比较数值(拆箱)
int a = 1;
Integer b = 1;
Integer c = 2;
Integer d = 1;
System.out.println(a==b); //true。操作中混合使用基本和包装类型,b拆箱,比较值
System.out.println(c==(a+b)); //true。运算时b拆箱,比较时c拆箱,比较值
System.out.println(c.equals(a+b)); //true。a+b拆箱得到值,再装箱与c比较
System.out.println(c==(d+b)); //true。+运算时b,d拆箱,比较时c拆箱,比较值
System.out.println(c.equals(d+b)); //true。运算b,d拆箱得到值,再装箱与c比较
Long g = 3L;
Long h = 2L;
System.out.println(g==(a+b));//true。a+b触发自动拆箱,比较的是值
System.out.println(g.equals(a+b));//false。a+b先拆箱得int值,再装箱后为Integer型
System.out.println(g.equals(a+h));//true。a+h拆箱后值为long型,装箱后为Long型
2、Integer的常量池为(-128,127),赋给Integer常量池范围内的值时,直接从缓存返回相同引用;超过常量池范围时,会重新new一个对象。
Integer c = 3; //int给赋Integer时,会调用valueOf()方法装箱: Integer c=Integer.valueOf(3);
Integer d = 3;
Integer e = 321;
Integer f = 321;
System.out.println(c==d); //true.在常量池,是相同引用
System.out.println(e==f); //false.不在常量池,是两个不同对象
System.out.println(c.equals(d)); //true.与下一句一样,对象内容相等
System.out.println(e.equals(f)); //true
此条法则对Short,Long等效,而Byte本身范围就在常量池范围。但对于Float和Double则都输出false,因为它们的valueOf()方法与Integer类的valueOf()方法实现方式不同。
3、Integer i = new Integer(xxx)和Integer i =xxx;的区别
- 第一种方式不会触发自动装箱的过程;而第二种方式会触发;
- 在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。
4、如果Integer引用未初始化,则自动拆箱时会报错:NullPointerException-空指针异常。
public class _try{
public Integer i;
int j;
public static void main(String[] args) {
_try a=new _try();
a.go();
}
public void go() {
j=i; //改成i=j,则输出0,0
System.out.println(i);
System.out.println(j);
}
}
因为引用没有初始化就是null。现在i是一个null,没有指向任何对象,故与基本类型混合使用自动拆箱时就会报一个NullPointException异常。
5、更适合用包装类型:
- 作为集合中的元素、键和值。
- 在参数化类型中。比如:你不能这样写——ArryList<int>,你只能写ArrayList<Integer>
- 在进行反射方法的调用时。
个人理解:拆箱和装箱都是有需要的时候编译器自动进行的。
拆箱:包装做运算,包装和基础比较、运算时,包装赋值给基础(赋值、传参、传返回值)
装箱:基础赋给包装(赋值、传参、传返回值)
不过基础和包装遇到重载的时候不转换类型