面试官:说⼀下⼋种基本数据类型
整型:byte,short,int,long
浮点型:float,double
逻辑型:boolean
字符型:char
原始类型 | 所占的字节数 | 包装类 |
---|---|---|
byte | 1字节 | Byte |
short | 2字节 | Short |
int | 4字节 | Integer |
long | 8字节 | Long |
float | 4字节 | Float |
double | 8字节 | Double |
boolean | 1字节 | Boolean |
char | 2字节 | Character |
要注意的是基本数据的包装类很多都实现了享元模式。享元模式就是运⽤共享技术有效地⽀持⼤量细粒度对象的复 ⽤。⽤⼀个常⻅的⾯试题来解释
Integer a1 = 40;
Integer a2 = 40;
System.out.println(a1 == a2);
Integer a3 = 200;
Integer a4 = 200;
System.out.println(a3 == a4);
由⾃动装箱和拆箱可以知道这2种写法是等价的
Integer a1 = 40;
Integer a1 = Integer.valueOf(40);
看⼀下Integer的valueOf⽅法:
public static Integer valueOf(int i) {
// i的取值范围为[-128,127]
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
IntegerCache是Ingeter的静态内部类,默认创建了[-128,127]的对象,并放到IntegerCache内部的⼀个cache数
组中,在[-128,127]这个范围内的整数对象,不⽤创建。直接从IntegerCache中的cache数组中根据下标拿就可
以,超出这个范围的每次去创建新的对象。其他⼏种包装类型的常量池和Integer思路都差不多,源码都很相似。
所以答案如下:
Integer a1 = 40;
Integer a2 = 40;
// true
System.out.println(a1 == a2);
Integer a3 = 200;
Integer a4 = 200;
// false
System.out.println(a3 == a4);
包装类缓存的范围如下:
包装类 | 缓存范围 |
---|---|
Byte | -128~127 |
Short | -128~127 |
Integer | -128~127 |
Long | -128~127 |
Character | 0~127 |
2.Java⼀个char类型可以存储中⽂吗?
可以,因为Java中使⽤了Unicode字符,不论中⽂还是因为固定占⽤2个字节。
char a = '中';
// 中
System.out.println(a);
3.什么是⾃动装箱,⾃动拆箱?
⾃动装箱就是Java⾃动将原始类型值转换成对应的对象,⽐如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这⾥的装箱和拆箱是⾃动进⾏的⾮⼈为转换,所以就称作为⾃动装箱和拆箱⾃动装箱时编译器调⽤valueOf将原始类型值转换成对象,同时⾃动拆箱时,编译器通过调⽤类似intValue(),doubleValue()这类的⽅法将对象转换成原始类型值
// jdk1.5 之前的写法
Integer tempNum1 = Integer.valueOf(5);
int num1 = tempNum1.intValue();
// jdk1.5之后的写法
Integer tempNum2 = 5;
int num2 = tempNum2;
4.为什么要需要基本数据类型的包装类?
(1)Java是⾯向对象的语⾔,很多地⽅需要使⽤的是对象⽽不是基本数据类型。例如,List,Map等容器类中基本
数据类型是放不进去的。
(2)包装类在原先的基本数据类型上,新增加了很多⽅法,如Integer.valueOf(String s)等
5.既然包装类型能完成所有功能,为啥还需要基本类型?
基本数据类型基于数值,对象类型基于引⽤。基本数据类型存储在栈的局部变量表中。
⽽对象类型的变量则存储堆中引⽤,实例放在堆中,因此对象类型的变量需要占⽤更多的内存空间。
显然,相对于基本类型的变量来说,对象类型的变量需要占⽤更多的内存空间。
6.写出如下代码的输出:
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);
System.out.println(i1 == i2);
System.out.println(i1 == i2 + i3);
System.out.println(i1 == i4);
System.out.println(i4 == i5);
System.out.println(i4 == i5 + i6);
System.out.println(40 == i5 + i6);
输⼊如下:
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);
// true
// Integer.valueOf()⽤了常量池,看上⾯的源码
System.out.println(i1 == i2);
// true
// + 操作会导致左右2边都转成基本数据类型
// 具体原因看下⾯
System.out.println(i1 == i2 + i3);
// false
// Integer.valueOf()使⽤常量池中的对象
// new Integer每次会创建新对象,
System.out.println(i1 == i4);
// false
// 2个不同的对象
System.out.println(i4 == i5);
// true、
// 解释在最下⾯
System.out.println(i4 == i5 + i6);
// true
// 解释在最下⾯
System.out.println(40 == i5 + i6);
语句i4 == i5 + i6,因为+这个操作符不适⽤于Integer对象,⾸先i5和i6进⾏⾃动拆箱操作,进⾏数值相加,即i4 ==40。然后Integer对象⽆法与数值进⾏直接⽐较,所以i4⾃动拆箱转为int值40,最终这条语句转为40 == 40进⾏数值⽐较