int相信我们都很熟悉吧,Java中的原始数据类型,同为原始数据类型的还有long、short、float、double、char、byte、boolean。原始数据类型不是对象。
Integer是int对应的包装类,其中有一个private final int value;
来存储数据,并且还提供了一些基本操作,例如sum、max、int和字符串的转换等方法。从value声明为private final
可以得知它也是一个不可变类型!
在Java5中引入了自动装箱和自动拆箱功能,也就是Java可以根据上下文自动将int转为Integer或Integer转为int。自动装箱、拆箱其实算一种语法糖(语法糖就是对现有语法的一个封装,主要是为了方便程序员的开发,提高开发效率)。
在编译阶段发生,由javac来帮我们自动装箱、拆箱。具体是调用Integer.valueOf
方法来进行装箱,调用Integer.intValue
方法来进行拆箱。我们来反编译下看看是不是这样,例如以下代码
public class IntegerTest {
public static void test() {
Integer integer = 100;
int a = integer + 1;
}
}
反编译结果,确实是这样!
我们再来说说这个valueOf方法,构建Integer对象的传统方式是直接调用构造器new一个对象,但是根据实践发现大部分的数据操作都集中在值比较小的范围,所以Java5中又引入了静态工厂方法valueOf,调用它时会利用IntegerCache
,也就是一个缓存,能带来明显的性能改进。默认的缓存值是-128到127。
什么意思呢?先看一下源码
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
如果没有修改默认缓存值(-128到127)的话,我们执行Integer i = 一个值(注意不是直接new Integer,直接new是不会利用缓存的),这个值如果大于等于-128,小于等于127,是不会new一个新的Integer对象而是去IntegerCache去找到这个缓存对象的引用直接返回。这样我们常用的一些值就能直接用缓存了!减少了消耗!
如果明确知道常用的整型的值更大一些那也是可以修改默认缓存值的。
通过设置JVM-XX:AutoBoxCacheMax=<size>
来修改缓存的最大值,最小值改不了。
再来看看IntegerCache都干了啥
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
很简单吧,就是弄了个Integer数组,在静态代码块内去读看看我们有没有设-XX:AutoBoxCacheMax=<size>
,没得话直接就拿默认的缓存值初始化cache数组,并且将一个个Integer放入数组内,如果有设置
integerCacheHighPropValue
就修改下最大的缓存值,然后操作。
还有一点要注意:避免无意中的装箱和拆箱,特别是在性能敏感的场合,因为创建大量的对象和大量的整数,无论是从内存角度还是处理速度上开销不是一个数量级的。所以在性能敏感的场合尽量使用原始数据类型。
如有错误欢迎指正!
个人公众号:yes的练级攻略
网友评论