《互联网大厂 Java 面试:核心知识、框架与中间件大考验》

71 阅读2分钟

互联网大厂 Java 面试:核心知识、框架与中间件大考验

王铁牛怀揣着对互联网大厂的向往,走进了面试室。严肃的面试官坐在对面,一场激烈的技术交锋即将开始。

第一轮面试

面试官:我们先从 Java 核心知识开始。Java 中基本数据类型有哪些? 王铁牛:Java 的基本数据类型有 byte、short、int、long、float、double、char、boolean。 面试官:不错,回答得很准确。那 String 是基本数据类型吗,为什么? 王铁牛:String 不是基本数据类型,它是一个类。因为基本数据类型是 Java 语言预先定义好的简单数据类型,而 String 类提供了很多方法来操作字符串。 面试官:很好。那说说 Java 中重载和重写的区别。 王铁牛:重载是指在一个类中,方法名相同但参数列表不同;重写是指子类重写父类的方法,方法名、参数列表和返回值类型都要相同,访问权限不能比父类的小。

第二轮面试

面试官:接下来聊聊 JUC 和多线程。什么是线程安全? 王铁牛:线程安全就是当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是线程安全的。 面试官:那 JUC 包中常用的线程安全的集合有哪些? 王铁牛:有 CopyOnWriteArrayList、ConcurrentHashMap 等。 面试官:不错。那说一下线程池的工作原理。 王铁牛:嗯……就是有一堆线程在那等着任务,来了任务就执行,差不多就是这样吧。

第三轮面试

面试官:现在谈谈框架相关的。Spring 中 Bean 的作用域有哪些? 王铁牛:有 singleton、prototype、request、session 等。 面试官:那 Spring Boot 有什么优点? 王铁牛:它可以快速搭建项目,减少了很多配置,提高了开发效率。 面试官:那 MyBatis 中 #{} 和 ${} 的区别是什么? 王铁牛:这个……好像一个是占位符,一个是拼接,具体的我有点记不清了。

面试官扶了扶眼镜,说道:“今天的面试就到这里,你先回家等通知吧。我们会综合评估后尽快给你答复。”

答案解析

  1. Java 基本数据类型:Java 中有 8 种基本数据类型,分为 4 类。整数类型:byte(1 字节)、short(2 字节)、int(4 字节)、long(8 字节);浮点类型:float(4 字节)、double(8 字节);字符类型:char(2 字节);布尔类型:boolean(1 位)。基本数据类型是 Java 语言预先定义好的简单数据类型,存储的是具体的值。
  2. String 不是基本数据类型:String 是一个类,位于 java.lang 包下。它用于表示字符串,提供了很多方法来操作字符串,如 length()、substring() 等。与基本数据类型不同,String 对象是通过引用传递的。
  3. 重载和重写的区别
    • 重载(Overloading):发生在同一个类中,方法名相同但参数列表不同(参数的类型、个数、顺序不同)。重载与方法的返回值类型、访问修饰符无关。例如:
public class OverloadExample {
    public int add(int a, int b) {
        return a + b;
    }
    public double add(double a, double b) {
        return a + b;
    }
}
- 重写(Overriding):发生在子类和父类之间,子类重写父类的方法。方法名、参数列表和返回值类型都要相同(返回值类型在 Java 5 及以后可以是协变类型),访问权限不能比父类的小,不能抛出比父类更多的异常。例如:
class Parent {
    public void print() {
        System.out.println("Parent");
    }
}
class Child extends Parent {
    @Override
    public void print() {
        System.out.println("Child");
    }
}
  1. 线程安全:当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是线程安全的。例如,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的。
  2. JUC 包中常用的线程安全的集合
    • CopyOnWriteArrayList:是 ArrayList 的线程安全版本,它在进行写操作(如 add、remove 等)时会创建一个新的数组副本,读操作则可以并发进行,适合读多写少的场景。
    • ConcurrentHashMap:是 HashMap 的线程安全版本,采用分段锁或 CAS 等机制来保证并发性能,在多线程环境下可以高效地进行读写操作。
  3. 线程池的工作原理
    • 线程池主要由线程池管理器、工作线程、任务队列和任务拒绝策略组成。当提交一个任务到线程池时,线程池的处理流程如下:
      • 线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下一步。
      • 线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下一步。
      • 线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给任务拒绝策略来处理这个任务。
  4. Spring 中 Bean 的作用域
    • singleton:单例模式,Spring IoC 容器中只会存在一个共享的 Bean 实例,所有对 Bean 的请求,只要 id 与该 Bean 定义相匹配,则只会返回 Bean 的同一实例。
    • prototype:原型模式,每次对该 Bean 的请求都会创建一个新的实例。
    • request:在一次 HTTP 请求中,一个 Bean 定义对应一个实例,即每个 HTTP 请求都会有各自的 Bean 实例,它们依据某个 HTTP 请求而创建,当请求结束后,该 Bean 实例将会被销毁。
    • session:在一个 HTTP Session 中,一个 Bean 定义对应一个实例。
  5. Spring Boot 的优点
    • 快速搭建项目:Spring Boot 提供了大量的 Starter 依赖,通过添加相应的 Starter 依赖,就可以快速集成各种功能,减少了手动配置的工作量。
    • 自动配置:Spring Boot 会根据项目中添加的依赖自动进行配置,开发者可以根据需要进行定制化配置。
    • 内嵌服务器:Spring Boot 内嵌了 Tomcat、Jetty 等服务器,无需额外部署服务器,直接运行项目即可。
    • 监控和管理:Spring Boot Actuator 提供了丰富的监控和管理功能,如健康检查、性能指标监控等。
  6. MyBatis 中 #{} 和 ${} 的区别
    • #{}:是占位符,MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为? 号,然后使用 PreparedStatement 的 set 方法来设置参数值,这样可以有效防止 SQL 注入。例如:
<select id="selectUserById" parameterType="int" resultType="User">
    SELECT * FROM users WHERE id = #{id}
</select>
- ${}:是字符串替换,MyBatis 在处理 ${} 时,会直接将 ${} 替换为参数的值,可能会导致 SQL 注入问题。例如:
<select id="selectUserByColumnName" parameterType="String" resultType="User">
    SELECT * FROM users WHERE ${columnName} = 'value'
</select>

一般情况下,优先使用 #{},只有在需要动态传入表名、列名等场景下才使用 ${}。