• 一道Integer面试题引发的对Integer的探究


      

    面试题:

    //在jdk1.5的环境下,有如下4条语句:
    
    Integer i01 = 59;
    int i02 = 59;
    Integer i03 =Integer.valueOf(59);
    Integer i04 = new Integer(59);
    
    以下输出结果为false的是:
    
    A.   System.out.println(i01== i02);
    B.   System.out.println(i01== i03);
    C.   System.out.println(i03== i04);
    D.   System.out.println(i02== i04);

    1.题目中提到了,是Jdk1.5的环境。

    OK,我们新建一个项目,新建一个类,把代码复制进去。将Java Compiler设置为1.5.  关于这个版本的问题稍后再谈。

    2.这里有两个数据类型,int和Integer。

       int为基本类型。

       Integer为对象类型。Integer的类声明是这样的:

    public final class Integer extends Number implements Comparable<Integer> {
    
        //...
    
    }

    1、Integer类是final的,不能被继承

    
    

    2、Integer类实现了Comparable接口,所以可以用compareTo进行比较。

    
    

    3、Integer继承了Number类,所以该类可以调用longValue、floatValue、doubleValue等系列方法返回对应的类型的值。

     

    3.题目中声明了三个Integer变量,i01,i03,i04.这三种声明方式有啥区别呢?

    3.1  Integer i04 = new Integer(59); 做了什么?

    看源码,这个构造函数是这样的:

        /**
         * The value of the {@code Integer}.
         *
         * @serial
         */
        private final int value;
    
        /**
         * Constructs a newly allocated {@code Integer} object that
         * represents the specified {@code int} value.
         *
         * @param   value   the value to be represented by the
         *                  {@code Integer} object.
         */
        public Integer(int value) {
           this.value = value;
        }

    new Integer(59)的这个操作,调用了构造函数,将59这个值,赋给了Integer的局部变量value。

    3.2  Integer i03 = Integer.valueOf(59); //这个 Integer.valueOf 方法又做了什么??

    看Integer.valueOf源码:

        /**
         * Returns an {@code Integer} instance representing the specified
         * {@code int} value.  If a new {@code Integer} instance is not
         * required, this method should generally be used in preference to
         * the constructor {@link #Integer(int)}, as this method is likely
         * to yield significantly better space and time performance by
         * caching frequently requested values.
         *
         * This method will always cache values in the range -128 to 127,
         * inclusive, and may cache other values outside of this range.
         *
         * @param  i an {@code int} value.
         * @return an {@code Integer} instance representing {@code i}.
         * @since  1.5
         */
        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);
        }

    这里,valueOf方法先判断传入参数的值,满足if 条件的话,则返回cache值。

    否则 new 一个Integer 返回。这里的 if中的条件 IntegerCache.high=127, IntegerCache.low=-128;从IntegerCache的类定义可以看出,IntegerCache里边定义了一个数组cache用来存储Integer对象,静态块里边完成了数组的初始化,存入了-128到127之间的Integer对象:

        private static class IntegerCache {//这个类是 Integer 类的 静态内部类。看这个代码不难发现,在Integer加载之后这个内部类的cache数组里边就初始化了-128到127之间的值
            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));
                }
                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() {}
        }

    所以,对于Integer.valueOf(i)方法 , 当i在-128-127之间时返回的是缓存的Integer对象。 否则返回的是一个新的Integer对象。

    这里传递的是59,所以返回的是cache里边的对象。

    3.3 Integer i01 = 59;// 这句话又做了什么?

    我们将源码产生的class文件反编译发现如下:

    源码:   
    public static void main(String[] args) { // TODO Auto-generated method stub Integer i01 = 59;// Integer.valueOf(59); int i02 = 59; Integer i03 = Integer.valueOf(59); Integer i04 = new Integer(59); System.out.println("i01 == i02:" + (i01 == i02)); System.out.println("i01 == i03:" + (i01 == i03)); System.out.println("i03 == i04:" + (i03 == i04)); System.out.println("i02 == i04:" + (i02 == i04)); }
    反编译之后:

    public static void main(String[] args)
    {
    Integer i01 = Integer.valueOf(59);
    int i02 = 59;
    Integer i03 = Integer.valueOf(59);
    Integer i04 = new Integer(59);
    System.out.println("i01 == i02:" + (i01.intValue() == i02));
    System.out.println("i01 == i03:" + (i01 == i03));
    System.out.println("i03 == i04:" + (i03 == i04));
    System.out.println("i02 == i04:" + (i02 == i04.intValue()));
    }

     

    可以发现:Integer i01=59;在反编译过来之后是Integer.valueOf(59);

    在用Integer 类型的i01和int类型的i02进行“==”比较的时候,反编译过来的是:i01.intValue() == i02

    这两个操作分别为 自动装箱自动拆箱。这个特性是在java1.5开始才有的。所以第一点中提到了jdk版本为1.5.

    如果我们在eclipse/myeclipse 中将java compiler设置成1.5以下的就会无法通过编译:

    Type mismatch: cannot convert from int to Integer

    通过上面的分析,这题就不难得出答案了。

    i01 == i02 等价于  i01.intValue()==i02  两个值的比较59==59   -->true;

    i01 == i03 由于 59在-128到127之间,所以,i01和i03的赋值操作返回的是同一个对象。都是从chche中返回的同一个对象,对象地址相同   true;

    i03 == i04 i03是来自缓存值,i04是新new的对象 ,二者不是同一个对象,所以false。

    i02 == i04 和第一个类似,true。

  • 相关阅读:
    测试面试题集锦(一)| 软件测试常见必考问题与流程篇(附答案)
    测试开发赏金内推 | BAT 最新高薪急聘岗位,名企测试负责人等你来面!
    Xbox分辨率突然变成640p
    UWP 自定义密码框控件
    前端笔记(Antd将组件设置国际化中文)
    【数据结构与算法】背包问题总结梳理
    Redis网络模型的源码分析
    [MOOC-Java]1.2.1用变量做计算
    [MOOC-Java]1.1.2第一个程序
    [MOOC-Java]1.1.1开发环境配置
  • 原文地址:https://www.cnblogs.com/demingblog/p/5626824.html
Copyright © 2020-2023  润新知