掌上先机 Java 一面

掌上先机 · Java 开发 · 一面 · 2026-04

面试题目

开场

  • 自我介绍

Java 基础

  • 基本类型有几个?
  • String 类设置成常量(final)有什么好处?
  • StringhashCode 会被计算几次?
  • 为什么 Java 不能多继承?

类加载

  • new 一个 Java 类的类加载过程是怎样的?

集合

  • HashMap 底层数据结构是什么?
  • HashMap 的扩容算法是怎样的?
  • 为什么负载因子是 0.75?设置成 0.7 或 0.8 会有什么问题?

面向对象

  • 面向对象三要素是什么?请简单介绍。

反问

  • 反问环节

参考解析

Java 基本类型有几个?

8 种byteshortintlongfloatdoublecharboolean。 对应包装类分别为 Byte、Short、Integer、Long、Float、Double、Character、Boolean。

String 设置成 final(常量)有什么好处?

  1. 安全性:字符串不可变,防止被子类篡改,适合作为 HashMap 的 key 和类加载参数。
  2. 线程安全:不可变对象天然线程安全,无需同步。
  3. 字符串常量池:相同内容的字符串可复用同一对象,节省内存。
  4. hashCode 可缓存:内容不变,hash 值只需计算一次。

StringhashCode 计算几次?

最多计算一次String 内部有 hash 字段缓存结果,第一次调用 hashCode() 时计算并缓存,后续直接返回缓存值(但需注意 hash 值恰好为 0 时会重复计算,属于已知的小缺陷)。

为什么 Java 不能多继承?

主要是为了避免菱形继承(Diamond Problem):若类 C 同时继承 A 和 B,而 A、B 都重写了同一方法,编译器无法确定调用哪个版本,产生二义性。Java 通过接口(interface)+ 默认方法(default)的方式在一定程度上支持多继承行为,同时要求显式解决冲突。

new 一个对象的类加载过程

  1. 加载:ClassLoader 找到 .class 文件,读入字节码,生成 Class 对象。
  2. 验证:校验字节码格式与安全性。
  3. 准备:为静态变量分配内存并赋默认值。
  4. 解析:将符号引用替换为直接引用。
  5. 初始化:执行静态代码块和静态变量赋值。
  6. 实例化:在堆中分配内存 → 执行构造方法 → 返回引用。

HashMap 底层数据结构

JDK 8 中为 数组 + 链表 + 红黑树

  • 数组(Node[])存储桶;
  • 同一桶内冲突元素用链表连接;
  • 链表长度 ≥ 8 且数组长度 ≥ 64 时,链表转为红黑树,提升查询效率至 O(log n)。

HashMap 扩容算法

  • 触发条件:元素数量超过 capacity × loadFactor
  • 新容量 = 旧容量 × 2(始终保持 2 的幂次)。
  • 重新散列:利用 (newCap - 1) & hash,原链表节点要么留在原位,要么移动到 原索引 + 旧容量 处,无需重新计算 hash,效率高。

负载因子为什么是 0.75?

这是空间与时间的折中

  • 过小(如 0.7):触发扩容更频繁,内存占用高,浪费空间。
  • 过大(如 0.8):桶内冲突增多,链表/红黑树变长,查询性能下降。
  • 0.75 在泊松分布下,桶中碰撞概率较低(长度 ≥ 8 的概率约为千万分之六),是工程实践中的最优经验值。

面向对象三要素

  1. 封装:隐藏内部实现,通过公开接口访问,提高安全性和可维护性。
  2. 继承:子类复用父类属性和方法,实现代码复用与扩展。
  3. 多态:同一接口/方法在不同对象上表现不同行为(编译时多态:重载;运行时多态:重写+向上转型)。