一、八种基础数据类型(Java核心)
Java的基础数据类型分为「数值型」和「非数值型」,共8种,记住一句话:4种整数、2种浮点数、1种字符、1种布尔,具体如下(面试直接背,不踩坑):
-
整数型(4种):byte(字节)、short(短整型)、int(整型)、long(长整型)
-
浮点数型(2种):float(单精度)、double(双精度)
-
字符型(1种):char
-
布尔型(1种):boolean
补充:基础数据类型都是"值类型",直接存储数据本身,不是对象,这也是和包装类(比如Integer)的核心区别。
二、int和long是多少位、多少字节?
记住固定数值,面试不会考复杂计算,重点记"字节=位/8"(1字节=8位):
-
int:32位,4字节(范围:-2³¹ ~ 2³¹-1,大概是-21亿到21亿)
-
long:64位,8字节(范围:-2⁶³ ~ 2⁶³-1,范围比int大得多,适合存储超大整数)
注意:Java里不管是32位还是64位系统,int和long的位数、字节数都是固定的,不会随系统变化(和C语言不一样,这点要记牢)。
三、long和int可以互转吗?
可以互转,但分「自动转换」和「强制转换」,不能直接随便转,否则会出问题:
-
long转int:必须强制转换(因为long范围比int大,直接转可能丢失数据),格式:int num = (int) longNum;
-
int转long:可以自动转换(隐式转换),因为int范围小,转成long不会丢失数据,格式:long num = intNum;
举个例子:long a = 100; int b = (int)a; // 正常;但如果long a = 2200000000;(超过int最大值),转int就会出现数据溢出,结果错误。
四、数据类型的转换方式有哪些?
核心分2种:自动转换(隐式)和强制转换(显式),再补充包装类的转换,覆盖面试考点:
1. 自动转换(隐式转换)
无需手动操作,Java自动完成,前提是:小范围类型 → 大范围类型,不会丢失数据。
常见顺序:byte → short → int → long → float → double(char比较特殊,可自动转int、long等)
示例:short s = 10; int i = s; // 自动转换,无报错
2. 强制转换(显式转换)
需要手动加强制转换符(括号+目标类型),前提是:大范围类型 → 小范围类型,可能丢失数据或精度,谨慎使用。
格式:目标类型 变量名 = (目标类型) 原变量;
示例:double d = 3.14; int i = (int)d; // 结果是3,丢失小数部分
3. 包装类转换(补充)
基础类型和包装类之间的转换(装箱拆箱),以及包装类之间的转换(比如Integer转Long),后续会详细讲。
五、类型互转会出现什么问题?
最常见2个问题:数据溢出 和精度丢失,面试必问,结合例子记更易理解:
1. 数据溢出(整数类型互转常见)
当大范围类型转小范围类型,且原数据超过小范围类型的最大值/最小值时,就会溢出,结果会变成一个毫无意义的负数或正数(循环溢出)。
示例:int max = Integer.MAX_VALUE; // 2147483647;int result = max + 1; // 结果变成-2147483648,溢出了
2. 精度丢失(浮点数和整数互转常见)
① 浮点数转整数:直接舍弃小数部分,不是四舍五入;② 小数类型之间互转(比如double转float),也可能丢失精度(因为float是32位,double是64位)。
示例:double d = 3.999; int i = (int)d; // 结果3,不是4;float f = (float)3.1415926535; // 精度丢失,变成近似值
补充:boolean类型不能和任何其他类型互转,哪怕强制转换也会报错(面试易错点)。
六、为什么用BigDecimal不用double?
核心原因:double是浮点数,存在精度误差,无法精确表示小数,适合科学计算;而BigDecimal是高精度类,能精确表示小数,适合金融、电商等需要精确计算的场景(比如金额计算)。
举个坑点例子:double a = 0.1; double b = 0.2; System.out.println(a + b); // 结果不是0.3,而是0.30000000000000004,这就是精度误差。
补充:BigDecimal使用时要注意,不能用构造方法new BigDecimal(double),要用new BigDecimal(String),否则还是会有精度问题(比如new BigDecimal("0.1")才是精确的)。
七、装箱和拆箱是什么?
装箱和拆箱,是「基础数据类型」和「对应包装类」之间的转换,Java 5之后自动支持(自动装箱/拆箱),不用手动操作:
-
装箱:基础数据类型 → 包装类(比如int → Integer)
-
拆箱:包装类 → 基础数据类型(比如Integer → int)
示例(自动装箱拆箱):
Integer i = 10; // 自动装箱(int 10 → Integer对象)
int j = i; // 自动拆箱(Integer对象 → int 10)
底层原理:装箱其实是调用包装类的valueOf()方法(比如Integer.valueOf(10)),拆箱是调用xxxValue()方法(比如i.intValue())。
八、Java为什么有Integer?
核心原因:Java是面向对象语言,很多场景需要使用对象,而int是基础数据类型(不是对象),无法满足这些场景,所以提供了Integer包装类,补充int的不足。
常见场景:
-
集合框架:比如ArrayList、HashMap等集合,只能存储对象,不能存储基础数据类型,所以需要用Integer存储int类型数据。
-
需要null值:int是基础数据类型,默认值是0,不能表示null;而Integer是对象,默认值是null,适合需要表示"无值"的场景(比如数据库中字段允许null)。
-
提供工具方法:Integer类提供了很多实用方法,比如将字符串转成int(Integer.parseInt("123"))、判断是否是数字等,int本身没有这些方法。
九、Integer相比于int有什么优点?
结合上一个问题,优点很明确,面试分3点说,清晰不啰嗦:
-
可以表示null值:解决了int无法表示"无数据"的问题,适配数据库、集合等场景。
-
提供丰富的工具方法:比如字符串转int、进制转换(十进制转二进制)、获取int的最大值/最小值等,无需自己写工具类。
-
可以作为对象使用:适配Java面向对象的特性,能参与泛型、反射等操作(比如泛型只能用对象类型,不能用int)。
十、那为什么还要保留int类型?
核心原因:int比Integer更高效、更节省内存,不是所有场景都需要Integer的功能,简单场景用int更合适。
-
内存方面:int是基础数据类型,直接存储值,占用4字节;Integer是对象,除了存储值,还会有对象头、引用等额外开销,内存占用比int大。
-
效率方面:int的运算速度更快,不需要经过对象的创建、拆箱等过程;而Integer的运算会涉及自动拆箱,效率稍低。
-
场景适配:如果只是简单的数值运算(比如计算年龄、数量),不需要null值和工具方法,用int更简洁、高效。
总结:int适合简单数值场景,Integer适合需要对象、null值、工具方法的场景,两者互补,不是替代关系。
十一、说一下Integer的缓存
这是面试高频难点,小林风格拆解:Integer缓存是Java的一个优化机制,目的是减少频繁创建相同值的Integer对象,节省内存、提高效率。
1. 缓存范围
默认缓存范围:-128 ~ 127(固定范围,不能修改),这个范围内的Integer对象,会被缓存起来,重复使用,不会重复创建新对象。
2. 缓存原理
当我们用Integer.valueOf(int i)方法创建Integer对象时(自动装箱底层也是调用这个方法),如果i在-128~127之间,会直接从缓存中取出已创建的对象;如果i不在这个范围,才会new一个新的Integer对象。