1. 简介

这篇文章整理了一些 Java 核心知识点中常见的面试问题及其答案。部分问题的答案可能不是显而易见的,因此通过这篇文章可以帮你厘清思路、加深理解。

2. 初级 Java 面试问题

2.1. Java 中的数据是按引用传递还是按值传递?

虽然这个问题的答案很简单,但对初学者来说可能会有些困惑。我们先明确一下两个概念:

  • 按值传递(Pass by value):传递的是对象的副本
  • 按引用传递(Pass by reference):传递的是对象的引用

在 Java 中,不管是基本类型还是对象引用,传递的都是值的副本

  • 对于基本类型:传递的是值的拷贝;
  • 对于对象:传递的是引用的拷贝(但不是对象本身)。

📌 结论:Java 是严格按值传递的语言。

想深入了解?可以看看这篇文章:Java 中的参数传递机制

2.2. import 与 static import 的区别

  • import 用于导入某个类或整个包:
import java.util.ArrayList; // 导入特定类
import java.util.*;         // 导入整个包
  • static import 用于导入静态成员或嵌套类:
import static java.util.Collections.EMPTY_LIST;

使用 static import 后,可以直接使用 EMPTY_LIST,而无需加上类名前缀。

2.3. Java 中有哪些访问修饰符?它们的作用是什么?

Java 中有四种访问修饰符:

  1. private:仅类内部可访问;
  2. default(包访问):仅同一包内可访问;
  3. protected:同包或子类可访问;
  4. public:所有地方都可访问。

⚠️ 注意:default 不是关键字,只是不写访问修饰符时的默认行为。

2.4. Java 中还有哪些其他修饰符?它们的作用是什么?

除了访问修饰符,还有以下五种常用修饰符:

  • static:属于类而非实例;
  • final:不可变或不可继承;
  • abstract:用于抽象类或方法;
  • synchronized:用于同步控制;
  • volatile:保证变量的可见性。

这些修饰符不控制访问权限,而是用于控制类、方法或变量的行为。

2.5. JDK、JRE 和 JVM 的区别

名称 全称 作用
JDK Java Development Kit 开发工具包,包含编译器、调试器等
JRE Java Runtime Environment 运行 Java 程序所需的最小环境
JVM Java Virtual Machine 执行字节码的虚拟机

📌 JDK 包含 JRE,JRE 包含 JVM。

2.6. 栈(Stack)和堆(Heap)的区别

  • :存储局部变量和方法调用信息,速度快,但空间有限。栈溢出时会抛出 StackOverflowError
  • :存储所有对象实例,由垃圾回收器管理。内存不足时会抛出 OutOfMemoryError

2.7. Comparable 与 Comparator 的区别

  • Comparable:类内部实现排序逻辑,使用 compareTo() 方法;
  • Comparator:外部定义排序规则,适用于第三方类或多种排序方式。

📌 compareTo()compare() 方法最好与 equals() 保持一致。

2.8. void 类型的作用

  • void 表示方法不返回值;
  • Void 是一个占位类,用于泛型场景,不能实例化。

2.9. Object 类有哪些方法?

方法 作用
clone() 复制对象
equals() 判断相等
finalize() 垃圾回收前调用
getClass() 获取运行时类
hashCode() 获取哈希码
notify() / notifyAll() 唤醒等待线程
toString() 字符串表示
wait() 线程等待

📌 hashCode() 应与 equals() 保持一致。

2.10. 什么是 Enum?如何使用?

  • enum 是一种特殊类,用于定义一组常量;
  • 可以包含属性、方法;
  • 不能被继承,但可以实现接口;
  • 线程安全,常用于单例模式。

示例:

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}

2.11. 什么是 JAR 文件?

JAR(Java Archive)是基于 ZIP 格式的归档文件,用于打包 Java 类文件和资源文件。支持:

  • ✅ 安全签名
  • ✅ 数据压缩
  • ✅ 跨平台使用
  • ✅ 版本控制

2.12. 什么是 NullPointerException?

NullPointerException 是最常见的运行时异常,出现在以下情况:

  • 调用 null 对象的方法;
  • 访问 null 对象的字段;
  • 获取 null 数组长度;
  • 抛出 null。

📌 不要手动捕获它,应该从源头避免。

2.13. Java 中的两种类型转换?可能抛出什么异常?如何避免?

  • 向上转型(Upcasting):安全,自动进行;
  • 向下转型(Downcasting):需手动转换,可能抛出 ClassCastException

✅ 使用 instanceof 判断避免异常:

if (obj instanceof String) {
    String str = (String) obj;
}

3. 高级 Java 面试问题

3.1. 为什么 String 是不可变的?

  • 存储在字符串常量池中,节省内存;
  • 保证哈希值不变,适合做 Map 的 key;
  • 线程安全;
  • 防止敏感信息被篡改。

📌 不可变对象天生线程安全,是设计上的经典实践。

3.2. 动态绑定与静态绑定的区别

  • 静态绑定:发生在编译时,适用于 privatestaticfinal 方法;
  • 动态绑定:发生在运行时,适用于重写方法。

📌 Java 默认使用动态绑定来支持多态。

3.3. 什么是 JIT?

JIT(Just-In-Time)是 JVM 中的即时编译器,在运行时将热点代码编译为本地机器码,以提升性能。

  • 编译热点代码;
  • 优化 CPU 指令;
  • 基于运行时数据进行优化。

📌 JIT 是 Java 高性能的关键之一。

3.4. Java 中的反射机制

反射允许程序在运行时检查或修改类的结构和行为。使用 java.lang.reflect 包。

  • 可访问私有成员;
  • 不需要知道类名;
  • 有安全限制(Java 9+ 模块化后更严格)。

📌 反射虽强大,但影响性能,慎用。

3.5. 什么是类加载器(Classloader)?

类加载器负责将 .class 文件加载到 JVM 中。Java 提供三种默认类加载器:

  1. Bootstrap Classloader:加载核心类(如 java.lang.*);
  2. Extension Classloader:加载扩展类;
  3. System Classloader:加载应用类路径下的类。

📌 类加载器遵循“双亲委派模型”。

3.6. 静态类加载与动态类加载的区别

  • 静态加载:使用 new 关键字;
  • 动态加载:使用 Class.forName() 在运行时加载类。

📌 动态加载常用于插件机制、JDBC 驱动加载等场景。

3.7. Serializable 接口的作用

实现 Serializable 接口可使类支持序列化:

  • 序列化:将对象转为字节流;
  • 反序列化:从字节流恢复对象。

📌 子类自动可序列化,但父类若未实现需提供无参构造函数。

3.8. Java 中有析构函数吗?

Java 没有传统意义上的析构函数,因为垃圾回收器会自动回收内存。

  • 对于资源(如文件、连接):应使用 close() 方法;
  • Java 7+ 推荐使用 try-with-resources
  • Java 9+ 使用 Cleaner 替代 finalize()

⚠️ finalize() 不可靠,不推荐使用。


原始标题:Java Interview Questions