美文网首页
经典面试题:Integer类型 ==比较问题

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

作者: 云芈山人 | 来源:发表于2021-06-30 20:45 被阅读0次

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

    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类型 ==比较问题

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