1. 计算机网络传输层有哪些协议?分别适用于什么场景?
传输层主要协议有TCP和UDP:
- TCP(传输控制协议):面向连接、可靠传输(通过三次握手建立连接、四次挥手断开,支持重传、流量控制、拥塞控制)。适用于对可靠性要求高的场景,如文件传输(FTP)、网页浏览(HTTP)、邮件发送(SMTP)等。
- UDP(用户数据报协议):无连接、不可靠传输(不保证数据顺序和完整性),但传输效率高。适用于实时性要求高的场景,如视频通话、语音聊天(VoIP)、直播、DNS 查询等。
2. 多线程的使用场景有哪些?线程开启多少个合适?判断标准有哪些?
使用场景:
- 异步任务处理(如短信发送、日志记录);
- 并发请求处理(如 Web 服务器处理多用户请求);
- 耗时操作并行化(如大数据计算、文件批量处理);
- 后台定时任务(如数据同步、缓存清理)。
线程数量判断标准:
- CPU 密集型任务(如计算):线程数≈CPU 核心数(避免频繁上下文切换);
- IO 密集型任务(如网络请求、文件 IO):线程数可适当增加(通常为 CPU 核心数 ×2,或根据 IO 等待时间调整);
- 结合系统资源(内存、句柄数)和业务响应时间要求。
3. 线程池的提交方式有哪几种?
线程池有两种主要提交方式:
- execute(Runnable command):无返回值,无法捕获任务异常(需在任务内部处理);
- submit(Callable<T> task) 或 submit(Runnable task, T result):返回
Future<T>
对象,可通过get()
获取结果或异常,支持取消任务(cancel()
)。
4. 锁的实现原理介绍一下?
Java 中锁的实现主要有两类:
- synchronized:底层依赖 JVM 的对象监视器(Monitor),通过对象头的 Mark Word 存储锁状态。锁升级过程:无锁 → 偏向锁 → 轻量级锁(自旋) → 重量级锁(操作系统互斥量)。
- Lock 接口(如 ReentrantLock):基于AQS(AbstractQueuedSynchronizer) 实现,通过 volatile 变量
state
控制锁状态,支持公平锁 / 非公平锁、可中断、超时获取等特性。
5. TCP 协议中拥塞控制的主要作用是什么?
拥塞控制是 TCP 防止网络过载的关键机制,主要作用:
- 避免发送方速率超过网络承载能力,防止网络拥塞;
- 维持网络吞吐量与延迟的平衡;
- 网络拥塞(如丢包)时,动态调整发送窗口大小,减少数据注入;
- 常用算法:慢开始、拥塞避免、快重传、快恢复。
6. String 类的常用函数有哪些?列举十种。
length()
:返回字符串长度;charAt(int index)
:返回指定索引的字符;substring(int beginIndex, int endIndex)
:截取子字符串;equals(Object obj)
:比较字符串内容是否相等;equalsIgnoreCase(String anotherString)
:忽略大小写比较;indexOf(String str)
:返回子字符串首次出现的索引;lastIndexOf(String str)
:返回子字符串最后出现的索引;trim()
:去除首尾空白字符;replace(char oldChar, char newChar)
:替换字符;split(String regex)
:按正则分割字符串为数组;startsWith(String prefix)
:判断是否以指定前缀开头;endsWith(String suffix)
:判断是否以指定后缀结尾。
7. String 和 StringBuffer、StringBuilder 的区别有哪些?所有类名包含 Buffer 的类的内部实现原理是什么?有什么优势?
区别:
- 可变性:
String
不可变(char 数组被final
修饰,修改创建新对象);StringBuffer
和StringBuilder
可变(直接修改内部数组)。 - 线程安全:
String
天然安全(不可变);StringBuffer
安全(方法加synchronized
);StringBuilder
不安全(无同步,性能更高)。 - 性能:
StringBuilder
>StringBuffer
>String
(频繁修改时)。
含 Buffer 类(如 StringBuffer、ByteBuffer)的原理:
通过预分配的字符 / 字节数组存储数据,容量不足时自动扩容(通常为原容量的 2 倍 + 2),减少内存分配次数。
优势:适合频繁修改场景,避免频繁创建对象导致的内存开销。
8. String 字符串的不可变是指哪里不可变?
String
的不可变指内部存储字符的 char 数组被private final
修饰:
- 无法通过外部修改数组引用(
final
修饰); String
类未提供修改数组元素的方法;- 任何修改(如拼接、替换)都会创建新
String
对象,原对象内容不变。
9. HTTP 协议有哪些字段,列举 3 个就可以。
- Host:指定请求的服务器域名和端口号,用于虚拟主机区分不同网站;
- Content-Type:表示请求 / 响应体的媒体类型,如
application/json
、text/html
; - User-Agent:描述发起请求的客户端信息(浏览器 / 设备型号等),服务器可据此返回适配内容;
- 其他常见:Cookie、Authorization、Content-Length。
10. Java 异常类有哪些?分别管理什么异常?
Java 异常体系以Throwable
为根,分为两类:
- Error:严重错误(如
OutOfMemoryError
、StackOverflowError
),程序无法处理,通常是 JVM 层面问题。 - Exception:可处理的异常,分为:
- Checked Exception(受检异常):编译期检查,必须显式处理(如
IOException
、ClassNotFoundException
); - Unchecked Exception(非受检异常):运行时异常,继承自
RuntimeException
(如NullPointerException
、IndexOutOfBoundsException
)。
- Checked Exception(受检异常):编译期检查,必须显式处理(如
11. Java 反射获取类信息的方式有哪几种?分别是什么?
有 3 种方式:
- Class.forName(String className):通过类全限定名获取(如
Class.forName("java.lang.String")
); - 类名.class:直接使用类的 class 属性(如
String.class
); - 对象.getClass ():通过实例对象获取(如
"abc".getClass()
)。
12. Java 代理的主要方法有哪几种?列举代理的使用场景 2 个。
主要方法:
- 静态代理:编译期生成代理类,手动实现与目标类相同的接口,在方法中增强逻辑;
- 动态代理:
- JDK 动态代理:通过
Proxy.newProxyInstance()
在运行时生成代理类,要求目标类实现接口; - CGLIB 动态代理:通过继承目标类生成代理子类,无需接口(基于字节码增强)。
- JDK 动态代理:通过
使用场景:
- 日志记录(在方法调用前后打印日志);
- 事务管理(在方法执行前后开启 / 提交事务)。
13. equals () 方法的作用是什么?重写 equals 需要注意哪些事项?为什么?
作用:判断两个对象的内容是否相等(默认继承自Object
,实现为==
,即比较地址)。
重写注意事项:
- 自反性:
x.equals(x)
必为true
; - 对称性:
x.equals(y)
与y.equals(x)
结果一致; - 传递性:若
x.equals(y)
和y.equals(z)
为true
,则x.equals(z)
必为true
; - 一致性:多次调用结果一致(对象未修改);
- 非空性:
x.equals(null)
必为false
; - 必须同时重写 hashCode ():确保
equals()
为true
的对象,hashCode()
值必相等(否则 HashMap 等集合会出现逻辑错误)。
14. Java 是按值传递还是按引用传递?什么是引用传递,什么是值传递,哪些语言支持引用传递?
Java 只有值传递:方法参数传递的是 “值的副本”。
- 基本类型:传递值本身的副本(修改参数不影响原变量);
- 引用类型:传递引用地址的副本(可修改对象内容,但无法修改原引用指向)。
值传递:传递变量的副本,方法内修改不影响原变量(如 Java、C)。
引用传递:传递变量的引用(别名),方法内修改直接影响原变量(如 C++ 的引用、Python 的列表传递)。
15. 描述 java 的类初始化顺序?如果存在继承,初始化顺序会如何?
无继承时:
静态变量 → 静态代码块 → 实例变量 → 实例代码块 → 构造方法。
有继承时(父类 A,子类 B):
- 父类静态变量 → 父类静态代码块;
- 子类静态变量 → 子类静态代码块;
- 父类实例变量 → 父类实例代码块 → 父类构造方法;
- 子类实例变量 → 子类实例代码块 → 子类构造方法。
16. 本地方法栈有什么作用?
本地方法栈(Native Method Stack)用于支持 Java 调用本地方法(如用 C/C++ 实现的方法),存储本地方法的局部变量、操作数栈等信息,与虚拟机栈类似,但服务于本地方法。
17. 描述 Java 的双亲委派机制,为什么要用到双亲委派机制?
双亲委派机制:类加载时,子类加载器先委托父类加载器加载,父类无法加载时才自己加载(如
AppClassLoader
→ExtClassLoader
→BootstrapClassLoader
)。作用:
- 防止类重复加载(保证核心类唯一性,如
java.lang.String
不会被自定义类篡改); - 安全性:避免恶意类冒充核心类。
- 防止类重复加载(保证核心类唯一性,如
18. 重写和重载的区别是什么?
特性 | 重写(Override) | 重载(Overload) |
---|---|---|
定义场景 | 子类与父类之间 | 同一类中 |
方法名 | 必须相同 | 必须相同 |
参数列表 | 必须相同 | 必须不同(个数 / 类型 / 顺序) |
返回值 | 子类返回值需是父类的子类(协变) | 可不同 |
访问修饰符 | 子类不能严于父类 | 无限制 |
19. 子类构造方法调用父类构造方法的注意事项有哪些?
- 子类构造方法默认隐式调用父类无参构造(通过
super()
); - 若父类无无参构造,子类必须显式调用父类有参构造(
super(参数)
),且必须放在子类构造方法第一行; - 不能同时调用
super()
和this()
(两者都需放在第一行,冲突)。
20. 子类实例初始化是否触发发父类实例初始化?
是。子类实例化时,会先执行父类的实例初始化(实例变量、实例代码块、构造方法),再执行子类的实例初始化(符合继承的初始化顺序)。
21. instanceof 关键字的作用是什么?
instanceof
用于判断一个对象是否是某个类(或接口、父类)的实例,返回 boolean 值。
例如:"abc" instanceof String
→ true
;new Object() instanceof String
→ false
。
22. 基本类型的强制类型转换是否会丢失精度?引用类型的强制类型转换需要注意什么?
- 基本类型强制转换:可能丢失精度(如
double
转int
会截断小数;long
转int
可能溢出)。 - 引用类型强制转换:
- 需确保对象实际类型与目标类型兼容(如
Object o = "abc"; String s = (String)o
合法); - 若不兼容,运行时抛出
ClassCastException
; - 转换前可通过
instanceof
判断,避免异常。
- 需确保对象实际类型与目标类型兼容(如
23. 重入锁有哪些?为什么要有重入锁?
重入锁:允许同一线程多次获取同一把锁(如synchronized
、ReentrantLock
)。
作用:
- 避免死锁(如一个同步方法调用另一个同步方法时,无需重新竞争锁);
- 简化递归场景的锁处理(递归方法中无需手动释放锁)。
24. 指令重排序的优点是什么?由什么原因导致的?
- 优点:编译器和 CPU 通过调整指令执行顺序,提高程序执行效率(如充分利用 CPU 流水线)。
- 原因:
- 编译器优化(编译期重排);
- CPU 指令级并行(运行期重排);
- 内存系统重排(缓存导致的可见性问题)。
25. Arrays.sort () 的内部原理介绍一下?
- 基本类型数组(如 int []、char []):使用双轴快速排序(Dual-Pivot Quicksort),效率高于传统快排;
- 对象数组:使用TimSort(归并排序与插入排序的结合),利用数据可能的部分有序性优化性能。
26. 堆排序的时间复杂度是多少,空间复杂度是多少?
- 时间复杂度:O (nlogn)(建堆 O (n),调整堆 O (nlogn));
- 空间复杂度:O (1)(原地排序,无需额外空间)。
27. 字符串 “asdasjkfkasgfgshaahsfaf” 经过哈夫曼编码之后存储比特数是多少?
需按以下步骤计算:
- 统计字符频率:假设统计后各字符出现次数为(示例):a:5, s:6, d:2, j:1, k:2, f:4, g:2, h:2;
- 构建哈夫曼树:每次合并频率最小的两个节点,生成新节点(频率为两者之和),重复至只剩一个节点;
- 计算编码长度:从根节点到叶子节点的路径长度为编码长度(左 0 右 1 或反之);
- 总比特数:各字符 “频率 × 编码长度” 之和(具体数值需按实际编码计算,约为 50-70 比特)。
28. CPU 高速缓存的优点和缺点有哪些?
- 优点:
- 速度接近 CPU 主频,大幅减少 CPU 访问内存的等待时间;
- 缓解 CPU 与内存之间的速度差异(CPU 远快于内存);
- 提高数据访问的局部性(时间局部性和空间局部性)。
- 缺点:
- 容量小(通常以 MB 为单位,远小于内存);
- 存在缓存一致性问题(多核心 CPU 中,不同核心缓存的同一数据可能不一致);
- 增加硬件复杂度和成本。
29. 线程安全的类有哪些?列举 2 个以上就可以。
Vector
:线程安全的动态数组(方法加synchronized
);Hashtable
:线程安全的哈希表(方法加synchronized
);ConcurrentHashMap
:高效的线程安全哈希表(分段锁 / CAS+ synchronized);AtomicInteger
:原子整数类(基于 CAS 实现线程安全)。
30. 什么是 LRU 算法?
LRU(Least Recently Used,最近最少使用)是一种缓存淘汰策略:当缓存满时,优先淘汰最长时间未被使用的缓存项。
应用场景:内存缓存(如 Redis 的 LRU 策略)、页面置换算法。
31. 何为 Spring Bean 容器?Spring Bean 容器与 Spring IOC 容器有什么不同吗?
- Spring Bean 容器:负责 Bean 的创建、管理、依赖注入的具体实现(如
BeanFactory
),是 IOC 容器的基础。 - Spring IOC 容器:更广泛的概念,包含 Bean 容器的功能,还提供依赖反转(IOC)的整体架构支持,管理对象的生命周期和依赖关系(如
ApplicationContext
是 IOC 容器的典型实现)。
32. Spring IOC 如何理解?
IOC(控制反转)是 Spring 的核心思想:将对象的创建、依赖管理权从代码转移到容器,反转了传统的 “开发者主动创建对象” 的控制流程,降低组件间耦合。
例如:传统方式需手动new
对象,IOC 中由容器自动创建并注入依赖,开发者只需声明依赖关系。
33. Spring DI 如何理解?
DI(依赖注入)是 IOC 的具体实现方式:容器在创建对象时,自动将其依赖的对象注入(无需手动set
或构造)。
常见注入方式:构造器注入、setter 注入、字段注入(@Autowired
)。
34. Spring 中基于注解如何配置对象作用域?以及如何配置延迟加载机制?
- 作用域配置:使用
@Scope
注解,常见值:singleton
:单例(默认,容器中只有一个实例);prototype
:原型(每次获取创建新实例);request
:请求域(Web 环境,每个请求一个实例)。
- 延迟加载:使用
@Lazy
注解,标记 Bean 在首次被使用时才创建(默认singleton
Bean 在容器启动时创建)。
35. Spring 工厂底层构建 Bean 对象借助什么机制?当对象不使用了要释放资源,目的是什么?何为内存泄漏?
- 构建 Bean 的机制:反射(通过
Class.newInstance()
或构造器反射创建对象)。 - 释放资源的目的:避免资源浪费(如数据库连接、文件句柄),防止内存泄漏。
- 内存泄漏:不再使用的对象仍被引用,导致 GC 无法回收,长期积累会耗尽内存。
36. 描述 Spring MVC 处理流程及应用优势?
处理流程:
- 客户端请求被
DispatcherServlet
(前端控制器)接收; DispatcherServlet
通过HandlerMapping
找到处理请求的Handler
;HandlerAdapter
调用Handler
处理请求,返回ModelAndView
;DispatcherServlet
通过ViewResolver
将逻辑视图解析为物理视图;- 视图渲染模型数据,返回响应给客户端。
优势:
- 分层清晰(表现层、业务层、数据层分离);
- 灵活的视图解析机制,支持多种视图技术;
- 强大的拦截器机制,便于统一处理(如登录验证、日志);
- 与 Spring 生态无缝集成。
37. Spring 中的事务处理方式及优缺点?
- 编程式事务:
- 方式:通过
TransactionTemplate
或PlatformTransactionManager
手动控制事务; - 优点:灵活,可精确控制事务边界;
- 缺点:代码侵入性强,与业务逻辑耦合。
- 方式:通过
- 声明式事务:
- 方式:通过
@Transactional
注解或 XML 配置,AOP 实现事务控制; - 优点:无代码侵入,配置简单,与业务逻辑分离;
- 缺点:灵活性稍差,复杂场景难以精确控制。
- 方式:通过
38. MyBatis 应用中 #与 $ 有什么异同点?
- 相同点:均可在 SQL 中嵌入参数。
- 不同点:
特性 | #{} | ${} |
---|---|---|
处理方式 | 预编译参数(? 占位符) | 字符串直接替换 |
SQL 注入风险 | 无(参数被转义) | 有(直接拼接 SQL) |
适用场景 | 普通参数传递 | 表名、列名动态拼接 |
39. MyBatis 应用动态 SQL 解决了什么问题?
解决传统 JDBC 中 SQL 语句硬编码、拼接复杂(如条件判断导致的多余AND/OR
)的问题。通过<if>
、<where>
、<foreach>
等标签,动态生成 SQL,提高代码灵活性和可维护性。
40. Shiro 框架权限管理时的认证和授权流程描述?
- 认证流程:
- 收集用户身份(如用户名)和凭证(如密码);
- 调用
Subject.login(token)
提交认证; - Shiro 委托
SecurityManager
处理,SecurityManager
调用Realm
; Realm
从数据库获取用户信息,比对凭证,成功则认证通过。
- 授权流程:
- 认证通过后,
Subject.hasRole("admin")
或isPermitted("user:delete")
检查权限; SecurityManager
委托Authorizer
处理,Authorizer
调用Realm
获取用户角色 / 权限;- 比对请求的角色 / 权限,返回结果。
- 认证通过后,
41. BeanFactory 和 ApplicationContext 有什么区别?
特性 | BeanFactory | ApplicationContext |
---|---|---|
功能 | 基础 Bean 管理 | 继承 BeanFactory,增加更多功能(事件、国际化等) |
初始化时机 | 懒加载(getBean 时创建 Bean) | 预加载(启动时创建 singleton Bean) |
常见实现 | DefaultListableBeanFactory | ClassPathXmlApplicationContext |
42. 请解释 Spring Bean 的生命周期?
- 实例化:容器创建 Bean 对象(调用构造方法);
- 属性注入:容器为 Bean 设置依赖属性(setter 方法或字段注入);
- 初始化前:执行
BeanPostProcessor
的postProcessBeforeInitialization
; - 初始化:
- 调用
InitializingBean
的afterPropertiesSet()
; - 执行
init-method
指定的方法;
- 调用
- 初始化后:执行
BeanPostProcessor
的postProcessAfterInitialization
; - 使用:Bean 可被应用程序使用;
- 销毁:
- 调用
DisposableBean
的destroy()
; - 执行
destroy-method
指定的方法。
- 调用
43. Spring Bean 的作用域之间有什么区别?
singleton
:全局唯一实例,容器启动时创建(默认);prototype
:每次请求创建新实例,容器不管理销毁;request
:Web 环境中,每个 HTTP 请求一个实例;session
:Web 环境中,每个会话一个实例;application
:Web 环境中,整个应用生命周期一个实例。
44. 使用 Spring 框架的好处是什么?
- 降低耦合(IOC 容器管理对象依赖);
- 声明式事务简化事务管理;
- AOP 支持横切关注点(如日志、安全);
- 丰富的生态(与 MyBatis、Hibernate 等无缝集成);
- 简化 Java EE 开发,提高开发效率。
45. Spring 中用到了那些设计模式?
- 工厂模式(
BeanFactory
创建 Bean); - 单例模式(
singleton
作用域 Bean); - 代理模式(AOP、事务管理);
- 模板方法模式(
JdbcTemplate
); - 观察者模式(事件监听机制)。
46. Spring 如何保证 Controller 并发的安全?
- Controller 默认是单例,需避免使用成员变量(多线程共享会导致安全问题);
- 若需状态,使用
prototype
作用域或 ThreadLocal 存储线程私有数据。
47. 使用 Spring 框架的好处是什么?(同 44 题,重复)
同 44 题答案。
48. 在 Spring 中如何注入一个 java 集合?
通过<list>
、<set>
、<map>
、<props>
标签或注解注入:
<bean id="myBean" class="com.example.MyBean">
<property name="list">
<list>
<value>item1</value>
<ref bean="otherBean"/>
</list>
</property>
</bean>
49. Spring 支持的事务管理类型?
- 编程式事务(通过
TransactionTemplate
); - 声明式事务(通过
@Transactional
或 XML 配置)。
50. Spring 框架的事务管理有哪些优点?
- 非侵入式(声明式事务无需修改业务代码);
- 支持多种事务管理器(JDBC、Hibernate 等);
- 灵活的事务属性配置(隔离级别、传播行为、超时等)。
51. Spring MVC 的主要组件?
DispatcherServlet
:前端控制器,统一接收请求;HandlerMapping
:映射请求到 Handler;HandlerAdapter
:执行 Handler 并返回ModelAndView
;ViewResolver
:解析视图名到具体视图;HandlerInterceptor
:拦截器,处理请求前后逻辑。
52. SpringMvc 怎么和 AJAX 相互调用的?
- AJAX 通过
XMLHttpRequest
或fetch
发送请求(通常为 JSON 格式); - Spring MVC 控制器方法用
@ResponseBody
注解返回 JSON(自动转换对象为 JSON);
示例:java
运行
@PostMapping("/api/data") @ResponseBody public Result getData(@RequestBody User user) { return Result.success(service.process(user)); }
53. Mybatis 中 #和 $ 的区别?(同 38 题,重复)
同 38 题答案。
54. mybatis 的缓存机制,一级,二级介绍一下?
- 一级缓存:
- 作用域:
SqlSession
(会话级别); - 默认开启,无需配置;
- 同一
SqlSession
内,相同 SQL 查询会缓存结果,关闭会话后失效。
- 作用域:
- 二级缓存:
- 作用域:
Mapper
(命名空间级别); - 需要手动开启(在 Mapper XML 中配置
<cache/>
); - 多个
SqlSession
共享缓存,查询结果会先放入二级缓存。
- 作用域:
55. SpringMVC 与 Struts2 的区别?
- 核心控制器:Spring MVC 是
DispatcherServlet
(单例);Struts2 是FilterDispatcher
(多例 Action); - 线程安全:Spring MVC Controller 单例(无状态安全);Struts2 Action 多例(有状态);
- 配置方式:Spring MVC 支持注解为主;Struts2 依赖 XML 配置较多;
- 灵活性:Spring MVC 更轻量,与 Spring 生态整合更好。
56. mybatis 的基本工作流程?
- 读取 MyBatis 配置文件(
mybatis-config.xml
); - 创建
SqlSessionFactory
(工厂模式); - 通过
SqlSessionFactory
获取SqlSession
; SqlSession
获取 Mapper 接口代理对象;- 调用 Mapper 方法执行 SQL;
- 提交事务(增删改)或直接获取结果(查询);
- 关闭
SqlSession
。
57. 什么是 MyBatis 的接口绑定,有什么好处?
- 接口绑定:将 Mapper 接口与 XML 映射文件关联,通过接口方法名匹配 XML 中的 SQL ID,无需实现类即可调用。
- 好处:
- 消除硬编码(无需手动调用
SqlSession
的selectOne
等方法); - 类型安全(编译期检查方法参数和返回值)。
- 消除硬编码(无需手动调用
58. MyBatis 的编程步骤?
- 导入 MyBatis 依赖;
- 编写核心配置文件(数据源、映射文件等);
- 编写实体类(POJO);
- 编写 Mapper 接口和 XML 映射文件(定义 SQL);
- 创建
SqlSessionFactory
和SqlSession
; - 通过
SqlSession
获取 Mapper 接口,调用方法操作数据库。
59. JDBC 编程有哪些不足之处,MyBatis 是如何解决这些问题的?
- JDBC 不足:
- 频繁创建 / 关闭连接,资源浪费(MyBatis 用连接池解决);
- SQL 硬编码在 Java 代码中,维护困难(MyBatis 将 SQL 放在 XML / 注解中);
- 手动设置参数和映射结果集,代码冗余(MyBatis 自动参数映射和结果映射);
- 无缓存机制,性能差(MyBatis 提供一、二级缓存)。
60. MyBatis 的优缺点?
- 优点:
- 简化 JDBC 代码,消除冗余操作(如连接管理、结果集处理);
- SQL 与代码分离,便于优化和维护;
- 支持动态 SQL,灵活应对复杂查询;
- 缓存机制提升查询效率。
- 缺点:
- 工作量较大(需编写大量 XML 或注解);
- SQL 优化依赖开发者能力;
- 对存储过程支持有限。