Integer a = Integer.valueOf(100);
Integer b = Inteegr.valueOf(100);
Double d1 = Double.valueOf(100);
Double d2 = Double.valueOf(100);
System.out.println(d1==d2);//false
System.out.println(a==b);//true
Integer c = 100;

在给Integer赋值时,实际上是自动装箱的过程,调用了Integer.valueOf()方法,当这个值大与等于-128并且小于等于127时使用了常量池。所以a与b的地址是相等的。而Double超过了127,故不使用常量池。

java的中基本数据类型,只有float与double没有常量池。其他六种都实现了常量池,但是只在大于等于-128并且小于等于127时才使用常量池。

public class Test {
     public static void main(String[] args) {
         constantTest();
     }
     public static void constantTest() {
         Integer i1 = 20;
         Integer i2 = 20;
         Integer i3 = 0;
         Integer i4 =  new Integer(10);
         Integer i5 = new Integer(10);
         Integer i6 = new Integer(0);
         Integer i7 = 200;
         Integer i8 = 200;
         System.out.println(i1==i1);//true
         System.out.println(i1==i2+i3);//true
         System.out.println(i4==i5);//false
         System.out.println(i4==i5+i6);//true
         System.out.println(i7==i8);//false
     }
 }


如下代码:Integer i1 = 20;java在编译时zi自动将代码装箱,也就是执行了Integer.valueOf(20)

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

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

i7==i8为false是因为Integer i7=200,Integer i8=200他们的值已经超出了常量池的范围,JVM会对i1和i2各自创建新的对象(即Integer i1=new Integer(200)),所以他们不是同一个引用。

包装类的常量池:
    将基本数据类型进行自动装箱时,装箱后的对象的字面值,如果是在-128-127之间,会先检查常量池中是否有相同字面值的对象
  如果有,则将常量池中对象的地址给引用变量。
  总结:
  (1)八种包装类都是final修饰
  (2)一经创建,对象内容不可变。
  (3)Character和Boolean的父类是Object其他六种类是Number类型。