Java 必须牢记的 50 个核心知识点(面试 + 日常编码全覆盖,精简好记忆)

一、基础数据类型与包装类(1~8)

  1. Java8 大基本类型:byte/short/int/long/float/double/char/boolean,存栈,无对象头,不产生 GC。
  2. 包装类是对象,存堆;-128~127 有缓存,超出范围==判断结果为 false。
  3. 浮点型float/double二进制存储有精度丢失,金额计算必须用BigDecimal
  4. char本质是无符号 16 位数字,存 ASCII/Unicode,单引号只能放单个字符。
  5. 自动装箱底层调用valueOf(),自动拆箱调用xxxValue(),循环大量装箱会加重 GC。
  6. null只能赋值给引用类型,基本类型不能赋值 null,否则编译报错。
  7. Boolean只有两个静态常量TRUE/FALSE,所有包装实例复用这两个对象。
  8. 三目运算符两边类型不一致时会自动向上转型,极易引发强转异常。

二、String、常量池(9~14)

  1. Stringfinal修饰不可变,修改字符串本质是新建对象。
  2. 字面量字符串存入字符串常量池,new String()一定会在堆创建新对象。
  3. 循环拼接字符串禁止直接+,海量循环用StringBuilder;单线程用StringBuilder,多线程StringBuffer
  4. equals判字符串相等,==只判断内存地址;常量前置"abc".equals(str)防止空指针。
  5. JDK8 常量池在堆,JDK7 后永久代取消,元空间存类信息,常量池移至堆。
  6. intern()方法主动将字符串放入常量池,复用对象减少内存占用。

三、面向对象、修饰符、重载重写(15~22)

  1. 四类访问权限:private < default(包私有) < protected < public
  2. final修饰变量不可二次赋值;修饰方法不能重写;修饰类不能被继承。
  3. static属于类,只加载一次;静态方法只能访问静态变量,不能使用this/super
  4. 方法重载:同类,方法名相同,参数列表不同,与返回值无关。
  5. 方法重写:子类重写父类方法,访问权限不能变严格;不能抛出更宽泛受检异常。
  6. this代表当前实例;super代表父类实例;静态上下文无法使用两者。
  7. 构造方法无返回值、方法名与类名一致;不能被static/final/abstract修饰。
  8. 抽象类abstract class可存变量、构造方法;接口 JDK8 前只有抽象方法。

四、接口、函数式接口、Lambda(23~28)

  1. JDK8 接口:支持default默认方法、static静态方法;JDK9 支持私有方法。
  2. 函数式接口只能有一个抽象方法 ,注解@FunctionalInterface强制校验。
  3. Lambda 引用外层局部变量,变量必须是final或有效 final,不能二次修改。
  4. Lambda 中this指向外层宿主对象,不存在 Lambda 自身 this。
  5. Stream 流属于一次性容器,执行终止操作后流关闭,重复使用抛异常。
  6. peek设计仅用于调试打印,禁止执行业务数据修改逻辑。

五、集合容器核心规则(29~36)

  1. ArrayList底层数组,查询快增删慢,线程不安全;LinkedList双向链表,增删快查询慢。
  2. HashMapJDK8 底层数组 + 链表 + 红黑树,链表长度超 8 转红黑树,低于 6 退化为链表。
  3. HashMap存自定义对象必须重写equals()hashCode(),否则去重失效。
  4. Arrays.asList()返回数组视图,固定长度,调用 add/remove 抛不支持操作异常。
  5. 遍历集合时使用集合自身 add/remove 会触发ConcurrentModificationException
  6. toMap()收集器 key 重复直接抛异常,必须传入第三个参数处理冲突 key。
  7. subList()只是原集合视图,不会创建新集合,clear 仅清空分片不释放原数据。
  8. 不可变集合List.of()/toUnmodifiableList不支持增删改,修改直接报错。

六、并发、线程、锁、ThreadLocal(37~42)

  1. parallelStream共用全局 ForkJoin 池,IO 阻塞任务会拖垮全局所有并行流。
  2. 禁止手动new Thread创建线程,统一使用线程池管理,避免线程无限膨胀。
  3. ThreadLocal线程私有,线程池场景使用后必须remove(),防止内存泄漏与数据串线。
  4. volatile仅保证可见性、禁止指令重排,不保证原子性,不能用于计数自增。
  5. synchronized锁对象 / 类;Lock手动锁必须放在try-finally中释放,防止死锁。
  6. 多线程操作ArrayList/HashMap非线程安全容器,会出现数据丢失、并发修改异常。

七、空指针、Optional、判空规范(43~46)

  1. Optional.of(null)直接 NPE;空对象使用Optional.ofNullable()
  2. Optional.get()无值抛异常,业务禁止裸调用,优先orElse/orElseGet/orElseThrow
  3. orElse无论对象是否为空都会执行入参方法;orElseGet仅为空时执行。
  4. 多层对象链式调用a.getB().getC()任意一层 null 直接空指针,建议分层判空。

八、内存、IO、异常、资源、编码规范(47~50)

  1. 文件流、网络流必须使用try-with-resources自动关闭,避免句柄泄漏。
  2. 捕获异常禁止只打印e.getMessage(),必须打印完整堆栈log.error("msg",e)
  3. 超大数据集必须分页 / 分片处理,一次性加载全量集合极易引发 OOM 堆溢出。
  4. 循环内重复创建 Lambda、大对象会频繁触发 GC,可复用的逻辑提取为静态常量。