Z
ZHANK

Java 面试题

15 道题 · 3 个模块

简单 6中等 6困难 3

基础语法

6
Q1.JDK、JRE、JVM 的区别?
简单
参考答案
- **JVM**(Java Virtual Machine):执行 Java 字节码的虚拟机——核心运行时
- **JRE**(Java Runtime Environment):JVM + 核心类库——运行 Java 程序所需
- **JDK**(Java Development Kit):JRE + 开发工具(javac、jar、调试器)——开发者安装这个

关系:JDK ⊃ JRE ⊃ JVM
Q2.String、StringBuilder、StringBuffer 的区别?
简单
参考答案
`String` 不可变——每次拼接创建新对象。`StringBuilder` 可变——单线程推荐,速度快。`StringBuffer` 可变——线程安全(synchronized),速度慢。
java
String s = "";
for (int i = 0; i < 10000; i++) s += i;  // ❌ 创建 10000 个对象

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) sb.append(i);  // ✅ 只创建一个对象
Q3.final、finally、finalize 的区别?
简单
参考答案
- **final**:修饰类→不可继承;方法→不可重写;变量→不可修改
- **finally**:try-catch 后**一定执行**的代码块(用于释放资源)
- **finalize()**:Object 的方法——GC 回收前调用(**已废弃**,用 Cleaner 替代)
Q4.Java 中的集合框架?List、Set、Map 的实现类?
中等
参考答案
| 接口 | 实现类 | 特点 |
|------|--------|------|
| List | ArrayList | 数组实现,随机访问快 |
| List | LinkedList | 双向链表,增删快 |
| Set | HashSet | 哈希表,无序 |
| Set | TreeSet | 红黑树,有序 |
| Set | LinkedHashSet | 哈希表+链表,保持插入顺序 |
| Map | HashMap | 哈希表,无序(常用) |
| Map | TreeMap | 红黑树,按键排序 |
| Map | ConcurrentHashMap | 线程安全 HashMap |

选择:默认 ArrayList+HashMap,需要排序用 TreeXXX,线程安全用 ConcurrentHashMap。
Q5.Java 中的异常体系?checked 和 unchecked 异常?
简单
参考答案
所有异常继承自 `Throwable`:
- **Error**:严重错误,不应捕获(OutOfMemoryError, StackOverflowError)
- **Exception**
  - **Checked**(编译时检查):必须 try-catch 或 throws(IOException, SQLException)
  - **Unchecked / RuntimeException**(运行时):不强制处理(NullPointerException, IllegalArgumentException)

java
try {
    // 可能抛异常的代码
} catch (IOException e) {
    // 处理 checked 异常
} catch (RuntimeException e) {
    // 处理 unchecked
} finally {
    // 清理资源
}
Q6.Java 中 == 和 equals() 的区别?为什么要同时重写 hashCode?
简单
参考答案
`==` 比较引用地址,`equals()` 比较内容。Java 约定:如果两个对象 `equals()` 相等,则 `hashCode()` 必须相等。

java
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof User)) return false;
    User u = (User) o;
    return Objects.equals(id, u.id);
}

@Override
public int hashCode() {
    return Objects.hash(id);
}

不重写 hashCode 会导致 HashMap/HashSet 行为异常(同一个对象找不到)。

面向对象

5
Q1.重载(Overload)和重写(Override)的区别?
简单
参考答案
| | 重载 Overload | 重写 Override |
|---|--------------|-------------|
| 发生位置 | 同一个类 | 父子类之间 |
| 方法签名 | 参数不同(数量/类型/顺序) | 完全相同 |
| 返回类型 | 可以不同 | 相同或协变 |
| 访问修饰符 | 任意 | 不能更严格 |
| 多态 | 编译时多态 | 运行时多态 |
| 注解 | 不需要 | @Override |
Q2.接口和抽象类的区别?Java 8+ 有什么变化?
中等
参考答案
| | 抽象类 | 接口 |
|---|--------|------|
| 多继承 | ❌ | ✅ |
| 构造函数 | ✅ | ❌ |
| 成员变量 | 任意 | public static final |
| 方法 | abstract + 具体 | abstract + default + static(Java 8+)|

