【Java】 面试核心合集:BigDecimal、缓存池、多态、反射全解析

大家好,我是程序员二叉。


简介

本文汇总 Java 后端面试高频核心考点,从金融业务BigDecimal选型原理与避坑、包装类缓存机制、面向对象多态、重载重写,到静态代码块执行顺序、反射全体系知识点,最后结合 Spring、MyBatis 源码落地场景逐一拆解。内容贴合日常开发与面试,干货密集,适合 Java 初学者夯实基础、面试突击复习 ,收藏即可快速查阅。欢迎点赞收藏关注。


一、为什么金融数据要用 BigDecimal?

1. 核心原因:float、double 会精度丢失

浮点数(float/double)是二进制存储 ,无法精确表示 0.1 这类十进制小数,会出现误差:

java 复制代码
double a = 0.1 + 0.2; // 结果是 0.30000000000000004,不是 0.3

金融场景(金额、利率、税费)绝对不能容忍精度误差,否则会造成资金损失。

2. BigDecimal 优势

  • 十进制精确表示,无精度丢失
  • 支持高精度运算(加减乘除、舍入模式)
  • 适合货币、订单、税务等金融计算

二、BigDecimal 常见坑点(面试必考)

1. 禁止用 new BigDecimal (double)

java 复制代码
BigDecimal bad = new BigDecimal(0.1); // 精度丢失!
BigDecimal good = new BigDecimal("0.1"); // 正确

2. 除法必须指定舍入模式,否则抛异常

java 复制代码
a.divide(b, 2, RoundingMode.HALF_UP); // 保留2位,四舍五入

3. 比较用 compareTo (),不要用 equals ()

equals() 会比较精度compareTo() 只比较数值大小。

4. BigDecimal 是不可变类,运算后必须接收返回值:

java 复制代码
BigDecimal num = new BigDecimal("10");
num.add(new BigDecimal("5")); // 错误,num 不变
num = num.add(new BigDecimal("5")); // 正确

5.不要用 toString () 做业务判断,可能出现科学计数法


三、自动装箱 & 拆箱

