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

59 阅读10分钟

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

严肃的面试官坐在桌前,面前放着王铁牛的简历。王铁牛有些紧张地走进面试房间,坐下后,面试开始了。

第一轮提问 面试官:首先问几个 Java 核心知识的问题。Java 中基本数据类型有哪些? 王铁牛:嗯,有 byte、short、int、long、float、double、char、boolean。 面试官:回答正确,很不错。那在 Java 里,什么是多态? 王铁牛:多态就是一个对象有多种形态,父类引用可以指向子类对象,调用方法时会根据实际的对象类型来执行相应的方法。 面试官:非常好。那说说 HashMap 和 Hashtable 的区别。 王铁牛:HashMap 是非线程安全的,允许 null 键和 null 值;Hashtable 是线程安全的,不允许 null 键和 null 值。

第二轮提问 面试官:进入 JUC 和多线程相关的问题。JUC 包是什么,有什么作用? 王铁牛:JUC 就是 java.util.concurrent 包,它提供了很多并发编程相关的工具类和接口,能方便我们进行多线程编程。 面试官:不错。那什么是线程池,为什么要使用线程池? 王铁牛:线程池就是预先创建好一定数量的线程,当有任务提交时,从线程池中获取线程来执行任务。使用线程池可以减少线程创建和销毁的开销,提高系统性能。 面试官:很好。那说说线程池的几种状态。 王铁牛:呃……这个我有点不太确定,好像有运行中,还有其他的我就不太清楚了。

第三轮提问 面试官:现在问一些框架和中间件的问题。Spring 框架的核心特性有哪些? 王铁牛:Spring 的核心特性有 IoC(控制反转)和 AOP(面向切面编程)。IoC 就是把对象的创建和依赖关系的管理交给 Spring 容器,AOP 可以在不修改原有代码的基础上增加额外的功能。 面试官:回答得很准确。那 Spring Boot 有什么优势? 王铁牛:Spring Boot 可以快速搭建 Spring 应用,它有自动配置的功能,能减少很多配置文件的编写。 面试官:很好。那 MyBatis 是如何实现数据库操作的? 王铁牛:这个……我记得是通过映射文件或者注解来定义 SQL 语句,然后和 Java 对象进行映射,但是具体细节我有点说不清楚。

面试官扶了扶眼镜,说道:“今天的面试就到这里,你整体对一些基础的知识掌握得还可以,在简单问题上回答得不错,说明有一定的知识储备。不过在一些复杂问题上,像线程池的状态和 MyBatis 具体实现细节,回答得不够完整和清晰,还需要进一步加强学习。你先回家等通知吧,我们后续会综合评估后给你答复。”

问题答案

  1. Java 中基本数据类型有哪些? Java 中的基本数据类型分为四大类:
  • 整数类型
    • byte:8 位,有符号,取值范围 -128 到 127。
    • short:16 位,有符号,取值范围 -32768 到 32767。
    • int:32 位,有符号,取值范围 -2147483648 到 2147483647。
    • long:64 位,有符号,取值范围 -9223372036854775808 到 9223372036854775807,定义时需要在数字后面加“L”。
  • 浮点类型
    • float:32 位,单精度浮点数,定义时需要在数字后面加“F”。
    • double:64 位,双精度浮点数,是 Java 中默认的浮点类型。
  • 字符类型
    • char:16 位,无符号,用于表示单个字符,使用单引号括起来,例如 'A'。
  • 布尔类型
    • boolean:只有两个值,true 和 false,用于逻辑判断。
  1. 在 Java 里,什么是多态? 多态是面向对象编程的重要特性之一,它允许不同的对象对同一消息做出不同的响应。在 Java 中,多态主要通过以下两种方式实现:
  • 方法重载(Overloading):在同一个类中,多个方法可以有相同的方法名,但参数列表不同(参数的类型、个数或顺序不同)。调用时,编译器会根据传入的参数来选择合适的方法执行。例如:
public class OverloadingExample {
    public int add(int a, int b) {
        return a + b;
    }
    public double add(double a, double b) {
        return a + b;
    }
}
  • 方法重写(Overriding)和父类引用指向子类对象:子类可以重写父类的方法,当父类引用指向子类对象时,调用重写的方法会执行子类中的实现。例如:
