博主是一名软件工程专业的大三学生,最近也是在找实习,博主是简历没少投但是回应却较少,不过话又说回来,若是投中了去面试却没有过那可盖了帽了(完了的意思)。所以我会分享一些Java的面试题大部分都是博主遇到过的。没有什么顺序就是想到哪题说那题。
一、Java基础(普通题)
下面是一些面试题目先看看能不能答出来,不要模棱两可,虽然基础但要清楚。
题目
Java基础
- 什么是 Java 的多态性?请举例说明。
- 面向对象三大特征?
- String 为什么是不可变的?有什么好处?
Java多线程
- Java 创建线程有哪几种方式?优劣对比?
synchronized
修饰方法和代码块的区别?- 在 Java 中启动多线程时为什么不是直接调用
run()
方法而是start()
方法?
Java集合
- HashMap 的是基于什么数据结构实现的?讲一讲它的工作原理是什么?
- ArrayList 和 LinkedList 有什么区别?它们适用场景是什么?
- 需要使用Map又要保证线程安全要用到什么数据结构?
Java设计模式
- 接口与抽象类的区别是什么?
- 对于设计模式中的单例模式是否了解?现在编写一个单例模式。
答案
Java基础
- 什么是 Java 的多态性?请举例说明。
参考答案:多态性是指对象在运行时表现出不同形态的能力,通过继承和接口实现。
示例:父类Animal
有speak()
方法,子类Dog
和Cat
重写该方法。当Animal a = new Dog()
时,a.speak()
调用的是Dog
的实现。
- 面向对象三大特征?
参考答案:面向对象编程(OOP)的三大核心特征是 封装(Encapsulation)、继承(Inheritance) 和 多态(Polymorphism)。
- String 为什么是不可变的?有什么好处?
参考答案:String 不可变是因为其内部使用final char[]
存储字符。好处包括:
线程安全,支持字符串常量池(节省内存),避免安全漏洞(如 SQL 注入)。
Java多线程
- Java 创建线程有哪几种方式?优劣对比?
参考答案:继承 Thread 类:简单但无法继承其他类。
实现 Runnable 接口:推荐,避免单继承限制。
实现 Callable 接口:支持返回值和抛出异常。
线程池(ExecutorService):复用线程,提高性能。
synchronized
修饰方法和代码块的区别?
参考答案:修饰方法:锁对象是当前实例(this)或类对象(静态方法)。
修饰代码块:锁对象可以自定义(如synchronized(obj)),粒度更细。
- 在 Java 中启动多线程时为什么不是直接调用
run()
方法而是start()
方法?
参考答案:
start()方法的作用:
start()是 Thread 类的核心方法,用于启动一个新线程。JVM 会为新线程分配调用栈等资源,并自动调用run()方法的代码。此时,run()在新线程的上下文中执行,实现真正的并发。
直接调用run()的问题:
如果直接调用run(),它会在当前线程(如 main 线程)中同步执行,就像普通方法调用一样,不会创建新线程。这违背了多线程的初衷。
Java集合
- HashMap 的是基于什么数据结构实现的?简单讲一讲它的工作原理是什么?
参考答案:HashMap 基于哈希表实现,底层结构是数组 + 链表 + 红黑树。
工作原理:
- 哈希计算:通过key.hashCode()计算哈希值,再经扰动函数(如(h = key.hashCode()) ^ (h >>> 16))减少哈希冲突。
- 数组定位:哈希值对数组长度取模((n-1) & hash),确定桶(Bucket)位置。
- 冲突处理:链表:冲突元素以链表形式存储在桶中(JDK7 及以前为头插法,JDK8 改为尾插法)。红黑树:当链表长度≥8 且数组长度≥64 时,链表转为红黑树(查询效率从 O (n) 提升至 O (log n))。
- 扩容机制:当元素数量超过阈值(容量 × 负载因子,默认 16×0.75=12)时,触发扩容(数组长度翻倍)并重新哈希。
- ArrayList 和 LinkedList 有什么区别?它们适用场景是什么?
参考答案:ArrayList是动态数组,LinkedList是双向链表。
ArrayList随机访问效率高适合读多写少的场景,二LinkedList插入效率高适合读少写多的场景。
- 需要使用Map又要保证线程安全要用到什么数据结构?
使用ConcurrentHashMap
Java设计模式
- 接口与抽象类的区别是什么?
参考答案:
特性 | 接口(Java 8+) | 抽象类 |
实现方式 | 多实现(implements) | 单继承(extends) |
默认方法 | 支持(default关键字) | 支持普通方法 |
构造函数 | 无 | 有(用于子类初始化) |
- 对于设计模式中的单例模式是否了解?现在编写一个单例模式。
参考答案:
public class Singleton {
private static volatile Singleton instance; // 禁止指令重排
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
二、Java基础(场景题)
下面是一些简单场景问题。
1、这段代码有什么性能问题?如何优化?
String result = "";
for (int i = 0; i < 1000; i++) {
result += "a";
}
答案
问题:String是不可变对象,每次+=操作都会创建新对象,导致大量临时对象和 GC,时间复杂度 O (n²)。
优化:使用StringBuilder(线程不安全,单线程场景)或StringBuffer(线程安全)。
2、代码的输出结果是什么?为什么?
public class Test {
public static final Test INSTANCE = new Test();
public static int counter1;
public static int counter2 = 0;
private Test() {
counter1++;
counter2++;
}
public static void main(String[] args) {
System.out.println("counter1=" + counter1); // 输出?
System.out.println("counter2=" + counter2); // 输出?
}
}
答案
输出:counter1=1,counter2=0。
原因:静态变量按声明顺序初始化。INSTANCE初始化时,counter1和counter2默认值为 0,构造函数执行后均变为 1;但counter2随后被显式赋值为 0。
3、这段代码会抛出什么异常?为什么?
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
for (String s : list) {
if (s.equals("b")) {
list.remove(s);
}
}
答案
抛出ConcurrentModificationException。
原因:for-each循环使用Iterator,修改集合结构(如remove())会导致modCount与expectedModCount不一致。
4、在多线程环境下使用 HashMap 会导致什么问题?如何解决?
答案
问题:多线程下put()可能导致环形链表(JDK7)或数据丢失(JDK8)。
解决方案:
使用ConcurrentHashMap(推荐)。
使用Collections.synchronizedMap(new HashMap<>())。5、上述方法的返回值是什么?为什么?
public static int test() {
try {
return 1;
} finally {
return 2;
}
}
答案
返回值:2
原因:finally块中的代码总是会执行,且return语句会覆盖try块中的返回值。
三、如何找题
以上的内容只是Java面试题中的冰山一角,要想通过面试需要的远远比这多,那么如何找题呢?有两种方式:
- 在网上找现成的资料,都是别人整理好的,最好是找2025年最新的。这个方法的优点是整理的资料往往会很全面。
- 使用AI模拟面试出题,这个方法的优点是可以根据你的需求来,并且不理解的可以让AI给你详细讲,直到理解这个知识点。
我个人推荐先从网上找一些资料保存到本地,先看一遍然后把资料喂给AI让他直接根据面试题对你进行模拟面试,一段时间熟悉差不多时,再让AI根据已有的题目进行难度的变化等等,加强对题的理解。
最后我祝大家都能找到合适的工作。