八股文
以下是上述 Java 常见八股文面试题的答案:
JVM 相关:
-
JVM 的内存区域划分是怎样的?
- 程序计数器、虚拟机栈、本地方法栈、堆、方法区
- 程序计数器、虚拟机栈、本地方法栈、堆、方法区
-
如何判断对象是否可以被回收?
- 引用计数法(存在循环引用问题)
- 可达性分析算法 主流方法(通过 GC Roots 对象作为起点,搜索引用链)
-
垃圾回收算法有哪些?
- 标记-清除算法、复制算法、标记-压缩算法、分代收集算法。
-
垃圾收集器有哪些?
- 新生代收集器:Serial、ParNew、Parallel Scavenge。
- 老年代收集器:Serial Old、Parallel Old、CMS。
- 全区域收集器:G1。
-
什么是类加载机制?包括哪些步骤?
- 类加载机制是将类的字节码加载到 JVM 中,并生成对应的
Class
对象。 - 步骤:加载、验证、准备、解析、初始化。
- 类加载机制是将类的字节码加载到 JVM 中,并生成对应的
-
什么是双亲委派模型?
- 当一个类加载器收到类加载请求时,先将请求委托给父类加载器,只有父类加载器无法完成加载时,子类加载器才会尝试加载。
-
介绍一下 JVM 的调优参数和常用的调优工具。
- 调优参数:如
-Xms
(初始堆大小)、-Xmx
(最大堆大小)、-XX:NewRatio
(新生代和老年代比例)等。 - 调优工具:
jstat
(查看 JVM 统计信息)、jmap
(生成堆转储快照)、jstack
(查看线程堆栈信息)等。
- 调优参数:如
-
内存泄漏和内存溢出的区别是什么?
- 内存泄漏:程序中不再使用的对象未被释放,导致内存占用不断增加。
- 内存溢出:程序申请的内存超过了 JVM 所能提供的最大内存。
Java 基础:
- 简述面向对象的三大特性(封装、继承、多态)及其含义。
- 封装:将数据和操作数据的方法封装在一个类中,隐藏内部实现细节,只通过公共方法访问。
- 继承:子类可以继承父类的属性和方法,实现代码复用和扩展。
- 多态:同一行为在不同对象上有不同的表现形式,通过方法重写和动态绑定实现。
- Java 中基本数据类型有哪些?
- 字节型(byte)、短整型(short)、整型(int)、长整型(long)、浮点型(float)、双精度浮点型(double)、字符型(char)、布尔型(boolean)。
- 介绍一下自动装箱和自动拆箱。
- 自动装箱:将基本数据类型自动转换为对应的包装类对象。
- 自动拆箱:将包装类对象自动转换为对应的基本数据类型。
String
、StringBuilder
、StringBuffer
的区别是什么?String
是不可变的字符串对象,每次操作会产生新的对象。StringBuilder
是可变的字符串对象,线程不安全,效率较高。StringBuffer
是可变的字符串对象,线程安全,效率略低于StringBuilder
。
- 接口和抽象类的区别有哪些?
- 接口中只能有抽象方法和常量,抽象类可以有普通方法和成员变量。
- 接口中所有方法默认是
public
的,抽象类方法可以有不同的访问修饰符。 - 一个类可以实现多个接口,但只能继承一个抽象类。
final
关键字的作用是什么?可以修饰哪些内容?final
修饰变量,变量值不可改变;修饰方法,方法不能被重写;修饰类,类不能被继承。
- 谈谈
static
关键字的用途。- 修饰成员变量,为类变量,被所有对象共享。
- 修饰方法,为类方法,可以通过类名直接调用。
- 用于静态代码块,在类加载时执行且只执行一次。
- 解释一下
this
和super
关键字的用法和区别。this
:在方法内部使用,代表当前对象,用于访问本对象的成员变量和方法,调用本类的其他构造方法。super
:在子类中使用,用于访问父类的成员变量和方法,调用父类的构造方法。
- 重载(Overload)和重写(Override)的区别是什么?
- 重载:在同一个类中,方法名相同,参数列表不同(参数类型、个数、顺序)。
- 重写:发生在子类和父类之间,方法名、参数列表相同,返回值类型小于等于父类,抛出异常范围小于等于父类,访问修饰符大于等于父类。
- 什么是构造函数?构造函数可以被重载吗?可以被继承吗?
- 构造函数用于创建对象时初始化对象的状态。
- 构造函数可以被重载。
- 构造函数不能被继承,但子类的构造函数会默认调用父类的无参构造函数。
集合框架:
List
、Set
、Map
接口分别有哪些常见的实现类?它们的特点是什么?List
:ArrayList
(基于动态数组,查询快,增删慢)、LinkedList
(基于双向链表,增删快,查询慢)、Vector
(线程安全的ArrayList
)。Set
:HashSet
(基于哈希表,元素无序且不重复)、TreeSet
(基于红黑树,元素有序且不重复)、LinkedHashSet
(基于链表和哈希表,元素有序且不重复)。Map
:HashMap
(基于哈希表,允许null
键和值)、TreeMap
(基于红黑树,按键有序)、HashTable
(线程安全的HashMap
,不允许null
键和值)、ConcurrentHashMap
(线程安全的高效HashMap
)。
- 比较
ArrayList
和LinkedList
的异同。- 相同点:都实现了
List
接口。 - 不同点:
- 数据结构:
ArrayList
基于动态数组,LinkedList
基于双向链表。 - 随机访问:
ArrayList
随机访问快,LinkedList
随机访问慢。 - 增删操作:
ArrayList
增删元素慢,LinkedList
增删元素快。
- 数据结构:
- 相同点:都实现了
HashSet
是如何保证元素唯一性的?- 通过计算元素的哈希值和
equals
方法来判断元素是否唯一。
- 通过计算元素的哈希值和
- 简述
HashMap
的工作原理,包括其存储结构、扩容机制等。- 存储结构:数组 + 链表(当链表长度超过阈值时转换为红黑树)。
- 扩容机制:当元素数量超过负载因子(默认 0.75)与容量的乘积时,进行扩容,容量变为原来的 2 倍,重新计算元素位置。
HashMap
和HashTable
的区别有哪些?HashMap
线程不安全,HashTable
线程安全。HashMap
允许null
键和值,HashTable
不允许。
ConcurrentHashMap
在并发环境下的优势是什么?- 采用分段锁技术,提高并发访问效率,减少锁的粒度。
- 解释
Iterator
和ListIterator
的区别。Iterator
只能向前遍历,ListIterator
可以双向遍历。ListIterator
可以修改元素,Iterator
不可以。
多线程与并发:
-
并发编程三要素是什么?
- 原子性:一个或多个操作要么全部执行成功,要么全部执行失败。
- 可见性:一个线程对共享变量的修改,其他线程能够立即看到。
- 有序性:程序执行的顺序按照代码的先后顺序执行。
-
实现线程的方式有哪些?
- 继承
Thread
类。 - 实现
Runnable
接口。 - 使用
Callable
和Future
创建线程。
- 继承
-
线程的状态流转图是怎样的?
- 新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、等待(Waiting)、超时等待(Timed_Waiting)、终止(Terminated)。
-
什么是线程安全?如何保证线程安全?
- 线程安全是指多个线程访问共享资源时不会出现数据不一致或错误的情况。
- 保证线程安全的方式:使用同步机制(如
synchronized
关键字、Lock
锁)、使用线程安全的集合类、避免共享可变状态等。
-
synchronized
关键字的作用及用法。- 作用:实现线程同步,保证同一时刻只有一个线程访问同步代码块或同步方法。
- 用法:修饰方法(非静态方法锁对象,静态方法锁类)、修饰代码块(指定锁对象)。
- 优化:引入了偏向锁,轻量级锁,重量级锁 减少锁竞争带来的上下文切换; 初始是偏向锁,随着线程竞争加剧,升级为 轻量级锁,最后升级为重量级锁;
-
- 偏向锁 优化同一线程对多次申请同一个锁,比较线程Id是否是当前线程,是不用竞争锁
-
- 轻量级锁 一个线程竞争 偏向锁失败,会 CAS自旋竞争轻量级锁,
-
解释一下线程同步和线程阻塞的概念。
- 线程同步:多个线程协调执行,按照预定的顺序访问共享资源。
- 线程阻塞:线程在等待某个条件满足时进入阻塞状态,暂时放弃 CPU 资源。
-
什么是线程池?有哪些创建方式?
- 线程池是一种管理线程的机制,避免频繁创建和销毁线程。
- 创建方式:通过
Executors
工厂类的静态方法(如newFixedThreadPool
、newCachedThreadPool
等),或直接使用ThreadPoolExecutor
类创建。
-
volatile
关键字的作用是什么?- 保证变量的可见性,禁止指令重排序。
-
ThreadLocal
的用途是什么?- 为每个线程提供独立的变量副本,实现线程隔离。
-
介绍一下
CountDownLatch
、CyclicBarrier
和Semaphore
的作用。CountDownLatch
:一个线程等待其他多个线程完成任务后再执行。CyclicBarrier
:多个线程相互等待,到达某个屏障点后再一起继续执行。Semaphore
:控制同时访问某个资源的线程数量。
Spring 框架:
- 简述 Spring 的核心概念(IOC 和 AOP)。
- IOC(控制反转):将对象的创建和管理交给 Spring 容器,降低对象之间的耦合度。
- AOP(面向切面编程):将横切关注点(如日志、事务、权限等)从业务逻辑中分离出来,实现代码的模块化和复用。
- 什么是依赖注入?有哪些方式?
- 依赖注入是将对象之间的依赖关系由容器在运行时动态注入。
- 方式:构造函数注入、属性注入、Setter 方法注入。
- AOP 的实现原理是什么?
- 基于动态代理(JDK 动态代理和 CGLIB 动态代理)。
- Spring Bean 的生命周期是怎样的?
- 实例化、属性赋值、初始化(调用
init-method
方法)、使用、销毁(调用destroy-method
方法)。
- 实例化、属性赋值、初始化(调用
- 解释 Spring 中事务管理的方式及传播行为。
- 方式:编程式事务管理、声明式事务管理(基于 XML 配置和注解)。
- 传播行为:
PROPAGATION_REQUIRED
(默认,支持当前事务,如果没有则创建新事务)、PROPAGATION_SUPPORTS
(支持当前事务,如果没有则以非事务方式执行)等。
- SpringMVC 的工作原理和主要组件。
- 工作原理:用户发送请求到前端控制器
DispatcherServlet
,DispatcherServlet
根据请求映射找到对应的处理器Handler
,并由HandlerAdapter
执行处理器,处理器返回ModelAndView
,DispatcherServlet
通过视图解析器将ModelAndView
转换为视图并响应给用户。 - 主要组件:
DispatcherServlet
、HandlerMapping
、HandlerAdapter
、ViewResolver
等。
- 工作原理:用户发送请求到前端控制器
- @Autowired 和 @Resource 注解的区别。
@Autowired
:按类型自动装配。@Resource
:先按名称装配,如果找不到再按类型装配。
MyBatis 框架:
- 什么是 MyBatis?它的优点有哪些?
- MyBatis 是一个持久层框架,将 SQL 语句的执行与 Java 代码解耦。
- 优点:灵活的 SQL 编写、与数据库的独立性较好、缓存机制等。
-
和$的区别是什么?
#
:采用预编译方式,能防止 SQL 注入,参数占位符形式。$
:直接拼接 SQL 字符串,可能存在 SQL 注入风险。
- MyBatis 是如何进行分页的?分页插件的原理是什么?
- 可以通过
RowBounds
对象或在 SQL 语句中使用分页语句(如 MySQL 的LIMIT
)进行分页。 - 分页插件的原理通常是通过拦截 SQL 语句,重新构建分页的 SQL 实现。
- 可以通过
- 如何执行批量插入?
- 可以通过循环调用插入方法或使用批量插入的 SQL 语句。
- MyBatis 中如何传递多个参数?
- 使用
@Param
注解为参数命名,或者将参数封装为一个对象。
- 使用
- 简述 MyBatis 的动态 SQL 及其作用。
- 动态 SQL 是根据不同条件动态生成 SQL 语句的部分,包括
if
、choose
、where
、set
等标签。作用是提高 SQL 语句的灵活性和复用性。
- 动态 SQL 是根据不同条件动态生成 SQL 语句的部分,包括
- 解释一下 MyBatis 的一级、二级缓存机制。
- 一级缓存:基于
SqlSession
,默认开启,同一个SqlSession
中执行相同的查询会从缓存中获取结果。 - 二级缓存:基于
namespace
,需要手动开启,不同SqlSession
之间可以共享缓存。
- 一级缓存:基于
Redis 数据库:
- 什么是 Redis?它的数据类型有哪些?
- Redis 是一个高性能的 key-value 数据库。
- 数据类型:字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)。
- Redis 相比 Memcached 有哪些优势?
- 支持数据持久化、数据结构更丰富、支持主从复制和集群等。
- Redis 的持久化机制有哪些?各自的优缺点是什么?
- RDB(快照):将数据定时保存到磁盘,恢复速度快,但可能会丢失数据。
- AOF(日志):将写操作记录到日志,数据完整性好,但文件较大,恢复速度较慢。
- Redis 过期键的删除策略是什么?
- 定时删除、惰性删除、定期删除。
- 如何实现 Redis 的分布式锁?
- 可以使用
SETNX
命令结合超时时间来实现简单的分布式锁。
- 可以使用
- Redis 集群的原理是什么?
- 通过数据分片和主从复制实现高可用和扩展性。
- Redis 支持的 Java 客户端有哪些?
- Jedis、Lettuce 等。
- 解释 Redis 哈希槽的概念。
- Redis 集群将数据分成 16384 个哈希槽,每个节点负责一部分哈希槽,通过计算键的哈希值确定所属的哈希槽,从而找到对应的节点。
MySQL 数据库:
- MySQL 中有哪几种锁?
- 共享锁(读锁)、排他锁(写锁)、意向共享锁、意向排他锁、记录锁、间隙锁、临键锁等。
- 简述 MySQL 中 InnoDB 和 MyISAM 的区别。
- 存储结构:InnoDB 支持聚簇索引,MyISAM 不支持。
- 事务支持:InnoDB 支持事务,MyISAM 不支持。
- 锁机制:InnoDB 支持行锁,MyISAM 支持表锁。
- 崩溃恢复:InnoDB 支持崩溃恢复,MyISAM 不支持。
- MySQL 中 Innodb 支持的四种事务隔离级别名称,以及逐级之间的区别?
- 读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)、串行化(Serializable)。
- 区别主要在于脏读、不可重复读、幻读的避免程度。
- 解释一下索引的概念,以及索引的优缺点。
- 索引是一种数据结构,用于快速查找和排序数据。
- 优点:提高查询效率。
- 缺点:增加数据插入、更新、删除的时间,占用存储空间。
- 什么是存储过程?有什么优点?
- 存储过程是一组预编译的 SQL 语句的集合。
- 优点:提高性能、增强安全性、减少网络流量等。
- 如何优化 MySQL 查询性能?
- 建立合适的索引、优化 SQL 语句、分表分库、缓存等。
设计模式:
- 常见的设计模式有哪些(如单例模式、工厂模式、代理模式等)?请简要介绍其中几种。
- 单例模式:保证一个类只有一个实例,并提供一个全局访问点。
- 工厂模式:定义一个创建对象的接口,让子类决定实例化哪一个类。
- 代理模式:为其他对象提供一种代理以控制对这个对象的访问。
- 观察者模式:定义对象间的
不积跬步,无以至千里;不积小流,无以成江海。