简介
Java基本数据类型分为四大类:
整数型: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 |
常见面试题
要注意的是基本数据的包装类很多都实现了享元模式。享元模式就是运用共享技术有效地支持大量细粒度对象的复用。用一个常见的面试题来解释。
1,判断如下代码的输出,并说明原因
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是Integer的静态内部类,默认创建了[-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个字节。
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
//+操作会导致左右两边都转换成基本数据类型,解释在下面
System.out.println(i1 == i2 + i3);
//false
//Intege.valueOf()使用常量池中的对象
//new Integer每次都创建新对象
//比较的是内存地址
System.out.println(i1 == i4);
//false
//两个不同的对象
//比较的是内存地址
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进行数值比较。