加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2021-05-21 07:23:32 所属栏目:大数据 来源: https://www.jb51.cc
导读:面试题: // 在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.

  

面试题:

//在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 int value;

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

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

?

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

看Integer.valueOf源码:

    
     * Returns an { Integer} instance representing the specified
     * { int} value.  If a new { 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.
     *
     *   i an { int} value.
     * @return an { Integer} instance representing { i}.
     * @since  1.5
     static Integer valueOf( 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对象:

    static class IntegerCache {//这个类是 Integer 类的 静态内部类。看这个代码不难发现,在Integer加载之后这个内部类的cache数组里边就初始化了-128到127之间的值
        int low = -128 high;
        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文件反编译发现如下:

源码:   
void main(String[] args) { TODO Auto-generated method stub Integer i01 = 59; Integer.valueOf(59); ; Integer i03 = Integer.valueOf(59); Integer i04 = ); 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。

?

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读