这题考什么
这题看着是背诵题,但面试官真正想听的是三件事:
- 你是不是真懂内存和范围:几个字节、有符号还是无符号、默认值,这些答不出就露馅了。
- 你踩没踩过数值的坑:自动装箱的
==、整型溢出、浮点精度、整数除法,问两句追问就能试出你是背的还是写过代码。 - 你理不理得清基本类型和包装类的关系:什么时候拆箱会 NPE、缓存池怎么回事,这块爱往深处问。
先说结论
Java 一共有 8 种基本类型:4 种整数型(byte、short、int、long),2 种浮点型(float、double),外加 char 和 boolean。
记住字节数:byte 1、short 2、int 4、long 8、float 4、double 8、char 2,boolean 不做硬性规定。和 String、数组这些引用类型的根本区别在于:基本类型存的是值本身,放在栈上(对象字段里就跟着对象放堆);引用类型存的是指向对象的引用。另外要注意 char 在 Java 里是无符号的 0~65535,这跟 C 语言不一样。
原理拆解
8 个类型的完整清单
byte b = 100; // 1 字节, -128 ~ 127
short s = 10000; // 2 字节, -32768 ~ 32767
int i = 100000; // 4 字节, 约正负 21 亿, 最常用
long l = 100000L; // 8 字节, 字面量建议加 L
float f = 1.5f; // 4 字节, 单精度, 字面量必须加 f
double d = 1.5; // 8 字节, 双精度, 默认浮点类型
char c = 'A'; // 2 字节, 无符号, 0 ~ 65535
boolean flag = true; // 只有 true / false
字段(成员变量)不赋值有默认值:数值型全是 0,char 是 '\u0000',boolean 是 false。但局部变量必须显式初始化,否则编译不过,这是常考点。
数值是怎么悄悄变化的
小类型往大类型走是自动提升,反过来必须强转,强转可能丢数据:
注意 char 也会往 int 提升,所以 'a' + 1 的结果是 98 而不是字符,System.out.println((char)('a' + 1)) 才是 b。反过来写 byte b = 1000; 直接编译错误,byte b = (byte) 1000; 能编译但值会溢出变味。
整型溢出很隐蔽:
byte b = 127;
b++; // 变成 -128, 编译器不报错
int max = Integer.MAX_VALUE;
max + 1; // 变成 Integer.MIN_VALUE
浮点数为什么不精确
float 和 double 遵循 IEEE 754,用二进制表示小数本身就有误差,所以 0.1 + 0.2 != 0.3 是常态。float 大约 7 位有效数字,double 大约 15~16 位。金额计算别用它们,用 BigDecimal。另外 1.0 / 0 是 Infinity,0.0 / 0 是 NaN,而 1 / 0 会直接抛 ArithmeticException,整数和浮点行为不一样。
还有个高频坑:float f = 3.14; 编译不过,因为 3.14 默认是 double,得写 3.14f 或强转。
基本类型和包装类是怎么打通的
每个基本类型都有对应包装类:Byte、Short、Integer、Long、Float、Double、Character、Boolean。Java 5 之后有自动装箱拆箱,本质是编译器帮你调 valueOf() 和 intValue():
Integer a = 100; // 等价于 Integer.valueOf(100)
int b = a; // 等价于 a.intValue()
坑在这儿:Integer.valueOf() 对 -128~127 做了缓存,所以
Integer x = 127, y = 127;
x == y; // true, 同一个缓存对象
Integer m = 128, n = 128;
m == n; // false, 两个不同对象
比较包装类一律用 equals()。另外 Integer i = null; int j = i; 会 NPE,因为拆箱要调方法。
面试怎么问
为什么要有 8 种而不是全用 long? 为了贴合硬件和省内存。CPU 寄存器、指令集本来就是按 1/2/4/8 字节设计的,数组里用 byte 比用 long 能省 8 倍空间,JVM 也能按类型选更高效的字节码。
boolean 到底占几个字节? JVM 规范没规定单个 boolean 的大小,只规定 boolean 数组用 byte 数组实现,每元素 1 字节。HotSpot 里单个 boolean 字段基本按 int 处理。面试说「规范未定,实践中 1~4 字节,按 int 对齐」比较稳,别说死。
char 能存汉字吗?
能,char 是 16 位 Unicode,'中' 就是一个 char。但生僻字(超出 BMP 的)需要用两个 char,也就是一个代理对,所以判断字符串长度用 codePointCount() 更严谨。
int 和 Integer 的区别? int 是基本类型,值直接存;Integer 是对象,能为 null、能放集合里、有缓存池。集合泛型只能用包装类,因为泛型参数不能是基本类型。
switch 支持哪些类型? byte、short、int、char 及其包装类,加上 String 和 enum。long 和 boolean 不支持,因为 JVM 的 switch 指令就是按 int 语义设计的。
变形题
Integer a = 1; Integer b = 2; a + b的结果类型是什么? int。加法会先拆箱成 int 再算,如果 a 是 null 就 NPE。byte b = 127; b = b + 1;能编译吗? 不能。b + 1会提升成 int,赋回 byte 必须强转,而且b++能编译,因为编译器自动加了强转。char c = 'a'; c = c + 1;呢? 同样编译不过,得(char)(c + 1),因为 char 参与运算是按 int 算的。1.0f == 1.0d是 true 吗? 是,比较时 float 会提升成 double。但new Float(1.0).equals(1.0)是 false,因为 equals 要求类型严格一致。
怎么记
字节数就是记忆锚点:整数 1、2、4、8 一路翻倍,浮点 4、8,char 2,boolean 不写死。分类就记「四整、二浮、一字符、一布尔」。溢出方向也别乱:小转大自动,大转小强转,强转有风险;整型除法会截断,浮点除法出 Infinity 或 NaN,这两条面试最爱拿来下套。