定义

  • 装箱 :基本类型 → 包装类型(int → Integer
  • 拆箱 :包装类型 → 基本类型(Integer → int
    示例
java 复制代码
Integer a = 10;   // 自动装箱:Integer.valueOf(10)
int b = a;        // 自动拆箱:a.intValue()

四、Integer (-128 ~ 127) 缓存池

1. 是什么?

JVM 会提前创建好 -128 到 127 的 Integer 对象并缓存,用到时直接复用,不新建对象。

2. 目的

节省内存、提升性能(高频小数字最常用)。


五、Integer a=128; Integer b=128; a==b 为什么是 false?

  • == 比较对象地址
  • -128~127 走缓存,同一个对象 → true
  • 128 超出缓存范围 ,每次 valueOf() 都会new 新对象
    → 两个不同对象,地址不同 → false
    ✅ 正确比较包装类值:用 equals()

六、多态体现在哪些方面?

多态 = 同一个行为,不同对象表现不同形态

体现在 3 点:

  1. 方法重载(编译时多态)
  2. 方法重写(运行时多态)
  3. 父类引用指向子类对象

七、编译时多态 vs 运行时多态

类型 实现方式 绑定时机
编译时多态 方法重载 编译期确定
运行时多态 方法重写 运行期确定
  • 编译时:编译器知道调用哪个方法
  • 运行时:JVM 根据实际对象类型决定调用哪个方法

八、重载 vs 重写(面试必背)

重载(Overload)

  • 同一个类中
  • 方法名相同
  • 参数列表不同(个数、类型、顺序)
  • 与返回值无关

重写(Override)

  • 子类继承父类
  • 方法名、参数、返回值完全相同
  • 子类权限不能更小
  • 不能抛出更宽泛的异常

九、Java 为什么不支持多继承?

避免菱形问题(二义性)

如果两个父类有同名方法,子类不知道继承哪一个,会产生冲突。

Java 用接口多实现替代多继承。


十、静态代码块、实例代码块、构造方法执行顺序

执行顺序

  1. 父类静态代码块
  2. 子类静态代码块
  3. 父类实例代码块
  4. 父类构造方法
  5. 子类实例代码块
  6. 子类构造方法
    口诀:先静态,后实例;先父类,后子类

十一、什么是反射?

反射 = 程序运行时,获取类的完整信息并操作对象

可以拿到:类名、父类、接口、构造器、字段、方法、注解等。

核心类:

  • Class
  • Constructor
  • Field
  • Method

十二、反射为什么性能低?

  1. 解析类元数据(耗时)
  2. 方法调用是动态的,无法编译优化
  3. 权限检查(访问私有、安全校验)
  4. 无法 JIT 编译优化

十三、反射的优缺点

优点

  • 运行时动态获取类信息
  • 解耦,提高扩展性
  • 框架底层核心技术
    缺点
  • 性能低
  • 破坏封装(可访问私有)
  • 代码可读性差
  • 编译期无法检查错误

十四、获取 Class 对象的 3 种方式

  1. 对象.getClass ()
java 复制代码
User user = new User();
Class<?> clazz = user.getClass();
  1. 类名.class
java 复制代码
Class<?> clazz = User.class;
  1. Class.forName ("全类名")
java 复制代码
Class<?> clazz = Class.forName("com.example.User");

区别

  • getClass():运行时确定
  • .class:编译期确定,不触发类加载
  • forName():动态加载类,会执行静态代码块(框架常用)

十五、反射创建对象

  1. 无参构造
java 复制代码
Class<?> clazz = User.class;
User user = (User) clazz.newInstance(); // JDK9 废弃
User user = (User) clazz.getDeclaredConstructor().newInstance();
  1. 有参构造
java 复制代码
Constructor constructor = clazz.getConstructor(String.class, int.class);
User user = (User) constructor.newInstance("张三", 20);

十六、反射调用私有字段 & 私有方法

1. 私有字段

java 复制代码
Field field = clazz.getDeclaredField("name");
field.setAccessible(true); // 关闭权限检查
field.set(user, "李四");

2. 私有方法

java 复制代码
Method method = clazz.getDeclaredMethod("privateMethod");
method.setAccessible(true);
method.invoke(user);

十七、Spring / MyBatis 哪里用到了反射?(框架底层)

Spring 用到反射的地方

  1. IOC 容器创建 Bean
  2. 依赖注入 @Autowired
  3. AOP 动态代理
  4. 注解解析(@Controller、@Service)
  5. 配置文件实例化对象

MyBatis 用到反射的地方

  1. SQL 参数赋值
  2. 结果集映射 ResultSet → Java 对象
  3. Mapper 接口动态代理
  4. 注解 / XML 解析

总结

  1. 金融必须用 BigDecimal 避免精度丢失
  2. 包装类缓存池、多态、重载重写是基础必考题
  3. 反射是框架灵魂,Spring/MyBatis 全靠它实现动态扩展
  4. 执行顺序、类加载、权限访问是面试常挖坑点
相关推荐
Full Stack Developme1 小时前
SpringMVC multipart 文件上传
java·开发语言
西凉的悲伤1 小时前
Spring Security + JWT 登录认证完整实践指南
java·后端·spring·spring security·jwt
晚笙coding1 小时前
从零讲透 LangChain 输出格式化:让模型真的“能用”
java·开发语言·langchain
奋斗的小方1 小时前
Java进阶篇1-1:异常
java·开发语言·python
码语智行1 小时前
行政区划 ZIP 导入(importZip)
java
何中应1 小时前
Nexus如何设置端口号
java·服务器·maven·nexus
思麟呀1 小时前
C++11并发编程:条件变量
java·linux·jvm·c++·windows
Full Stack Developme1 小时前
Hutool CollUtil 教程
java·开发语言·windows·python
超梦dasgg1 小时前
连接 & 连接池完整详解(以数据库连接最常用,Redis/MQ 同理)
数据库·redis·缓存