java Integer与int的装箱(缓存)与拆箱

装箱与拆箱

JAVA中的自动装箱指的是把基本类型的值转换为对应的包装类对象自动拆箱则相反。如下代码所示:

 Integer i1=100;
 int i2=i1;
  • 分析如下:
  1. Integer i1=100实现了自动装箱,底层调用了调用包装类的valueOf方法,也就是Integer.valueOf(100)
  2. int i2=i1实现了自动拆箱,底层调用包装类的intValue方法。
    需要注意的是:自动装箱拆箱是 编译器 帮我们自动转换的,我们不需要手工调用valueOf()和intValue()方法。

Integer的缓存 -128~127

  • 自动装箱时的缓存问题:
    先看一个问题,对于下面定义的四个变量进行==比较:
    Integer a=1;
    Integer b=1;
    Integer c=200;
    Integer d=200;
    System.out.println(a==b);//true
    System.out.println(c==d);//false

我们都知道“= =”在JAVA里面是比较对象引用的,如果两个对象引用指向堆中的同一块内存就返回true,否则返回false。根据自动装箱规则我们知道Integer a = 1 等价于 Integer a = Integer.valueOf(1);,但是在valueOf方法上,查看源码:

public static Integer valueOf(int i) {
    final int offset = 128;
    if (i >= -128 && i <= 127) { // must cache
        return IntegerCache.cache[i + offset];
    }
        return new Integer(i);
}

Integer.valueOf()中有个内部类IntegerCache(类似于一个常量数组,也叫对象池),它维护了一个Integer数组cache,长度为(128+127+1)=256。Integer类中还有一个Static Block(静态块)

static {
        for(int i = 0; i < cache.length; i++)
        cache[i] = new Integer(i - 128);
}

从这个静态块可以看出,Integer已经默认创建了数值[-128,-127]的Integer缓存数据。所以使用Integer a=1时,JVM会直接在该在对象池找到该值的引用。也就是说这种方式声明一个Integer对象时,JVM首先会在Integer对象的缓存池中查找有木有值为1的对象,如果有直接返回该对象的引用如果没有则使用New Integer创建一个对象并返回该对象的引用地址。因为Java中==比较的是两个对象是否是同一个引用(即比较内存地址),a和b都是引用的同一个对象,所以a= =b结果为true;c和d已经超出了缓存的范围所以重新生成了Integer对象,所以c==d结果为false。

int和Integer的比较== equals()

  • 示例代码:
     class BoxIntInteger {
        
            public static void main(String[] args) {
         
                Integer a = new Integer(10111);
                int b = 10111;
                boolean equal1 = a == b;
                boolean equal2 = a.equals(b);
                System.out.println(equal1);
                System.out.println(equal2);
            }
        }

运行结果:

true
true
  • 反编译字节码:
 public static void main(String args[])
    {
        Integer a = new Integer(10111);
        int b = 10111;
        boolean equal1 = a.intValue() == b;  
        boolean equal2 = a.equals(Integer.valueOf(b));
        System.out.println(equal1);
        System.out.println(equal2);        
    }
  • 由实例代码和反编译代码可以看出:
  1. 可以看出对于Integer与int使用 = = 比较大小的话,优先Integer拆箱

  2. 如果使用equals比较大小的话,则int装箱

提示:对于Integer与int之间大小比较优先使用equals比较否则容易出现空指针,例如:

Integer c= null;
System.out.println(c==1);

原因:由于Integer需要调用intValue进行拆箱因而空指针

Integer与Integer必须使用equals方法比较,这个就不必解释了。但是通常我们可以看先Integer与Integer之间使用==也可以正确比较,原因是:Integer对于-128到127之间的数字在缓存中拿,不是创建新对象。

为什么要用到包装类型?

  1. 把一个基本类型包装成一个类,可以使这个类型具有很多可以调用的方法
  2. 包装类型使得Java向面向对象语言的靠近。其实Java还不算是很纯的面向对象的语言。真正的面向对象,是没有基本数据类型的。它只有一种类型,就是对象。
  3. 泛型中,基本类型是不可以做泛型参数的。如:List < int> list = new ArrayList< int> ();这是不合法的。你只能这个样写List< Integer> list = new ArrayList< Integer> ();也就是要用int型的包装类类型来解决基本类型不可以做泛型参数的问题 。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值