什么是拆箱和装箱 Java中为每种基本类型都提供了对应的包装器类型。拆箱就是把包装器类型转换为基本数据类型的过程;装箱就是把基本数据类型转换为包装器类型的过程。
1 2 3 Integer i = 10 ; int b = i;
Java中拆箱和装箱的实现过程是:
以Double类型举例
拆箱:调用doubleValue方法;
装箱:调用Double.valueOf方法
面试相关问题 Integer比较 1 2 3 4 5 6 7 Integer i1 = 100 ;Integer i2 = 100 ;Integer i3 = 200 ;Integer i4 = 200 ;assertThat(i1 == i2).isEqualTo(true ); assertThat(i3 == i4).isEqualTo(false );
比较过程:
调用Integer.valueOf()方法将各个变量装箱;
装箱后比较各个变量指向的内存地址是否相同。
但是为什么以上两个结果不同呢?看一下Integer的valueOf方法的实现便知究竟
1 2 3 4 5 public static Integer valueOf (int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer (i); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 private static class IntegerCache { static final int low = -128 ; static final int high; static final Integer cache[]; static { 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 ); h = Math.min(i, Integer.MAX_VALUE - (-low) -1 ); } catch ( NumberFormatException nfe) { } } high = h; cache = new Integer [(high - low) + 1 ]; int j = low; for (int k = 0 ; k < cache.length; k++) cache[k] = new Integer (j++); assert IntegerCache.high >= 127 ; } private IntegerCache () {} }
通过分析源码,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。
Double类型比较 那么Double类型是否相同呢?
1 2 3 4 5 6 7 Double d1 = 100.0 ;Double d2 = 100.0 ;Double d3 = 200.0 ;Double d4 = 200.0 ;assertThat(d1 == d2).isEqualTo(false ); assertThat(d3 == d4).isEqualTo(false );
原因同样我们去看Double.valueOf的源码实现
1 2 3 public static Double valueOf (String s) throws NumberFormatException { return new Double (parseDouble(s)); }
通过分析源码,double类型在每一次装箱时,都会新建一个对象。
Boolean类型比较 1 2 3 4 5 6 7 Boolean i1 = false ;Boolean i2 = false ;Boolean i3 = true ;Boolean i4 = true ; assertThat(i1 == i2).isEqualTo(true ); assertThat(i3 == i4).isEqualTo(true );
同样看Boolean.valueOf的源码实现
1 2 3 4 5 6 7 8 public static final Boolean TRUE = new Boolean (true );public static final Boolean FALSE = new Boolean (false );public static Boolean valueOf (boolean b) { return (b ? TRUE : FALSE); }
关于equals和== == 如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的内存地址
equals 如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。