面试官:说一下八种基本数据类型及其包装类吧_自动装箱

介绍

整型:byte,short,int,long
浮点型:float,double
逻辑型:boolean
字符型:char

原始类型

原始类型所占的字节数

包装类

byte

1个字节

Byte

shot

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是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.既然包装类型能完成所有功能,为啥还需要基本类型?
基本数据类型基于数值,对象类型基于引用。基本数据类型存储在栈的局部变量表中。
而对象类型的变量则存储堆中引用,实例放在堆中,因此对象类型的变量需要占用更多的内存空间。

显然,相对于基本类型的变量来说,对象类型的变量需要占用更多的内存空间。

5.写出如下代码的输出

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进行数值比较

欢迎关注

面试官:说一下八种基本数据类型及其包装类吧_基本数据类型_02