大家好,欢迎来到程序视点
!我是小二哥。
上一篇文章中,我们分辨了基本类型和包装类型的区别。今天我们来聊聊包装类型的缓存机制。
笔试题
关于包装类型的缓存机制,几乎是一道必考题。题例大概如下:
代码语言:javascript复制Integer a = 100;
Integer b = 100;
System.out.println(a == b);
代码语言:javascript复制Integer a = 200;
Integer b = 200;
System.out.println(a == b);
请给出上面两处打印的结果。答案分别是:true
和false
。
ps:如果你能正确给出答案,且能明白其中缘由,请直接查看文末最后一题。如果文末的题目你也能做对,且明白其中原因,那以下内容就可以直接跳过了;反之,请详细阅读本文。
同样都是包装类型的赋值,比较结果却不一样,这是怎么回事呢?这和自动装箱有关。
把基本类型转换成包装类型的过程叫做装箱(boxing)。
自动装箱的发生,就涉及到包装类型的缓存机制。(我们会在下一篇文章中来说明这个知识点)
包装类型的缓存源码
Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。
先记住下面这四句话:
Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据。 Character 创建了数值在 [0,127] 范围的缓存数据。 Boolean 直接返回 True or False。 两种浮点数类型的包装类 Float和Double 没有实现缓存机制。
自动装箱是通过包装类的 valueOf() 方法完成的。 因此,我们去看它们 valueOf() 方法的源码即可。
Integer 缓存源码:
代码语言:javascript复制public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i (-IntegerCache.low)];
return new Integer(i);
}
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;
...
high = h;
cache = new Integer[(high - low) 1];
int j = low;
for(int k = 0; k < cache.length; k )
cache[k] = new Integer(j );
...
}
}
Integer 的缓存是由一个Integer数组来实现的(上面哪个 cache 数组)。
ps:我这里只摘取了核心的逻辑。详细源码,请自行查阅JDK源码!
同理,Character 缓存源码:
代码语言:javascript复制public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
private static class CharacterCache {
private CharacterCache(){}
static final Character cache[] = new Character[127 1];
static {
for (int i = 0; i < cache.length; i )
cache[i] = new Character((char)i);
}
}
还有Boolean 缓存源码:
代码语言:javascript复制public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
至于Byte,Short和Long的缓存,就请大家抽空自己翻翻了。这里就不粘贴了。
特别注意:Float和Double 没有实现缓存机制。 我们来瞧瞧Double的valueOf()方法:
代码语言:javascript复制public static Double valueOf(double d) {
return new Double(d);
}
在double进行自动装箱时,返回的是new出来的一个对象,即每一个都是不同的。
最后一题
根据上面的知识,看看下面这道题的输出结果:
代码语言:javascript复制Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);
Float i11 = 333f;
Float i22 = 333f;
System.out.println(i11 == i22);
Double i3 = 1.2;
Double i4 = 1.2;
System.out.println(i3 == i4);
答案分别是:true
、false
、false
。你答对了吗?