Java 8+ 接口可以有 `default` 和 `static` 方法实现。Java 9+ 可以有 `private` 方法。
Q3.Java 中的四种引用类型?
困难
参考答案
| 引用类型 | GC 行为 | 用途 |
|----------|--------|------|
| 强引用 Strong | 永不回收 | 默认 new |
| 软引用 SoftReference | 内存不足时回收 | 缓存 |
| 弱引用 WeakReference | 下次 GC 回收 | WeakHashMap |
| 虚引用 PhantomReference | 随时可回收 | 对象回收跟踪 |
Q4.Java 8 的 Stream API 常用操作?
中等
参考答案
java
List<String> list = Arrays.asList("apple", "banana", "cat");

// 中间操作(惰性)
list.stream()
    .filter(s -> s.length() > 3)      // 过滤
    .map(String::toUpperCase)          // 转换
    .sorted()                          // 排序
    .distinct()                        // 去重
    .limit(5)                          // 限制
    .skip(1)                           // 跳过

// 终端操作
    .collect(Collectors.toList());     // 收集
    .forEach(System.out::println);     // 遍历
    .count();                          // 计数
    .anyMatch(s -> s.startsWith("a")); // 匹配
Q5.设计模式在 Java 中的应用?举例说明
困难
参考答案
1. **单例模式**:Spring Bean 默认单例
2. **工厂模式**:`Calendar.getInstance()`、Spring BeanFactory
3. **建造者模式**:`StringBuilder`、Lombok @Builder
4. **观察者模式**:事件监听器、Spring Event
5. **代理模式**:Spring AOP、Java 动态代理
6. **装饰器模式**:`BufferedReader` 包装 `Reader`
7. **适配器模式**:`Arrays.asList()` 适配数组→List
8. **策略模式**:`Comparator` 接口、Spring 策略注入

JVM

4
Q1.Java 的垃圾回收机制?常见的 GC 算法?
中等
参考答案
JVM 堆内存分**年轻代**(Eden + Survivor×2)和**老年代**。
- **Minor GC**:年轻代满了触发——复制算法,速度快
- **Major/Full GC**:老年代满了触发——标记-清除/标记-整理

GC 算法:Serial、Parallel、CMS(并发标记清除)、G1(分区)、ZGC(低延迟)、Shenandoah
Q2.== 和 equals() 的区别?
中等
参考答案
`==` 比较**引用地址**(基本类型比较值)。`equals()` 比较**对象内容**——Object 默认实现也是 `==`,需要重写。
java
String a = new String("hello");
String b = new String("hello");
a == b       // false——不同对象
a.equals(b)  // true——String 重写了 equals

// 重写 equals 必须同时重写 hashCode
Q3.Java 内存模型(JMM)?volatile 关键字的作用?
困难
参考答案
JMM 定义了多线程环境下变量的**可见性**和**有序性**规则。

`volatile` 保证:
1. **可见性**:一个线程修改 volatile 变量后,其他线程立即看到最新值
2. **禁止指令重排**:volatile 变量前后的操作不会被重排序

java
volatile boolean running = true;
// 线程1
while (running) { doWork(); }
// 线程2
running = false;  // 线程1 立即看到变更

`volatile` 不保证原子性——复合操作仍需 `synchronized` 或 `AtomicXXX`。
Q4.synchronized 和 Lock 的区别?
中等
参考答案
| | synchronized | Lock (ReentrantLock) |
|---|-------------|---------------------|
| 语法 | 关键字 | API |
| 自动释放 | ✅(退出代码块) | ❌(必须 unlock) |
| 尝试获取 | ❌ | ✅ tryLock() |
| 可中断 | ❌ | ✅ lockInterruptibly() |
| 公平锁 | ❌ | ✅ new ReentrantLock(true) |
| 条件变量 | wait/notify | Condition |
| 性能 | Java 6+ 优化后接近 | 略高但灵活 |

**默认用 synchronized**,需要高级特性时用 Lock。