美文网首页
站在源码角度看Integer相关的面试题

站在源码角度看Integer相关的面试题

作者: 蜗牛没吃饱 | 来源:发表于2020-01-01 16:08 被阅读0次

    最近市场行情不太好,为了让自己保值,打算从基础开始重新学一遍java相关的知识。
    今天先从最简单的Integer说起,Integer实际上是int的封装类,因为在java的世界里,万物皆对象,即便是基础数据类型,实际上在背后都会有对应的封装类。

    当我们写Integer a=new Integer(100);时实际上就是纯粹的创建了一个Integer对象。
    当我们写Integer a=100;时,实际上由于java语法糖的存在,编译器会将这行代码翻译成Integer a=Integer.valueOf(100);我们再来看Integer.valueOf(int i)方法:

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

    继续看IntegerCache类:

    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() {}
    }
    

    通过以上代码,我们可以很清楚的知道在Integer内部存在一个缓存,这个缓存会默认保存-128~127个Integer对象,而且这些对象的创建写在了static块中,意味着很早就被创建出来了。一旦我们执行Integer a=x(-128<=x<=127,实际上返回的都是同一个IntegerCache中缓存的对象。只有当x>127或x<-128时,才相当于new了一个新对象。
    看到这里我们就需要掌握一个技巧了:
    能用a=100就不要用a=new Integer(100),以达到利用Integer缓存的机制。

    Integer类还有个需要看的地方是他重写了equals方法:

        public boolean equals(Object obj) {
            if (obj instanceof Integer) {
                return value == ((Integer)obj).intValue();
            }
            return false;
        }
    

    很清晰的可以看到,Integer之间的equals比较实际上就是”值“比较,只需要看两个数一不一样就好了。那有人会问,int属于Integer嘛?当然,int在底层会被自动转成Integer,还记得那句话么?万物皆对象。

    通过以上的了解,大家可以试着做一下下面这些题:

       //第1题
        int a=100;
        Integer b=100;
        System.out.print(a==b);
    

    答案:true
    解释:当一个Integer对象和基本数据类类型int相比较的时候,虚拟机会将Integer对象自动拆包成int,这个时候通过==进行比较的就是”值“了。

       //第2题
        int a=100;
        Integer b=new Integer(100);
        System.out.print(a==b);
    

    答案:true
    解释:与第一题一样,无论这个Integer对象是通过语法糖创建的,还是通过new对象创建的。其本质都已经是Integer对象了。只要是Integer对象,在和int进行==比较时,就都是”值“比较。

       //第3题
        Integer a=100;
        Integer b=100;
        System.out.print(a==b);
    

    答案:true
    解释:两个都是对象,但由于-128<100<127,所以实际上都是去的IntegerCache中的同一个对象,当两个对象进行==比较时,实际上是比较的内存地址,因为只是同一个对象的两个不同引用,所以内存地址实际相等。

       //第4题
        Integer a=130;
        Integer b=130;
        System.out.print(a==b);
    

    答案:false
    解释:IntegerCache只缓存-128-127之间的数对象。对于不在其范围内的对象都相当于创建了一个新对象。(除非动了虚拟机参数,将IntegerCache的缓存范围修改了。)

       //第5题
        int a=130;
        Integer b=130;
        Integer c=130;
        Integer d=new Integer(130);
        System.out.print(b.equal(a)&&b.equals(c)&&b.equals(d)&&c.equals(d));
    

    答案:true
    解释:integer重写了equals方法,将判断改成了值判断,值相等则equals方法一定为true。

    相关文章

      网友评论

          本文标题:站在源码角度看Integer相关的面试题

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