在Java开发岗位的面试中,面试官不仅考察基础知识,还会结合项目经验、架构设计、性能优化等维度综合评估候选人。本文从 Java基础、JVM与并发、数据库、框架与中间件、项目与架构 五个方面,整理15个典型面试题,并提供 回答思路+示例答案+代码示例,帮助初中级Java工程师在面试中脱颖而出。
面试题:Java集合框架有哪些常用接口和实现类?ArrayList和LinkedList的区别?
回答思路:
示例代码:
// ArrayList 示例
List<String> arrayList = new ArrayList<>();
arrayList.add("Java"); // O(1) 平均
arrayList.get(0); // O(1)
// LinkedList 示例
List<String> linkedList = new LinkedList<>();
linkedList.add("Python"); // O(1)
linkedList.remove(0); // O(1) 头尾操作完美回答:
Java集合框架主要分为List、Set、Map三大接口。
ArrayList(动态数组,查询快)、LinkedList(链表,增删快)。HashSet(无序)、TreeSet(有序)。HashMap(线程不安全)、ConcurrentHashMap(线程安全)。ArrayList vs LinkedList:
ArrayList 的 get(index) 是O(1),LinkedList 是O(n)。LinkedList 在头尾插入是O(1),ArrayList 可能需要扩容(O(n))。 实际应用:在电商项目中,商品列表用 ArrayList(高频查询),而订单排队系统用 LinkedList(频繁增删)。
面试题:什么是多线程?如何创建线程?Thread和Runnable的区别?
回答思路:
示例代码:
// 方式1:继承Thread(不推荐)
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running");
}
}
// 方式2:实现Runnable(推荐)
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable running");
}
}
// 使用线程池
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(new MyRunnable());完美回答:
多线程 允许一个进程内多个任务并发执行,提高CPU利用率。Java创建线程的方式:
Thread vs Runnable:
Runnable 更灵活,可以配合线程池使用。Thread 是类,Runnable 是接口,避免继承冲突。 实际应用:在“悦听戏曲”项目中,使用 CompletableFuture 实现异步编排,提升接口响应速度。
面试题:JVM内存模型是怎样的?堆和栈的区别?
回答思路:
示例代码:
// 堆溢出示例
List<Object> list = new ArrayList<>();
while (true) {
list.add(new Object()); // OutOfMemoryError: Java heap space
}
// 栈溢出示例
public class StackOverflow {
public static void recursive() {
recursive(); // StackOverflowError
}
}完美回答:
JVM内存分为:
StackOverflowError。堆 vs 栈:
实际应用:在“秋水商城”项目中,因缓存大Key导致堆OOM,通过 -Xmx 调整堆大小解决。
面试题:MySQL索引有哪些类型?B+树索引的优势?
回答思路:
LIKE '%xx%)。示例代码:
-- 创建联合索引
CREATE INDEX idx_category_price ON products(category_id, price);
-- 索引失效示例(使用函数)
SELECT * FROM products WHERE YEAR(create_time) = 2023; -- 无法走索引完美回答:
MySQL索引类型:
(a,b) 索引能优化 WHERE a=1 AND b=2)。B+树优势:
WHERE id > 100)。 实际应用:在电商项目中,商品表 (category_id, price) 建联合索引,查询性能提升50%。
面试题:如何解决缓存穿透和缓存击穿?你在项目中是怎么做的?
回答思路:
示例代码:
// 使用Redisson解决缓存击穿
RLock lock = redisson.getLock("product:lock");
try {
lock.lock();
// 查DB并回填缓存
} finally {
lock.unlock();
}完美回答:
缓存穿透:查询不存在的数据(如恶意攻击),解决方案:
NULL。缓存击穿:热点key过期瞬间高并发请求压垮DB,解决方案:
实际应用:在“悦听戏曲”项目,用 RedissonLock + 布隆过滤器 防止恶意请求穿透。
最终建议:
掌握这些方法,你的面试通过率将大幅提升! 🚀