面试_java_包装类

117 阅读4分钟

Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样 和八个基本数据类型对应的类统称为包装类 (Wrapper Class)。



基本数据类型和包装类的区别

  1. 初始值不同。包装类默认值为null,基本数据类型则不同的类型不一样
  2. 存储位置不同。基本数据类型存储在栈(stack)中,包装类则分成引用和实例,引用在栈(stack)中,具体实例在堆(heap)中。
  3. 声明和使用方式不同。包装类使用new初始化,有些集合类的定义不能使用基本数据类型,例如 ArrayList<Integer>


装箱和拆箱

基本类型和对应的包装类可以相互装换:

  • 由基本类型向对应的包装类转换称为装箱,例如把 int 包装成 Integer 类的对象:
Integer i = Integer.valueOf(1); //手动装箱
Integer i = 1; //自动装箱
  • 包装类向对应的基本类型转换称为拆箱,例如把 Integer 类的对象简化为 int。
int i1 = i.intValue(); //手动拆箱    (如果i为null, 则这行代码书写时不会报红,但编译不通过)
int i2 = i; //自动拆箱

jdk5.0开始增加自动装箱/拆箱



包装类的==与equals

  • ==,比较的是地址值是否相同。
    • 如果是Integer、Short、Byte、Character、Long这几个类型,直接返回缓存中的同一个引用,地址值相同。
      • Integer类型有缓存[-128, 127]的对象。缓存上限可以通过配置jvm更改
      • Byte,Short,Long类型有缓存(-128, 127)
      • Character缓存[0, 127]
      • Boolean缓存TRUE、FALSE
    • 基本数据类型和包装类比较,会先把包装类拆箱,再去比较两边基本数据类型的数值。
    • 如果其中有一个操作数是表达式(即包含算术运算),则两边分别进行自动拆箱,去比较两边的数值。
  • equals方法,比较的是包装的基本数据类型的值。
    • 基本数据类型和包装类比较,会先把基本数据类型装箱,因为基本数据类型没有equals方法。



面试问题

1. 下面这段代码的输出结果是什么?

public class Main {
    public static void main(String[] args) {
        Integer i1 = 100;
        Integer i2 = 100;
        Integer i3 = 200;
        Integer i4 = 200;
        
        System.out.println(i1==i2);   // true
        System.out.println(i3==i4);   // false。 
    }
}

以上代码在经过编译时,会在声明的变量前家伙是那个valueOf方法,代码变成了:

public class Main {
    public static void main(String[] args) {
        Integer i1 = Integer.valueOf(100);
        Integer i2 = Integer.valueOf(100);
        Integer i3 = Integer.valueOf(200);
        Integer i4 = Integer.valueOf(200);
        
        System.out.println(i1==i2);
        System.out.println(i3==i4);
    }
}

看一下Integer的valueOf方法的源码:

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

从这2段代码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在 [-128,127] 之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。

上面的代码中 i1 和 i2 的数值为100,因此会直接从cache中取已经存在的对象,所以 i1 和 i2 指向的是同一个对象,而 i3 和 i4 则是分别指向不同的对象。

注意:

如果将Integer换为Double 或者 Float,两个输出则都是False,因为这两个不取缓存


2. 下面这段代码的输出结果是什么?

public class Main {
    public static void main(String[] args) {
        Integer i1 = new Integer(100);
        Integer i2 = new Integer(100);
        Integer i3 = new Integer(100);
        Integer i4 = new Integer(100);
        
        System.out.println(i1==i2);    // false
        System.out.println(i3==i4);	   // false
    }
}

原因:只有valueOf方法构造对象时会用到缓存,new方法等不会使用缓存!

小结:不会使用缓存的情况:

  • Double、Float包装类
  • new创建出的包装类

3. 下面这段代码的输出结果是什么?

关于equals

double i0 = 0.1;
Double i1 = new Double(0.1);
Double i2 = new Double(0.1);
System.out.println(i1.equals(i2)); //true 2个包装类比较,比较的是包装的基本数据类型的值
System.out.println(i1.equals(i0)); //true 基本数据类型和包装类型比较时,会先把基本数据类型装箱后再比

关于“==”

double i0 = 0.1;
Double i1 = new Double(0.1);
Double i2 = new Double(0.1);
System.out.println(i1 == i2);    //false new出来的都是新的对象
System.out.println(i1 == i0);    //true 基本数据类型和包装类比较,会先把包装类拆箱再比,“==”比的是地址。因为i1是拿i0创建的,所以地址一样

4. 下面这段代码的输出结果是什么?

public class Main {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 321;
        Integer f = 321;
        Long g = 3L;
        Long h = 2L;
         
        System.out.println(c==d);
        System.out.println(e==f);
        System.out.println(c==(a+b));
        System.out.println(c.equals(a+b));
        System.out.println(g==(a+b));
        System.out.println(g.equals(a+b));
        System.out.println(g.equals(a+h));
    }
}
true
false
true
true
true
false
true

第一个和第二个输出结果没有什么疑问。第三句由于 a+b 包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),因此它们比较的是数值是否相等。而对于c.equals(a+b)会先触发自动拆箱过程,再触发自动装箱过程,也就是说a+b,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf方法,再进行equals比较。同理对于后面的也是这样,不过要注意倒数第二个和最后一个输出的结果(如果数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法)。




alexyyek.github.io/2014/12/29/… zhuanlan.zhihu.com/p/65538963