`
CSunDNan
  • 浏览: 6457 次
  • 来自: 杭州
社区版块
存档分类
最新评论

“比较”有意思

阅读更多

 

  • 你来猜?

Integer i = 127;

Integer j = 127;

 

i == j 答案是true还是false呢?如果是128呢?

昨晚在书上看到这么一个问题,感觉很有意思,呵呵。书上没有答案,我默算肯定两者都是true,后来跑了一下代码,奇迹出现了,还果然出了我的料。前者竟然是true,而后者是false。心理不踏实,便探个究竟。直接javap –verbose TestEqual这个类,发现对应的jvm指令基本上一致。没发现啥特殊之处,我想两者区别不应该体现在指令层面。虽然如此,但我发现有这个一个地方:

 

即,127被赋值给变量i或者j的时候,装箱成为了Integer,从上图中很容易看出调用Integer.valueOf(int)这个方法,返回值为Integer。所以我从这里展开追踪,哈哈。有了:

 

 

其中:IntegerCache.low = -128

  1. 注意到这里有个范围的控制,似乎是在这个范围中的数字,直接从缓存(Integer.cache)中取,而在范围之外的采用new的方式。关于new的方式我们都知道,会有一个新地址的出现。
  2. 从上面断言assert IntegerCache.high >= 127;强制要求high的下界为127,同时这个数值也是缓存的上界

现在继续,来看这个缓存的设置:

 

 

在缓存初次被使用的时候,就会被初始化了,如果没有通过设置属性来控制最大数值默认最大的数值为127。所以jvm为了性能的目的,将-128127 Integer数值缓存起来了。i == j,只要是属于这个区间的肯定返回true,因为虽然==比较的是地址( ),但他们确实是同一个地址。呵呵。所以我们最初问题的答案到这里便揭晓了,呵呵。

  • 不妨多想一下,看看ByteShortLongFloatDouble有没有同样的缓存机制呢?

看了一下jdk源码,发现ByteShortLong采用同样的机制,唯一不同的地方就是上界128是写死的。而FloatDouble没有采用该机制。

  • 既然说可以通过配置来扩大Integer的缓存上界,那就体验一把吧。

通过这个选项皆可以扩容了,呵呵。-XX:AutoBoxCacheMax=500,于是乎我在eclipse中配置了vm参数:

 

 

 

结果出现:

俺不懂了,于是乎上网查了一下,原来这个参数适应于server模式,不适合client模式,哈哈。好吧,改为:

 

-server -XX:AutoBoxCacheMax=500

 

哈哈,大功告成了:

Integer i = 128 Integer j = 128, 相等了。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics