十、享元模式
本文最后更新于 944 天前,其中的信息可能已经有所发展或是发生改变。

Flyweight

定义

共享存储单元,节约内存空间。

使用场景

例如文本编辑器里,每个字符都有字体大小,显示颜色,背景颜色等属性。将这些属性抽取为字体,每个字体的属性在内存中只保留一份即可。感觉和CSS挺像的,不过享元模式侧重点不是代码复用,而是对象复用。

JDK里使用的地方

Integer缓存

int类型在自动装箱时,调用java.lang.Integer#valueOf(int)

    public static Integer valueOf(int i) {
        // 如果在缓存范围内
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            // 直接返回缓存中的对象
            return IntegerCache.cache[i + (-IntegerCache.low)]; 
        return new Integer(i);
    }

IntegerCache是Integer的私有静态内部类

    private static class IntegerCache {
        // 缓存范围低位是固定的
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // 高位默认127,可配置
            // high value may be configured by property
            int h = 127;
            // 读取JVM参数
            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;
            // 第一次调用java.lang.Integer#valueOf(int)时才初始化,实例化缓存范围内的所有对象,和String的缓存机制不同
            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() {}
    }

String缓存

通过字面量的形式创建字符串时,jvm会先在字符串常量池中查找是否有相同内容的字符串,如果要,就返回其引用。否则就创建字符串对象,并存入字符串常量池里。

字符串常量池的位置

在JDK 7以前的版本中,字符串常量池是放在永久代中的。

因为按照计划,JDK会在后续的版本中通过元空间来代替永久代,所以首先在JDK 7中,将字符串常量池先从永久代中移出,暂时放到了堆内存中。

在JDK 8中,彻底移除了永久代,使用元空间替代了永久代,于是字符串常量池再次从堆内存移动到永久代(元空间)

作者:Yuyy
博客:https://yuyy.info
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