专栏首页Java技术栈Java中的享元设计模式,涨姿势了!

Java中的享元设计模式,涨姿势了!

首先来看一段代码:
public class ShareTest {
  public static void main(String[] args) {
    Integer a = 127;
    Integer b = 127;
    System.out.println(a==b);
    Integer c = 128;
    Integer d = 128;
    System.out.println(c==d);
  }
}

运行结果为:true false

为什么会出现这种情况呢?我们来从源代码中分析一下,首先Integer a = 127这行代码调用的是Integer中的valueOf方法,我们来看看这个方法的源码:

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

其中IntegerCache就是Integer中的一个内部类,看下这篇:IntegerCache的妙用和陷阱,从这段代码中我们可以看出,当我的参数i的范围在low和high之间时,会直接返回这个内部类中的一个数组中对应的值,否则会创建一个新的对象。

那么我们再来看你看这个数组是怎么创建的:


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) {
      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);
    }
    high = h;

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

  private IntegerCache() {}
}

由这段代码我们可以知道,这个内部类在初始化的时候创建了一个数组,并且这个数组的长度为 (high-low+1),然后遍历循环,创建了从-128到127这256个Integer对象,并将它们放入到这个数组中。

另外,推荐大家关注微信公众号:Java技术栈,在后台回复:设计模式,可以获取我整理的 N 篇最新设计模式教程,都是干货。

所以当我们在调用valueOf的时候,如果值得范围是在128到127之间,那么是不会创建新的对象的,但是如果超过了这个范围,那么就会创建姓的对象。这就是之前代码运行结果的原因。

到了这里,享元模式的核心思想已经渐渐清晰了,其实就是将一些常用的对象缓存起来,在使用的时候直接拿过来使用,不必创建新的对象,这个省去了创建对象时消耗的资源,也省去了GC在回收这些垃对象时消耗的资源。

在我们日常开发中,享元模式还是比较常见的,最典型的就是池技术,例如服务器的线程池,JDBC的连接池,这些都是享元模式的很好的体现,当然,常量池也是享元模式思想。

作者:Mazin

https://my.oschina.net/u/3441184/blog/886337

本文分享自微信公众号 - Java技术栈(javastack)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • GET方法传递中文参数乱码解决办法

    原文地址:http://blog.163.com/sparkle_tiangz/blog/static/117590203201011042727965/

    逝兮诚
  • 深入理解GBDT回归算法

    Boosting、Bagging和Stacking是集成学习(Ensemble Learning)的三种主要方法。Boosting是一族可将弱学习器提升为强学习...

    OpenCV学堂
  • java反射----根据方法名,类和对象执行对象的该方法

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    逝兮诚
  • 蓝桥杯JAVA Fibonacci数列

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    逝兮诚
  • 速度提升一倍,无需实例掩码预测即可实现全景分割

    论文链接:https://arxiv.org/pdf/1910.03892.pdf

    OpenCV学堂
  • C#刷遍Leetcode面试题系列连载(5):No.593 - 有效的正方形

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    Enjoy233
  • js实现关于数据字典的使用和数据存放的策略

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    逝兮诚
  • mysql完成字符串分割

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    逝兮诚
  • 查询结果集合成一列的sqlserver实现方法stuff

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    逝兮诚
  • mysql存储过程----三种定义变量方式

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    逝兮诚

扫码关注云+社区

领取腾讯云代金券