经典面试题:Integer类型 ==比较问题

在聊到面试题之前,需要先搞清楚几个概念。

1、自动装箱与自动拆箱

自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间的一个转化。如int转化为Integer,long转化为Long等。而自动拆箱则相反,是对象包装类型转化成基本数据类型。

   Integer num = 2;

num 是Integer类型,而2是int类型,Integer与int并无继承关系,理论上应报错,但因为自动装箱机制存在,Java自动将int转化为Integer类型,即

Integer num = Integer.valueOf(2);

valueOf()方法返回一个Integer类型值,并将其赋值给变量num。这就是int的自动装箱。

2、8种基本数据类型

8种基本数据类型.png

3、Integer与int 区别

  1. Integer是包装类,int是基本数据类型;
  2. Integer变量必须实例化后才能使用,int不需要;
  3. Integer实际上是个对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象,而int是直接存储数据值;
  4. Integer的默认值为null,int的默认值为0。

4、字节字符区别

字节是存储容量的基本单位,字符是数字,字母,汉字以及其他语言的各种符号。 1 字节=8 个二进制单位:一个一个字符由一个字节或多个字节的二进制单位组成。

5、java 基本类型与引用类型的区别

  • 基本类型保存原始值。
  • 引用类型保存的是引用值(引用值就是指对象在堆中所 处的位置/地址)。

6、常见面试题

  1. 例1
  • short s1 = 1; s1 = s1 + 1;
    首先s1+1运算时会自动提升表达式的类型为int,再将int类型赋值给short类型的s1,会报类型转化错误。
  • short s1 = 1; s1+=1;
    +=是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。
  1. 例2
Integer a = new Integer(50);
Integer b = new Integer(50);
System.out.print( a == b );

输出为false。
由于Integer变量是对Integer对象的引用,所以两个通过new生成的Integer对象永远是不相等的。

  1. 例3
Integer c = new Integer(100);
int d = 100;
System.out.print( c == d );

输出为true。
Integer变量与int比较时,只要值相等,则结果为true。因为包装类Integer与int比较时,会自动拆箱为int,然后进行比较,故而最后变成了两个int变量在比较。

  1. 例4
Integer e = new Integer(100);
Integer  f = 100;
System.out.print( e == f );

输出为false。
非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向的是堆中新建的对象,两者的内存地址不同。

  1. 例5
Integer  g = 100;
Integer  h= 100;
System.out.print( g == h );

Integer  j  = 128;
Integer  k = 128;
System.out.print( j == k );

第一个输出的是true,第二个是false。
两个非new出来的Integer对象,如果范围在-127~128之间,则为true,否则为false。
Integer g =100。通过自动装箱机制转化为Integer g = Integer.valueOf(100)。

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);
}

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.class在装载(Java虚拟机启动)时,其内部类型IntegerCache的static块即开始执行,实例化并暂存数值在-128到127之间的Integer类型对象。当自动装箱int型值在-128到127之间时,即直接返回IntegerCache中暂存的Integer类型对象。

为什么Java这么设计?
出于效率考虑,因为自动装箱经常遇到,尤其是小数值的自动装箱;而如果每次自动装箱都触发new,在堆中分配内存,就显得太慢了;所以不如预先将那些常用的值提前生成好,自动装箱时直接拿出来返回。哪些值是常用的?就是-128到127了。

比较数值是否相等,而非判断是否为同一对象;而自动装箱又不能保证同一数值的Integer一定是同一对象或一定不是同一对象,那么就不要用==,直接用equals()好了。实际上,Integer重写了equals()方法,直接比较对象的数值是否相等。

你可能感兴趣的:(经典面试题:Integer类型 ==比较问题)