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

20 阅读2分钟

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

严肃的面试官坐在办公桌后,面前放着求职者王铁牛的简历。王铁牛紧张地坐在对面,双手不自觉地捏着衣角。

第一轮提问 面试官:首先问几个 Java 核心知识的问题。Java 中基本数据类型有哪些? 王铁牛:这个我知道,有 byte、short、int、long、float、double、char、boolean。 面试官:回答正确。那 Java 中多态的实现方式有哪些? 王铁牛:多态的实现方式主要有继承和接口,通过父类引用指向子类对象,或者接口引用指向实现类对象。 面试官:非常棒。那在 Java 里,什么是自动装箱和自动拆箱? 王铁牛:自动装箱就是把基本数据类型自动转换为对应的包装类对象,自动拆箱则相反,是把包装类对象自动转换为基本数据类型。

第二轮提问 面试官:接下来聊聊 JUC 和多线程。JUC 包是什么,有什么作用? 王铁牛:JUC 是 java.util.concurrent 包,它提供了很多用于多线程编程的工具类,能帮助我们更方便地进行并发编程。 面试官:不错。那线程池有哪些创建方式? 王铁牛:可以通过 Executors 工具类创建,像 newFixedThreadPool、newCachedThreadPool 这些,也可以通过 ThreadPoolExecutor 手动创建。 面试官:很好。那线程池的核心参数有哪些,分别代表什么意思? 王铁牛:呃……这个……好像有核心线程数、最大线程数,其他的我有点记不清了。

第三轮提问 面试官:现在来谈谈一些框架和中间件。Spring 的核心特性有哪些? 王铁牛:Spring 的核心特性有 IoC(控制反转)和 AOP(面向切面编程)。IoC 是把对象的创建和管理交给 Spring 容器,AOP 是在不修改源代码的情况下对程序进行增强。 面试官:回答得挺好。那 Spring Boot 有什么优点? 王铁牛:Spring Boot 可以快速搭建项目,简化配置,有内置的服务器,还能自动配置。 面试官:不错。那 MyBatis 中 #{} 和 ${} 的区别是什么? 王铁牛:这个……我不太确定,好像和 SQL 注入有关,但具体我也说不清楚。

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

答案详解

  1. Java 基本数据类型
    • Java 有 8 种基本数据类型,分为 4 类。整数类型:byte(1 字节)、short(2 字节)、int(4 字节)、long(8 字节);浮点类型:float(4 字节)、double(8 字节);字符类型:char(2 字节);布尔类型:boolean(理论上 1 位,但实际实现可能是 1 字节)。这些基本数据类型用于存储不同类型的数据,是 Java 编程的基础。
  2. Java 多态的实现方式
    • 继承:通过创建子类继承父类,父类引用可以指向子类对象。例如:
class Animal {
    public void eat() {
        System.out.println("Animal is eating");
    }
}
class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("Dog is eating");
    }
}
// 使用
Animal animal = new Dog();
animal.eat(); 
- **接口**:实现接口的类可以通过接口引用指向该类对象。例如:
interface Shape {
    void draw();
}
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}
// 使用
Shape shape = new Circle();
shape.draw(); 
  1. 自动装箱和自动拆箱
    • 自动装箱:把基本数据类型自动转换为对应的包装类对象。例如:
Integer i = 10; // 自动装箱,相当于 Integer i = Integer.valueOf(10);
- **自动拆箱**:把包装类对象自动转换为基本数据类型。例如:
Integer i = 10;
int j = i; // 自动拆箱,相当于 int j = i.intValue();
  1. JUC 包
    • java.util.concurrent 包是 Java 并发编程的核心包,提供了很多用于多线程编程的工具类和接口。比如:
      • 线程池相关类:Executors、ThreadPoolExecutor 等,用于管理线程的创建和执行。
      • 并发集合类:ConcurrentHashMap、CopyOnWriteArrayList 等,这些集合类在多线程环境下是线程安全的。
      • 锁相关类:ReentrantLock、ReentrantReadWriteLock 等,用于实现线程同步。
  2. 线程池的创建方式
    • 通过 Executors 工具类创建
      • newFixedThreadPool:创建一个固定大小的线程池,核心线程数和最大线程数相同。例如:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
    - **newCachedThreadPool**:创建一个可缓存的线程池,线程数会根据任务量自动调整。例如:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
- **通过 ThreadPoolExecutor 手动创建**:可以更灵活地配置线程池的参数。例如:
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
    2, // 核心线程数
    5, // 最大线程数
    60L, // 线程空闲时间
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(10) // 任务队列
);
  1. 线程池的核心参数
    • corePoolSize:核心线程数,线程池会一直保持这些线程存活,即使它们处于空闲状态。
    • maximumPoolSize:最大线程数,线程池允许创建的最大线程数量。
    • keepAliveTime:线程空闲时间,当线程空闲时间超过这个值时,会被销毁,除非线程数小于核心线程数。
    • unit:keepAliveTime 的时间单位,如 TimeUnit.SECONDS。
    • workQueue:任务队列,用于存储等待执行的任务。常见的有 LinkedBlockingQueue、ArrayBlockingQueue 等。
    • threadFactory:线程工厂,用于创建线程。
    • handler:任务拒绝策略,当任务队列满且线程数达到最大线程数时,如何处理新提交的任务。常见的拒绝策略有 AbortPolicy(直接抛出异常)、CallerRunsPolicy(由调用线程处理)等。
  2. Spring 的核心特性
    • IoC(控制反转):传统的程序中,对象的创建和管理由程序自己负责,而在 Spring 中,对象的创建和管理交给了 Spring 容器。通过依赖注入(DI)的方式,将对象的依赖关系注入到对象中。例如:
// 定义一个服务类
public class UserService {
    private UserDao userDao;
    // 通过构造函数注入依赖
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
}
// 在 Spring 配置文件或使用注解配置
- **AOP(面向切面编程)**:在不修改源代码的情况下,对程序进行增强。例如,在方法执行前后添加日志记录、事务管理等功能。可以通过定义切面(Aspect)、切点(Pointcut)和通知(Advice)来实现。

8. Spring Boot 的优点: - 快速搭建项目:通过 Spring Initializr 可以快速生成项目骨架,减少了手动配置的时间。 - 简化配置:Spring Boot 提供了自动配置功能,根据项目的依赖自动配置 Spring 应用,减少了大量的配置文件。 - 内置服务器:内置了 Tomcat、Jetty 等服务器,无需额外配置服务器即可运行项目。 - 生产就绪:提供了监控、健康检查等功能,方便在生产环境中管理和维护应用。 9. MyBatis 中 #{} 和 ${} 的区别: - #{}:是预编译处理,MyBatis 会将 #{} 替换为占位符 ?,在执行 SQL 时会使用 PreparedStatement 进行参数绑定,能有效防止 SQL 注入。例如:

<select id="getUserById" parameterType="int" resultType="User">
    SELECT * FROM users WHERE id = #{id}
</select>
- **${}**:是字符串替换,MyBatis 会直接将 ${} 替换为实际的值,存在 SQL 注入风险。例如:
<select id="getUserByUsername" parameterType="String" resultType="User">
    SELECT * FROM users WHERE username = '${username}'
</select>

所以在实际开发中,尽量使用 #{} 进行参数传递。