Java 工程师面试题 + 参考答案2026年大厂题目 Java 工程师面试题 + 参考答案──────────────────────────────────────────────────1. JDK、JRE、JVM 分别是什么?三者有什么关系?参考答案:JVM是 Java 虚拟机,负责执行字节码文件。JRE是 Java 运行环境,包含JVM和运行 Java 程序所需的核心类库。JDK是 Java 开发工具包,包含JRE以及编译器、调试工具等开发工具。关系可以理解为:JDK包含JRE,JRE包含JVM。开发 Java 程序通常需要JDK,运行 Java 程序至少需要JRE。──────────────────────────────────────────────────2. Java 为什么能跨平台?参考答案:Java 程序先被编译成与平台无关的字节码,也就是.class文件。不同操作系统上只要安装了对应实现的JVM,就可以由JVM把同一份字节码翻译成当前平台能执行的机器指令。所以 Java 跨平台的核心不是源码直接跨平台,而是字节码 + 不同平台上的 JVM实现了跨平台运行。──────────────────────────────────────────────────3. 面向对象的三大特性是什么?参考答案:Java 面向对象的三大特性是:封装:把属性和行为封装到对象内部,对外只暴露必要接口,降低耦合。继承:子类可以复用父类已有的属性和方法,提高代码复用率。多态:同一个父类引用可以指向不同子类对象,调用同一方法时表现出不同实现。例如支付系统里可以定义一个PayService接口,不同支付方式实现自己的pay()方法,这就是多态的典型应用。──────────────────────────────────────────────────4.==和equals()有什么区别?参考答案:对于基本类型,==比较的是值是否相等。对于引用类型,==比较的是两个引用是否指向同一个对象。equals()用来比较对象逻辑上是否相等。在Object类中,equals()默认实现其实也是比较地址。但像String、Integer等类已经重写了equals(),比较的是内容。面试中要补一句:如果重写了equals(),通常也要一起重写hashCode(),否则在哈希容器中会出现行为不一致的问题。──────────────────────────────────────────────────5.hashCode()有什么作用?为什么重写equals()往往要重写hashCode()?参考答案:hashCode()主要用于哈希结构中快速定位元素,比如HashMap、HashSet。对象放入哈希容器时,通常先根据hashCode()找桶位,再用equals()比较是否为同一个逻辑对象。Java 约定中:如果两个对象通过equals()比较相等,那么它们的hashCode()必须相同。如果两个对象hashCode()相同,不代表它们一定相等。如果只重写equals()而不重写hashCode(),会导致逻辑相等的对象进入不同桶,出现HashSet去重失效或HashMap查询不到值的问题。──────────────────────────────────────────────────6.String、StringBuilder、StringBuffer有什么区别?参考答案:String是不可变类,每次拼接都会产生新对象。StringBuilder是可变字符序列,线程不安全,但性能较好。StringBuffer也是可变字符序列,方法大多带同步,线程安全,但性能相对低一些。一般来说:单线程字符串频繁拼接优先用StringBuilder多线程共享字符串缓冲区时才考虑StringBuffer少量固定字符串使用String即可──────────────────────────────────────────────────7. 为什么String设计成不可变?参考答案:String不可变主要有几个原因:安全性:字符串经常用于类加载、网络地址、文件路径等关键场景,不可变可以避免内容被篡改。线程安全:不可变对象天然线程安全,多线程共享时不需要额外同步。字符串常量池复用:相同字面量可以共享对象,节省内存。哈希值稳定:字符串常作为HashMap的键,不可变可以保证hashCode()不会变化。所以不可变带来了更好的安全性、可复用性和稳定性。──────────────────────────────────────────────────8.final、finally、finalize有什么区别?参考答案:final是关键字,可以修饰类、方法、变量。finally是异常处理中的代码块,通常用于释放资源。finalize()是Object的方法,对象被垃圾回收前可能被调用。补充说明:final修饰类表示不能被继承,修饰方法表示不能被重写,修饰变量表示只能赋值一次。finally不管是否发生异常,一般都会执行。finalize()机制不可预测,性能也不好,已经不推荐作为资源释放手段,通常改用try-with-resources。──────────────────────────────────────────────────9.abstract class和interface有什么区别?参考答案:抽象类更强调“是什么”,接口更强调“能做什么”。主要区别:抽象类可以有成员变量、构造方法、普通方法和抽象方法。接口主要用于定义规范,类可以实现多个接口,但只能继承一个抽象类或父类。接口更适合做能力扩展和解耦,抽象类更适合抽取公共状态和共用逻辑。如果多个子类之间有明显的公共属性和模板逻辑,通常用抽象类;如果只是约定行为,比如Runnable、Comparable,通常用接口。──────────────────────────────────────────────────10. 重载和重写有什么区别?参考答案:重载是方法名相同、参数列表不同,发生在同一个类中,返回值类型是否相同不是区分重载的依据。重写是子类对父类方法重新实现,方法名、参数列表要一致,返回值类型要兼容,访问权限不能更严格。重载体现的是编译期多态,重写体现的是运行期多态。──────────────────────────────────────────────────11. Java 的访问修饰符有哪些?参考答案:Java 常见访问修饰符有四种:private:只能在当前类中访问默认不写:同包可访问protected:同包可访问,不同包的子类也可访问public:任何地方都可访问访问范围从小到大是:private default protected public。──────────────────────────────────────────────────12. Java 中异常分哪几类?参考答案:Java 中所有异常和错误都继承自Throwable,主要分两大类:Error:系统级严重错误,程序通常无法处理,比如OutOfMemoryErrorException:程序运行过程中可处理的异常Exception又可以分为:受检异常:编译期要求显式处理,比如IOException运行时异常:编译期不强制处理,比如NullPointerException/