class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}
class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}
public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();
        animal.sound(); // 输出 "Dog barks"
    }
}
  1. 说说 HashMap 和 Hashtable 的区别。
  • 线程安全性
    • HashMap:是非线程安全的,在多线程环境下,如果多个线程同时对 HashMap 进行读写操作,可能会导致数据不一致或者抛出 ConcurrentModificationException 异常。
    • Hashtable:是线程安全的,它的方法都使用了 synchronized 关键字进行同步,所以在多线程环境下可以保证数据的一致性,但这也导致了它的性能相对较低。
  • 对 null 的支持
    • HashMap:允许键和值都为 null,不过只能有一个 null 键,但可以有多个 null 值。
    • Hashtable:不允许键和值为 null,如果尝试插入 null 键或 null 值,会抛出 NullPointerException 异常。
  • 继承和实现
    • HashMap:继承自 AbstractMap 类,实现了 Map 接口。
    • Hashtable:继承自 Dictionary 类,也实现了 Map 接口。
  1. JUC 包是什么,有什么作用? JUC 即 java.util.concurrent 包,是 Java 5 引入的一个用于并发编程的工具包。它提供了一系列高级的并发编程工具和类,主要作用如下:
  • 线程池:提供了 ThreadPoolExecutor、ScheduledThreadPoolExecutor 等线程池实现,方便管理和复用线程,提高系统性能。
  • 锁机制:如 ReentrantLock、ReentrantReadWriteLock 等,比传统的 synchronized 关键字更加灵活,支持公平锁、可重入锁等特性。
  • 并发集合:如 ConcurrentHashMap、CopyOnWriteArrayList 等,这些集合在多线程环境下是线程安全的,并且具有较高的并发性能。
  • 同步器:如 CountDownLatch、CyclicBarrier、Semaphore 等,用于协调多个线程之间的执行顺序和资源共享。
  • 原子类:如 AtomicInteger、AtomicLong 等,提供了一些原子操作,避免了多线程环境下的竞态条件。
  1. 什么是线程池,为什么要使用线程池? 线程池是一种管理线程的机制,它预先创建一定数量的线程,当有任务提交时,从线程池中获取线程来执行任务,任务执行完后线程不会销毁,而是返回到线程池中等待下一个任务。使用线程池的原因主要有以下几点:
  • 减少线程创建和销毁的开销:创建和销毁线程是一个比较耗时和耗资源的操作,线程池可以复用线程,避免了频繁创建和销毁线程带来的性能损耗。
  • 提高响应速度:当有任务提交时,线程池中如果有空闲线程,就可以立即执行任务,而不需要等待新线程的创建。
  • 控制并发线程数量:通过设置线程池的大小,可以控制同时执行的线程数量,避免过多线程导致系统资源耗尽。
  • 便于管理:线程池可以统一管理线程的生命周期、监控线程的状态等。
  1. 说说线程池的几种状态。 线程池有以下几种状态:
  • RUNNING:线程池的初始状态,接受新任务并处理队列中的任务。
  • SHUTDOWN:调用 shutdown() 方法后进入此状态,不再接受新任务,但会继续处理队列中的任务。
  • STOP:调用 shutdownNow() 方法后进入此状态,不再接受新任务,也不处理队列中的任务,并且会尝试中断正在执行的任务。
  • TIDYING:当所有任务都已终止,并且工作线程数量为 0 时,线程池进入此状态,会执行 terminated() 方法。
  • TERMINATED:terminated() 方法执行完毕后,线程池进入此状态,表示线程池已经完全终止。
  1. Spring 框架的核心特性有哪些? Spring 框架的核心特性主要有 IoC(控制反转)和 AOP(面向切面编程):
  • IoC(控制反转):也称为依赖注入(DI),是一种设计模式,它将对象的创建和依赖关系的管理从代码中分离出来,交给 Spring 容器来完成。通过 IoC,对象之间的耦合度降低,代码的可维护性和可测试性提高。例如,一个类依赖另一个类的实例,传统方式是在类内部创建该实例,而在 Spring 中,可以通过配置文件或注解将该实例注入到类中。
  • AOP(面向切面编程):是一种编程范式,它允许在不修改原有代码的基础上,对程序的某些部分进行增强。AOP 主要用于处理一些横切关注点,如日志记录、事务管理、权限验证等。在 Spring 中,通过定义切面、切点和通知来实现 AOP 功能。
  1. Spring Boot 有什么优势? Spring Boot 是基于 Spring 框架的快速开发框架,它的优势主要有以下几点:
  • 快速搭建项目:Spring Boot 提供了很多 Starter 依赖,通过添加相应的 Starter 依赖,就可以快速集成各种功能,如 Web 开发、数据库访问等,减少了繁琐的配置过程。
  • 自动配置:Spring Boot 会根据项目中添加的依赖和配置,自动进行一些默认的配置,开发者只需要根据需要进行少量的配置即可。例如,添加了 Spring Boot 的 Web Starter 依赖后,Spring Boot 会自动配置嵌入式的 Tomcat 服务器。
  • 内嵌服务器:Spring Boot 支持内嵌 Tomcat、Jetty 等服务器,不需要单独部署服务器,直接运行项目的主类就可以启动应用。
  • 生产就绪:Spring Boot 提供了很多生产环境下的特性,如健康检查、监控、日志管理等,方便开发者对应用进行管理和维护。
  • 微服务支持:Spring Boot 是构建微服务的理想选择,它可以和 Spring Cloud 等框架结合,快速构建分布式系统。
  1. MyBatis 是如何实现数据库操作的? MyBatis 是一个优秀的持久层框架,它实现数据库操作的主要步骤如下:
  • 配置文件
    • 核心配置文件:通常是 mybatis-config.xml,用于配置数据源、事务管理器等全局信息。
    • 映射文件:用于定义 SQL 语句和 Java 对象之间的映射关系,通常以 .xml 结尾。例如:
<mapper namespace="com.example.mapper.UserMapper">
    <select id="getUserById" parameterType="int" resultType="com.example.entity.User">
        SELECT * FROM users WHERE id = #{id}
    </select>
</mapper>
  • 创建 SqlSessionFactory:通过读取核心配置文件,创建 SqlSessionFactory 对象,它是 MyBatis 的核心工厂类,用于创建 SqlSession 对象。
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  • 获取 SqlSession:通过 SqlSessionFactory 创建 SqlSession 对象,它是一个会话对象,用于执行 SQL 语句。
SqlSession session = sqlSessionFactory.openSession();
  • 执行 SQL 语句:可以通过 SqlSession 的方法执行映射文件中定义的 SQL 语句,也可以使用注解的方式定义 SQL 语句。
User user = session.selectOne("com.example.mapper.UserMapper.getUserById", 1);
  • 关闭 SqlSession:操作完成后,需要关闭 SqlSession 对象,释放资源。
session.close();