资讯专栏INFORMATION COLUMN

Hold住面试官之Integer Cache

Cheriselalala / 3009人阅读

摘要:还有需要注意的一点是,此类缓存行为不仅存在于对象。还存在于其他的整数类型,,,。但是能改变缓存范围的就只有了。

前言

最近跟许多朋友聊了下,在这个“跳槽”的黄金季节,大家都有点蠢蠢欲动,所以最近就多聊聊面试的时候需要注意的一些问题,这些问题不一定多深奥,多复杂,但是一不注意的话却容易掉坑。下面看一下面试的时候经常遇到的一段代码:

public class IntegerDemo {
    public static void main(String[] args) {
        Integer numA = 127;
        Integer numB = 127;

        Integer numC = 128;
        Integer numD = 128;

        System.out.println("numA == numB : "+ (numA == numB));
        System.out.println("numC == numD : "+ (numC == numD));
    }
}

根据大家以往的经验,会认为上面的代码用“==“符号来比较,对比的是对象的引用,那么ABCD是不同的对象,所以输出当然是false了。我在《“==”、“equals()”、“hashcode()”之间的秘密》这篇文章也讨论过。那么事实也是如此吗?下面看一下输出结果:

numA == numB : true
numC == numD : false

What?这个输出结果怎么跟以往的认知有所出入呢?在我们的代码“Integer numA = 127”中,编译器会把基本数据的“自动装箱”(autoboxing)成包装类,所以这行代码就等价于“Integer numA = Integer.valueOf(127)”了,这样我们就可以进入valueOf方法查看它的实现原理。

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

//Integer静态内部类
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方法会先判断传进来的参数是否在IntegerCache的low与high之间,如果是的话就返回cache数组里面的缓存值,不是的话就new Integer(i)返回。

那我们再往上看一下IntegerCache,它是Integer的内部静态类,low默认是-128,high的值默认127,但是high可以通过JVM启动参数XX:AutoBoxCacheMax=size来修改(如图),如果我们按照这样修改了,然后再次执行上面代码,这时候2次输出都是true,因为缓存的区间变成-128~200了。

但是如果我们是通过构造器来生成一个Integer对象的话,下面的输出都是false。因为这样不会走ValueOf方法,所以按照正常的对象对比逻辑即可。

public class IntegerDemo {
    public static void main(String[] args) {
        Integer numA = new Integer(127);
        Integer numB = new Integer(127);

        Integer numC = new Integer(128);
        Integer numD = new Integer(128);

        System.out.println("numA == numB : "+ (numA == numB));//false
        System.out.println("numC == numD : "+ (numC == numD));//false
    }
}

还有需要注意的一点是,此类缓存行为不仅存在于Integer对象。还存在于其他的整数类型Byte,Short,Long,Character。但是能改变缓存范围的就只有Integer了。

结语

有时候往往越简单的知识越容易掉坑里,所以要保持自己的求知欲,不断巩固的基础,才能让自己在面试的时候不会栽跟头。

文章始发于微信公众号《深夜里的程序猿》,每天分享最干的干货,转载请注明出处,侵权必究。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77509.html

相关文章

  • Tornado Demo 之 chatdemo 不完全解读

    摘要:清楚了以上流程,我们直接来看函数主要用作初始化应用监听端口以及启动。其中就是保存聊天室所有聊天消息的结构。关于的解读我会放到阅读源码时讲。然后把消息加到缓存里,如果缓存大于限制则取最新的条消息。 tornado 源码自带了丰富的 demo ,这篇文章主要分析 demo 中的聊天室应用: chatdemo 首先看 chatdemo 的目录结构: ├── chatdemo.py ├── ...

    TesterHome 评论0 收藏0
  • IntegerCache

    摘要:类实际上是中中的缓存类,目的是节省内存消耗,提高程序性能。而当堆内存中的对象存储非常多时,就有可能造成内存泄漏。使用频率高创建对象也就越多,堆内存中的对象也就越多,所以也就会可能发生上述中的内存溢出等问题。 面试题:问以下代码输出的结果是多少? public class IntegerTest { @Test public void test() { ...

    yiliang 评论0 收藏0
  • 踩坑记[持续更新]

    摘要:解决的中只有一个生命周期的钩子也只有一句代码报错中的就是整个组建中的原来是写在了使用指令的后面所以此时还没有在组件中注册所以会报错误正确代码标题这是一段内容这是一段内容这是一段内容这是一段内容。 用于记录coding过程中遇到的比较难解决或者有意思的问题,包括前端/后端(Node/Db),会持续更新... 后端 Node redis集群模式下pipline报错(2019.3.14) ...

    0x584a 评论0 收藏0
  • 踩坑记[持续更新]

    摘要:解决的中只有一个生命周期的钩子也只有一句代码报错中的就是整个组建中的原来是写在了使用指令的后面所以此时还没有在组件中注册所以会报错误正确代码标题这是一段内容这是一段内容这是一段内容这是一段内容。 用于记录coding过程中遇到的比较难解决或者有意思的问题,包括前端/后端(Node/Db),会持续更新... 后端 Node redis集群模式下pipline报错(2019.3.14) ...

    ckllj 评论0 收藏0

发表评论

0条评论

Cheriselalala

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<