美文网首页
Java装箱类缓存分析

Java装箱类缓存分析

作者: 王小宝wy | 来源:发表于2017-07-14 19:02 被阅读0次

Integer

Integer内部有一个IntegerCache类,这个类用来缓存int型数值,默认缓存的范围是-128 ~ 127,如果设置了系统属性java.lang.Integer.IntegerCache.high,则获取这个系统属性,之后进行比对:

i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);

正常情况下,上限要么还是127,要么就是java.lang.Integer.IntegerCache.high, 如果该系统属性比Integer.MAX_VALUE - 128 - 1还大, 那么上限就是Integer.MAX_VALUE - 128 - 1(有谁会那么蛋疼的把上限设这么高?.), 确定好上限后,会初始化内部的缓存数组:

cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
 cache[k] = new Integer(j++);

预先放入-128 ~ 127范围内的Integer对象

当调用Integer.valueOf(int)时, 会首先判断传入的int值是不是在-128127范围内,如果从`ImageCache`中直接获取`Integer`对象,这样避免了重新创建一个Integer的内存开销;如果不在-128127范围内,那么就直接生成一个新的Integer, 代码如下:

    public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

Integer内部有缓存,那么同样都是装箱对象的Double,Long等类型会有缓存吗?

Byte

    private static class ByteCache {
        private ByteCache(){}

        static final Byte cache[] = new Byte[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Byte((byte)(i - 128));
        }
    }
    
    public static Byte valueOf(byte b) {
        final int offset = 128;
        return ByteCache.cache[(int)b + offset];
    }

Byte是基础类型byte的装箱类,一个byte代表的是一个字节,刚好是-128 ~ 127,所以Byte装箱类缓存了byte可能的所有值

Short

  private static class ShortCache {
        private ShortCache(){}

        static final Short cache[] = new Short[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Short((short)(i - 128));
        }
    }
    
    public static Short valueOf(short s) {
        final int offset = 128;
        int sAsInt = s;
        if (sAsInt >= -128 && sAsInt <= 127) { // must cache
            return ShortCache.cache[sAsInt + offset];
        }
        return new Short(s);
    }


可以看到Short也是缓存了-128 ~ 127范围内的值

Long

   private static class LongCache {
        private LongCache(){}

        static final Long cache[] = new Long[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Long(i - 128);
        }
    }
    
    public static Long valueOf(long l) {
        final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
    }
    

Long内部也使用了缓存,范围也同样是-128 ~ 127

Double、Float

    public static Float valueOf(float f) {
        return new Float(f);
    }
    
    public static Double valueOf(double d) {
        return new Double(d);
    }
    

可以看到, Double, Float内部并没有使用缓存,而是每次都是直接生成一个新的对象

为什么这两个类没有做缓存呢?因为没意义……这两个类代表的都是浮点数,从Integer, Short,Byte中可以看到,缓存至多存256个数,缓存太多反而会占用更多内存,而浮点数是包含小数点后面的数,如果要缓存256个数,应该怎么选范围呢?还是-128~127?那126.01怎么办,没有缓存到啊,126.10也没有缓存到,所以对于浮点数来说缓存命中率太低,还不如不缓存,省的浪费内存

相关文章

  • Java装箱类缓存分析

    Integer Integer内部有一个IntegerCache类,这个类用来缓存int型数值,默认缓存的范围是-...

  • RecyclerView

    RecyclerView的四级缓存分析 Recyclerview的缓存类RecycleView的四级缓存是由三个类...

  • 优秀博客集锦(一)

    理解Java Integer的缓存策略Java中Integer和其他包装类具有缓存机制,会缓存常用的一部分数字。 ...

  • 2018-04-11

    java实现简单的缓存 下面代码展示用java实现一个简单缓存: 上面代码中,CacheImmutable类直接调...

  • JAVA类加载机制

    jvm之java类加载机制和类加载器(ClassLoader)的详解java类加载机制:全盘负责、双亲委派、缓存机...

  • 学习路线

    Java Se基础 Java基础语法、数组、类与对象、继承与多态、异常、范型、集合、流与文件、反射、枚举、自动装箱...

  • 8.包装类,包装类的自动装箱和自动拆箱

    问题:关于 Java 包装类,包装类的自动装箱和自动拆箱你怎么理解? 从程序语言来说,Java语言是一个面向对象语...

  • 数据结构--容器汇总(java & Android)

    数据结构与算法容器概览(java)容器类框架分析(1)(java)ArrayList源码分析容器类框架分析(2)(...

  • Java自动装箱踩坑

    Java有装箱和拆箱 把基本数据类型转换成包装类的过程就是打包装,英文对应于boxing,中文翻译为装箱。 反之,...

  • 《剖析缓存系列》—— 熟悉JSR-107 JAVA缓存规范

    本系列介绍 本系列《剖析缓存系列》,由浅到深的对缓存进行分析介绍,从缓存形式,更新策略,常见问题,以及JAVA缓存...

网友评论

      本文标题:Java装箱类缓存分析

      本文链接:https://www.haomeiwen.com/subject/uquohxtx.html