java自动拆箱装箱与包装类型的缓存机制

缓存机制

Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False。 而Float和Double没有缓存机制。

举例子 源码分析

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;
            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() {}
    }

从中可以看出通过valueof 和cache 分析得出在范围内确实有这种缓存机制。

实验

Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出 true

Float i11 = 333f;
Float i22 = 333f;
System.out.println(i11 == i22);// 输出 false

Double i3 = 1.2;
Double i4 = 1.2;
System.out.println(i3 == i4);// 输出 false

Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);// 输出false

从字节码文件中可以看出 Integer i1 = 33;这种方式其实用的也是valueOf

 2 invokestatic #4 <java/lang/Integer.valueOf : (I)Ljava/lang/Integer;>
 5 astore_1
 6 bipush 33

自动装箱与拆箱

  • 装箱:将基本类型用它们对应的引用类型包装起来;
  • 拆箱:将包装类型转换为基本数据类型;

实验

Integer i = 10;  //装箱
int n = i;   //拆箱
0 bipush 10
2 invokestatic #4 <java/lang/Integer.valueOf : (I)Ljava/lang/Integer;>
5 astore_1
6 aload_1
7 invokevirtual #6 <java/lang/Integer.intValue : ()I>
10 istore_2
11 return

从字节码和实验中可以看出 装箱就是使用valueOf 拆箱就是使用value方法 所以装箱也有缓存机制。

如果频繁拆装箱的话,也会严重影响系统的性能。我们应该尽量避免不必要的拆装箱操作。

你可能感兴趣的:(java,缓存,开发语言)