JAVA自动装箱拆箱以及装箱时的缓存问题

来源:互联网 发布:ubuntu安装fcitx五笔 编辑:程序博客网 时间:2024/05/01 03:36
一个很古老的问题了,但是有些细节还是需要我们注意的。

0> 概述
JAVA中的自动装箱指的是把基本类型的值转换为对应的包装类对象,自动拆箱则相反。
JAVA中的基本类型: boolean, byte, char, short, int, long ,float, double
对应的包装类型: Boolean, Byte, Character, Short, Integer, Long, Float, Double
自动装箱时调用包装类的valueOf方法,比如Integer.valueOf(100).
自动拆箱时调用包装类的xxxValue方法,比如intObj.intValue();
注意,自动装箱拆箱是编译器帮我们自动转换的,我们不需要手工调用valueOf()和intValue()方法。

1> 自动装箱
  1)把一个int值赋给Integer类型
  2)集合类添加原始类型时的自动装箱

2> 自动装箱时的缓存问题
  先看一个问题,对于上面定义的四个变量进行==比较:
我们都知道==在JAVA里面是比较对象引用(地址)的,如果两个对象引用指向堆中的同一块内存就返回true,否则返回false。
根据自动装箱规则我们知道Integer intObj = 1 <==> Integer intObj = Integer.valueOf(1);,鬼就出在valueOf方法上,查看源码:
发现如果valueOf(i)的参数i再[low,high]范围内,就直接从缓存里面取出一个事先new好的对象返回,这里low,high默认值分别为-128, 127,即i如果落在[-127, 128],就会直接返回缓存里面的对象。
所以: Integer i11=1; 和Integer i12=1;返回的是同一个对象,而对于Integer i21=200和Integer i22=200,因为超出了缓存范围,所以每次都是从堆内存中new出一个新的对象返回,这就是==不成立的原因了。
说句题外话,对于Integer,我们可以通过-Djava.lang.Integer.IntegerCache.high=10000或者 -XX:AutoBoxCacheMax=2000(server模式启动)来设置缓存的范围

除了Integer,其它包装类型对缓存的使用如下:
  * Boolean就两个缓存值TRUE,FALSE
  * Byte占1个字节,表示范围是[-128,127], 因为范围不大,所以全部256个值都是缓存的
  * Short, Long缓存范围是[-128,127],而且不可更改. 也无法通过extends方式扩展,因为这两个类是final的
  * Float,Double没有缓存,每次valueOf(1.0)都是返回一个堆中的新对象

3> 自动拆箱
  1) Integer和int类型进行 == > >= < <=比较时,会把Integer自动拆箱
  2) Integer和Integer进行 > >= < <=比较时,两个都会自动拆箱
  3) switch会自动拆箱,但是case后面只能是常量 (字面量或者常变量)

看来上面这些,不知道你是否有新的收获,如果有,那么作者的目的就达到了~
2 0
原创粉丝点击