java面试题1
目录
计算机网络
传输层协议及适用场景
Java 编程
多线程
线程池提交方式
锁的实现原理
TCP 协议拥塞控制
String 类常用函数
String、StringBuffer、StringBuilder 的区别
String 字符串的不可变
HTTP 协议字段
Java 异常类
Java 反射获取类信息的方式
Java 代理
equals () 方法
Java 参数传递方式
Java 类初始化顺序(含继承)
本地方法栈作用
双亲委派机制
重写(Override)和重载(Overload)的区别
子类构造方法调用父类构造方法注意事项
子类实例初始化是否触发父类实例初始化
instanceof 关键字作用
类型转换
重入锁
指令重排序
Arrays.sort () 内部原理
堆排序复杂度
字符串哈夫曼编码存储比特数
CPU 高速缓存优缺点
线程安全的类
LRU 算法
Spring 框架
Spring Bean 容器与 Spring IOC 容器的区别
Spring IOC 理解
Spring DI 理解
Spring 注解配置对象作用域和延迟加载
Spring 工厂底层构建 Bean 对象机制
Spring MVC 处理流程及优势
Spring 事务处理方式及优缺点
MyBatis 中 #与 $ 的区别
MyBatis 动态 SQL 解决的问题
Shiro 框架认证和授权流程
BeanFactory 和 ApplicationContext 区别
Spring Bean 的生命周期
Spring Bean 的作用域区别
使用 Spring 框架的好处
Spring 中用到的设计模式
Spring 如何保证 Controller 并发安全
在 Spring 中注入 Java 集合
Spring 支持的事务管理类型
Spring 事务管理的优点
Spring MVC 主要组件
SpringMVC 与 AJAX 交互
MyBatis 缓存机制
SpringMVC 与 Struts2 区别
MyBatis 基本工作流程
MyBatis 接口绑定的好处
MyBatis 编程步骤
JDBC 不足与 MyBatis 解决方案
MyBatis 优缺点
计算机网络
传输层协议及适用场景
- TCP(传输控制协议)
- 特点:面向连接、可靠传输、流量控制、拥塞控制。
- 适用场景:文件传输(FTP)、网页浏览(HTTP)、邮件(SMTP)等需要可靠性的场景。
- UDP(用户数据报协议)
- 特点:无连接、不可靠、低延迟、高效率。
- 适用场景:视频流(RTP)、DNS 查询、在线游戏等实时性要求高的场景。
Java 编程
多线程
- 使用场景
- 高并发请求处理(如 Web 服务器)。
- 异步任务(如日志写入、消息队列消费)。
- 计算密集型任务(如并行计算)。
- 线程数设置
- CPU 密集型:线程数 ≈ CPU 核心数(避免过多线程导致频繁上下文切换)。
- IO 密集型:线程数 ≈ CPU 核心数 × (1 + 平均 IO 等待时间 / CPU 计算时间)。
- 判断标准
- CPU 利用率、响应时间、吞吐量、系统资源占用(内存、线程切换开销)。
线程池提交方式
execute(Runnable task)
:提交无返回值的任务。submit(Callable<T> task)
:提交有返回值的任务,返回Future<T>
。invokeAll()
/invokeAny()
:批量提交任务并等待结果。
锁的实现原理
- 悲观锁(如 synchronized)
直接加锁,认为并发冲突概率高,通过操作系统互斥量(Mutex)或 JVM 的 Monitor 实现。 - 乐观锁(如 CAS)
通过版本号或 CAS(Compare-And-Swap)原子操作实现,适合低冲突场景。 - AQS(AbstractQueuedSynchronizer)
Java 并发包(如 ReentrantLock)的底层实现,通过 CLH 队列管理线程阻塞和唤醒。
TCP 协议拥塞控制
- 作用:防止网络过载,通过动态调整发送速率避免拥塞崩溃。
- 机制
- 慢启动:初始阶段指数增长拥塞窗口(cwnd)。
- 拥塞避免:线性增长 cwnd,避免过快。
- 快速重传 / 恢复:检测丢包后快速调整。
String 类常用函数
length()
charAt(int index)
substring(int begin, int end)
equals(Object obj)
indexOf(String str)
toLowerCase()
/toUpperCase()
trim()
replace(char old, char new)
split(String regex)
concat(String str)
String、StringBuffer、StringBuilder 的区别
- 不可变性
- String 不可变(线程安全但效率低)。
- StringBuffer 可变(线程安全,同步)。
- StringBuilder 可变(非线程安全,高效)。
- Buffer 类原理:内部使用字符数组(如
char[] value
)动态扩容,避免频繁内存分配。
String 字符串的不可变
- 不可变:底层
final char[]
数组引用和内容不可变(任何修改都会生成新对象)。 - 例如:
String s = "a"; s += "b";
会创建新对象。
HTTP 协议字段
- Host:指定服务器域名。
- Content-Type:请求 / 响应的数据类型(如
application/json
)。 - User-Agent:客户端标识(如浏览器类型)。
Java 异常类
- Exception(可检查异常)
- IOException(文件操作错误)。
- SQLException(数据库错误)。
- RuntimeException(非检查异常)
- NullPointerException、ArrayIndexOutOfBoundsException。
- Error(系统错误)
- OutOfMemoryError、StackOverflowError。
Java 反射获取类信息的方式
Class.forName("全限定类名")
- 对象
.getClass()
- 类名
.class
Java 代理
- 方法
- 静态代理(手动编写代理类)。
- 动态代理(JDK Proxy、CGLib)。
- 场景
- AOP(如 Spring 事务管理)。
- RPC 框架(远程方法调用封装)。
equals () 方法
- 作用:比较对象内容是否相等(默认比较地址,需重写)。
- 注意事项
- 重写时需同时重写
hashCode()
(确保哈希一致性)。 - 满足自反性、对称性、传递性、一致性。
- 重写时需同时重写
Java 参数传递方式
- 按值传递
- 基本类型传递值副本,引用类型传递引用的副本(即 “按共享对象传递”)。
- 引用传递语言:C++(&)、C#(ref)。
Java 类初始化顺序(含继承)
- 父类静态代码块 → 子类静态代码块。
- 父类实例代码块 → 父类构造方法。
- 子类实例代码块 → 子类构造方法。
本地方法栈作用
- 存储 JVM 调用本地(Native)方法(如 C/C++ 库)的栈帧信息。
双亲委派机制
- 机制:类加载器优先委派父类加载器加载,避免重复加载和核心类被篡改。
- 作用:保证安全性(如防止自定义
java.lang.String
)。
重写(Override)和重载(Overload)的区别
- 重写:子类覆盖父类方法(相同签名)。
- 重载:同一类中方法名相同、参数不同。
子类构造方法调用父类构造方法注意事项
- 子类构造方法必须显式或隐式调用
super()
(父类无参构造)或super(参数)
,需要放在第一行,和this
不能重复。
子类实例初始化是否触发父类实例初始化
- 是:子类实例化前会先初始化父类(包括代码块和构造方法)
instanceof 关键字作用
- 用于判断一个对象是否属于某个类(或其子类、接口实现类)。
- 语法:
对象 instanceof 类/接口
- 示例:
java
运行
Object obj = "Hello"; if (obj instanceof String) {System.out.println("obj是String类型"); }
- 注意:
- 如果对象为 null,返回 false。
- 用于多态场景下的类型安全检查。
类型转换
- 基本类型转换
- 可能丢失精度(如 double 转 int 会截断小数部分)。
- 示例:
java
运行
double d = 3.14; int i = (int)d; // i=3(精度丢失)
- 引用类型转换
- 需确保对象实际类型与目标类型兼容,否则抛出
ClassCastException
。 - 示例:
java
运行
Object obj = "123"; String s = (String)obj; // 成功 Integer num = (Integer)obj; // 抛出ClassCastException
- 建议先用
instanceof
检查类型。
- 需确保对象实际类型与目标类型兼容,否则抛出
重入锁
- 重入锁(Reentrant Lock)
- 实现类:
ReentrantLock
、synchronized
(隐式重入)。
- 实现类:
- 作用
- 允许线程多次获取同一把锁(避免死锁)。
- 示例:递归调用或嵌套同步代码块中需重复加锁。
- 为什么需要:防止线程因重复获取锁而阻塞自己(如递归调用同步方法)。
指令重排序
- 优点:提高 CPU 流水线效率,优化程序性能(如乱序执行)。
- 原因
- 编译器优化:调整指令顺序以减少空转。
- CPU 乱序执行:并行执行无依赖的指令。
- 内存系统重排序:缓存一致性协议(如 MESI)导致写操作延迟。
- 注意:需通过
volatile
或内存屏障(如synchronized
)避免多线程下的可见性问题。
Arrays.sort () 内部原理
- 基本类型数组(如 int []):使用双轴快速排序(Dual-Pivot Quicksort),时间复杂度 O (n log n)。
- 对象数组(如 Object []):使用归并排序(TimSort),稳定排序,时间复杂度 O (n log n)。
- 特点:对小数组(长度 < 47)使用插入排序优化。
堆排序复杂度
- 时间复杂度
- 建堆:O (n)。
- 排序:O (n log n)(每次调整堆 O (log n),共 n 次)。
- 总复杂度:O (n log n)。
- 空间复杂度:O (1)(原地排序,无需额外空间)。
字符串哈夫曼编码存储比特数
- 步骤
- 统计字符频率(如 a:7, s:5, f:4, ...)。
- 构建哈夫曼树(频率低的字符编码长)。
- 计算总比特数:∑(字符频率 × 编码长度)。
- 示例(简化版):假设编码后平均每个字符占 3 比特,总长度≈24 字符 × 3 比特 = 72 比特。
- 实际值需根据具体哈夫曼树计算。
CPU 高速缓存优缺点
- 优点
- 减少访问内存的延迟(缓存速度远高于内存)。
- 提高数据局部性(时间局部性、空间局部性)。
- 缺点
- 缓存一致性:多核 CPU 需同步缓存(如 MESI 协议)。
- 缓存污染:频繁换入换出降低命中率。
线程安全的类
- StringBuffer:同步方法保证线程安全。
- ConcurrentHashMap:分段锁 + CAS 实现高效并发。
- Vector(已过时):所有方法用
synchronized
修饰。
LRU 算法
- 定义:Least Recently Used(最近最少使用),淘汰最久未访问的数据。
- 实现
- 数据结构:哈希表(快速查找) + 双向链表(维护访问顺序)。
- 示例:
LinkedHashMap
(通过accessOrder=true
实现 LRU)。
- 应用:缓存淘汰策略(如 Redis、页面置换算法)。
Spring 框架
Spring Bean 容器与 Spring IOC 容器的区别
- Spring Bean 容器:管理 Bean(对象)的生命周期(创建、依赖注入、销毁)。
- IOC 容器:是 Bean 容器的核心,负责控制反转(将对象创建权交给容器)。
- 区别
- Bean 容器是 IOC 容器的具体实现(如
ApplicationContext
)。 - IOC 是设计思想,Bean 容器是技术实现。
- Bean 容器是 IOC 容器的具体实现(如
Spring IOC 理解
- 定义:Inversion of Control(控制反转),将对象的创建和依赖管理交给 Spring 容器。
- 核心
- 解耦:对象间通过接口依赖,而非硬编码。
- 配置化:通过 XML 或注解定义 Bean。
Spring DI 理解
- 定义:Dependency Injection(依赖注入),IOC 的实现方式。
- 方式
- 构造器注入(推荐)。
- Setter 注入。
- 字段注入(@Autowired)。
Spring 注解配置对象作用域和延迟加载
- 作用域
java
运行
@Scope("prototype") // 多例 @Scope("singleton") // 单例(默认)
- 延迟加载
java
运行
@Lazy // 首次访问时初始化Bean
Spring 工厂底层构建 Bean 对象机制
- 机制:反射(
Class.newInstance()
) + 动态代理(AOP)。 - 释放资源
- 调用
@PreDestroy
方法或实现DisposableBean
接口。
- 调用
- 内存泄漏:对象无法被 GC 回收(如静态集合持有 Bean 引用)。
Spring MVC 处理流程及优势
- 流程
- 用户请求 →
DispatcherServlet
。 - 调用
HandlerMapping
找到 Controller。 - 执行 Controller → 返回
ModelAndView
。 - 视图渲染(
ViewResolver
)。
- 用户请求 →
- 优势
- 分层清晰(MVC)。
- 支持 RESTful、注解驱动开发。
Spring 事务处理方式及优缺点
- 方式
- 声明式事务(
@Transactional
):代码简洁,但粒度较粗。 - 编程式事务(
TransactionTemplate
):灵活,但需手动管理。
- 声明式事务(
- 缺点:声明式事务可能因异常处理不当导致事务不生效。
MyBatis 中 #与 $ 的区别
#{}
:预编译(防 SQL 注入),自动加引号(适用于参数值)。${}
:字符串替换(直接拼 SQL),适用于动态表名、列名。
MyBatis 动态 SQL 解决的问题
- 问题:根据条件拼接 SQL(避免 Java 代码中写大量 if)。
- 标签:
<if>
、<where>
、<foreach>
。
Shiro 框架认证和授权流程
- 认证(Authentication)
- 用户提交凭证(如用户名 / 密码)。
Realm
校验凭证 → 生成Subject
。
- 授权(Authorization)
Subject
调用checkPermission()
或checkRole()
。Realm
查询权限数据并验证。
BeanFactory 和 ApplicationContext 区别
特性 | BeanFactory | ApplicationContext |
---|---|---|
功能 | 基础 IOC 容器,提供 Bean 的创建和依赖注入 | 继承 BeanFactory,扩展企业级功能(AOP、事件发布、国际化等) |
加载时机 | 懒加载(首次调用getBean() 时初始化) | 预加载(启动时初始化所有单例 Bean) |
AOP 支持 | 需手动注册拦截器 | 内置 AOP 支持 |
适用场景 | 资源受限环境(如移动设备) | 大多数企业级应用 |
Spring Bean 的生命周期
- 实例化:通过反射创建 Bean 对象。
- 属性赋值:依赖注入(
@Autowired
或 XML 配置)。 - 初始化:
- 调用
InitializingBean.afterPropertiesSet()
。 - 执行自定义初始化方法(
@PostConstruct
或init-method
)。
- 调用
- 使用:Bean 准备就绪,被应用程序使用。
- 销毁:
- 调用
DisposableBean.destroy()
。 - 执行自定义销毁方法(
@PreDestroy
或destroy-method
)。
- 调用
Spring Bean 的作用域区别
作用域 | 描述 |
---|---|
singleton | 默认作用域,每个容器中只有一个实例(线程不安全需自行同步)。 |
prototype | 每次请求创建新实例(适合有状态的 Bean)。 |
request | 每个 HTTP 请求创建一个实例(Web 应用)。 |
session | 每个用户会话创建一个实例(Web 应用)。 |
application | 整个 Web 应用共享一个实例(类似 singleton,但跨 ServletContext)。 |
使用 Spring 框架的好处
- 解耦:IOC 降低组件间耦合。
- AOP 支持:统一处理日志、事务等横切关注点。
- 简化开发:集成 JDBC、ORM、Web 框架(如 MyBatis、Hibernate)。
- 模块化:Spring Boot、Spring Cloud 等生态支持。
Spring 中用到的设计模式
- 工厂模式:
BeanFactory
创建对象。 - 单例模式:默认 Bean 作用域。
- 代理模式:AOP 动态代理(JDK/CGLib)。
- 模板方法:
JdbcTemplate
封装固定流程。 - 观察者模式:事件监听(
ApplicationEvent
)。
Spring 如何保证 Controller 并发安全
- 默认情况:Controller 是单例,成员变量共享可能导致线程不安全。
- 解决方案
- 避免使用成员变量(推荐)。
- 使用
@Scope("prototype")
声明多例 Controller(性能较差)。 - 对共享变量加锁(如
synchronized
)。
在 Spring 中注入 Java 集合
- XML 配置
xml
<bean id="collectionBean"><property name="list"><list><value>item1</value><value>item2</value></list></property><property name="map"><map><entry key="key1" value="value1"/></map></property> </bean>
- 注解配置
java
运行
@Autowired private List<String> list; @Autowired private Map<String, Object> map;
Spring 支持的事务管理类型
- 编程式事务:通过
TransactionTemplate
或PlatformTransactionManager
手动控制。 - 声明式事务:通过
@Transactional
注解(推荐)。
Spring 事务管理的优点
- 统一 API:支持 JDBC、JPA、Hibernate 等不同持久化技术。
- 声明式简化:通过注解配置事务边界和属性。
- 传播机制:支持 REQUIRED、REQUIRES_NEW 等复杂场景。
Spring MVC 主要组件
DispatcherServlet
:前端控制器,接收所有请求。HandlerMapping
:映射请求到 Controller。- Controller:处理业务逻辑。
ViewResolver
:解析视图名到具体页面。
SpringMVC 与 AJAX 交互
- 后端返回 JSON
java
运行
@RestController public class AjaxController {@GetMapping("/data")public Map<String, String> getData() {return Map.of("key", "value");} }
- 前端 AJAX 调用
javascript
fetch("/data").then(response => response.json()).then(data => console.log(data));
MyBatis 缓存机制
- 一级缓存
- 作用域:
SqlSession
级别(默认开启)。 - 失效条件:执行 update、commit、close 操作。
- 作用域:
- 二级缓存
- 作用域:Mapper 级别(需手动配置
<cache/>
)。 - 跨
SqlSession
共享,适合读多写少场景。
- 作用域:Mapper 级别(需手动配置
SpringMVC 与 Struts2 区别
特性 | SpringMVC | Struts2 |
---|---|---|
设计思想 | 基于方法拦截(Servlet API) | 基于类拦截(Filter 分发) |
性能 | 更高(无拦截器栈) | 较低(多层拦截器) |
配置 | 注解驱动(简洁) | XML 配置(繁琐) |
社区生态 | 活跃(Spring 生态) | 逐渐被淘汰 |
MyBatis 基本工作流程
- 加载配置(
mybatis-config.xml
+ Mapper XML)。 - 创建
SqlSessionFactory
。 - 通过
SqlSession
执行 SQL(调用 Mapper 接口方法)。 - 返回结果(自动映射或手动处理)。
MyBatis 接口绑定的好处
- 定义:Mapper 接口与 XML/SQL 直接绑定。
- 好处
- 类型安全(编译时检查)。
- 无需手动写 DAO 实现类。
MyBatis 编程步骤
- 定义 Mapper 接口。
- 编写 XML/SQL 映射文件。
- 通过
SqlSession.getMapper()
获取代理对象。 - 调用接口方法执行 SQL。
JDBC 不足与 MyBatis 解决方案
JDBC 问题 | MyBatis 解决方案 |
---|---|
硬编码 SQL(维护难) | SQL 与 Java 代码分离(XML / 注解) |
手动处理结果集 | 自动映射对象(ORM) |
频繁创建 / 释放连接 | 连接池集成(如 HikariCP) |
MyBatis 优缺点
- 优点
- 灵活(SQL 可控)。
- 轻量级(无侵入性)。
- 缺点
- 需手动编写 SQL(对复杂查询不友好)。
- 缓存机制较弱(对比 Hibernate)。