Java 面试笔记

Java 面试笔记

参考:HashMap 与 Hashtable 的区别

1 HashMap 与 Hashtable 的区别

  1. 线程安全:HashMap 不是线程安全的,不能在没有同步代码的情况下被多线程共享;Hashtable 是线程安全的,可以被多线程共享;
  2. null 值:HashMap 允许一个 null key 和多个 null value;Hashtable 不允许任何 null key 或 value;
  3. 选择:如果不需要线程同步,通常首选 HashMap 而不是 Hashtable。

为什么 Hashtable 不允许 null 而 HashMap 允许

要从 Hashtable 中成功存取对象,key 必须实现 hashCode 方法和 equals 方法。由于 null 不是对象,无法实现这些方法。HashMap 是 Hashtable 的改进版本,创建得更晚,所以放宽了这个限制。

2 JVM 面试要点

JVM 内存结构

  • 线程私有:虚拟机栈(栈帧:局部变量表、操作数栈、方法返回地址)、本地方法栈、程序计数器;
  • 线程共享:堆(对象实例)、方法区(类信息/常量/静态变量,JDK8 后为元空间 Metaspace,使用本地内存);
  • 类加载信息存储在方法区/元空间。

类加载过程

加载(Loading)→ 验证(Verification)→ 准备(Preparation)→ 解析(Resolution)→ 初始化(Initialization)。

  • 类加载器:启动类加载器(Bootstrap)、扩展类加载器(Extension)、应用类加载器(Application),双亲委派模型;
  • 磁盘文件到 JVM 的加载过程即以上五步,加载阶段把字节流读入内存形成 Class 对象。

垃圾回收

  • 判断回收:可达性分析,GC Roots:虚拟机栈中引用的对象、方法区中静态属性引用的对象、方法区中常量引用的对象、本地方法栈中 JNI 引用的对象等;
  • minor gc / full gc:新生代 Minor GC(Eden 满触发),老年代 Full GC;
  • 四种引用:
    • 强引用:引用存在则永不回收,内存不足抛 OOM;
    • 软引用 SoftReference:内存不足先回收,适合缓存;
    • 弱引用 WeakReference:下次 GC 即回收;
    • 虚引用 PhantomReference:虚引用随时可能被回收,主要用于堆外内存回收跟踪。

四种引用作为 GC Root 的判断

见上面 GC Roots 列表。

3 线程池

  • 原理:核心线程 corePoolSize → 工作队列 workQueue → 最大线程数 maximumPoolSize → 拒绝策略 handler;
  • 有界 vs 无界队列:无界队列(如 LinkedBlockingQueue 不设容量)任务会一直排队,不会创建非核心线程,可能导致任务积压、内存溢出;有界队列(如 ArrayBlockingQueue)队列满后才创建非核心线程,超过最大线程数执行拒绝策略,能控制资源占用;
  • 应用场景:CPU 密集型任务核心线程数 = CPU 核数+1;IO 密集型 = CPU 核数*2。

4 集合类中为什么不用 int 基本类型

Java 集合只能存放对象的引用,不能存放基本数据类型。因为泛型擦除后所有元素都以 Object 处理,基本类型需要通过自动装箱(Integer 等包装类)存入。用包装类而不是 int 的另一个原因是 int 没有 hashCode/equals 方法。

5 ReentrantLock 与 synchronized

维度 synchronized ReentrantLock
实现 JVM 关键字(monitorenter/exit) JDK 类(AQS)
锁获取 隐式 显式 lock/unlock
中断 不响应中断 lockInterruptibly 支持中断
公平性 非公平 可配置公平/非公平
条件 wait/notify Condition 接口
可重入 支持 支持

6 Java 面试考点汇总

  • 重载/重写和多态;
  • 同步和异步;
  • 手写生产者消费者模式(wait/notify 或 BlockingQueue);
  • BlockingQueue 如何实现阻塞(Condition 的 await/signal);
  • JVM 判断回收、GC Roots、minor gc/full gc;
  • 类加载过程及不足;
  • Java 四种引用;
  • 方法区。
阅读 — · 全站 —
🎸 我的歌单 0 首