《互联网大厂 Java 面试:核心知识、框架与中间件的全方位考察》
在互联网大厂的一间明亮的面试室内,严肃的面试官正对面坐着略显紧张的王铁牛。一场关于 Java 技术的面试即将拉开帷幕。
第一轮面试开始
- 面试官:首先问你几个 Java 核心知识的问题。Java 中的基本数据类型有哪些?
- 王铁牛:这个我知道,有 byte、short、int、long、float、double、char、boolean。
- 面试官:不错,回答得很准确。那你说说 Java 中重载和重写的区别是什么?
- 王铁牛:重载是在同一个类中,方法名相同但参数列表不同;重写是子类重写父类的方法,方法名、参数列表和返回值类型都要相同。
- 面试官:很好,看来你对基础知识掌握得挺扎实。那在 Java 里,什么是多态?
- 王铁牛:多态就是一个对象可以有多种表现形式,比如父类的引用可以指向子类的对象,通过父类引用调用方法时会根据实际指向的子类对象来执行不同的方法。
- 面试官:非常棒,回答得很清晰。这一轮你表现得很不错。
第二轮面试开始
- 面试官:接下来我问一些关于 JUC、JVM 和多线程的问题。JUC 包下有哪些常用的类或工具?
- 王铁牛:嗯……有 CountDownLatch、CyclicBarrier,还有……还有啥来着,我有点记不清了。
- 面试官:先放一放这个问题。那说说 JVM 的内存结构是怎样的?
- 王铁牛:JVM 内存有堆、栈,还有……还有方法区,别的我就不太确定了。
- 面试官:再问你,多线程编程中,如何避免死锁?
- 王铁牛:这个嘛,我好像知道一点,就是要保证线程获取锁的顺序一致,但是具体怎么实现我有点迷糊。
- 面试官:这一轮你对部分问题回答得不够完整和准确,需要加强这方面的知识。
第三轮面试开始
- 面试官:现在问你关于一些框架和中间件的问题。Spring 框架的核心特性有哪些?
- 王铁牛:Spring 核心特性有 IOC 和 AOP,IOC 就是控制反转,把对象的创建和依赖关系的管理交给 Spring 容器;AOP 就是面向切面编程,能在不修改原有代码的基础上增加一些额外的功能。
- 面试官:回答得不错。那 Spring Boot 相比 Spring 有哪些优势?
- 王铁牛:Spring Boot 简化了 Spring 项目的配置,有自动配置功能,能快速搭建项目,还内置了服务器,开发起来更方便。
- 面试官:那说说 MyBatis 的工作原理。
- 王铁牛:MyBatis 就是通过配置文件或者注解来映射 SQL 语句,然后和数据库进行交互,具体的工作流程我不太能说清楚。
- 面试官:最后问你,Dubbo、RabbitMq、xxl - job、Redis 这些技术你在项目中有用过吗?简单说下它们的作用。
- 王铁牛:Dubbo 好像是做分布式服务调用的,RabbitMq 是消息队列,xxl - job 是分布式任务调度的,Redis 是缓存数据库,但是具体怎么用我就不太熟悉了。
面试结束 面试官扶了扶眼镜,看着王铁牛说:“今天的面试就到这里了。你对一些基础知识和部分框架的基本概念回答得还可以,说明有一定的 Java 基础。但在 JUC、JVM 以及一些框架和中间件的深入理解和实际应用方面还有所欠缺。我们需要综合考虑所有面试者的情况,你先回家等通知吧。”
问题答案
- Java 中的基本数据类型有哪些?
- Java 中有 8 种基本数据类型,分为 4 类:
- 整数类型:byte(1 字节,范围 -128 到 127)、short(2 字节)、int(4 字节)、long(8 字节)。
- 浮点类型:float(4 字节)、double(8 字节)。
- 字符类型:char(2 字节,用于表示单个字符)。
- 布尔类型:boolean(只有两个值 true 和 false)。
- Java 中有 8 种基本数据类型,分为 4 类:
- Java 中重载和重写的区别是什么?
- 重载(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)**:发生在子类和父类之间,子类重写父类的方法。方法名、参数列表和返回值类型必须相同(返回值类型可以是父类方法返回值类型的子类,称为协变返回类型),访问修饰符不能比父类的更严格。例如:
class Parent {
public void print() {
System.out.println("Parent method");
}
}
class Child extends Parent {
@Override
public void print() {
System.out.println("Child method");
}
}
- 在 Java 里,什么是多态?
- 多态是指同一个行为具有多个不同表现形式或形态的能力。在 Java 中多态主要通过以下两种方式实现:
- 继承和方法重写:子类重写父类的方法,父类的引用可以指向子类的对象。通过父类引用调用重写的方法时,会根据实际指向的子类对象来执行不同的方法。例如:
- 多态是指同一个行为具有多个不同表现形式或形态的能力。在 Java 中多态主要通过以下两种方式实现:
class Animal {
public void makeSound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof");
}
}
public class PolymorphismExample {
public static void main(String[] args) {
Animal animal = new Dog();
animal.makeSound(); // 输出 Woof
}
}
- **接口和实现类**:一个接口可以有多个实现类,接口的引用可以指向不同的实现类对象。
4. JUC 包下有哪些常用的类或工具? - CountDownLatch:一个同步辅助类,允许一个或多个线程等待其他线程完成操作。例如,主线程等待多个子线程完成任务后再继续执行。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
int threadCount = 3;
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
try {
// 模拟线程执行任务
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();
}
}).start();
}
latch.await();
System.out.println("All threads have completed their tasks.");
}
}
- **CyclicBarrier**:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点。与 CountDownLatch 不同的是,CyclicBarrier 可以重复使用。
- **Semaphore**:一个计数信号量,用于控制同时访问某个资源的线程数量。
- **ReentrantLock**:一个可重入的互斥锁,功能与 synchronized 类似,但更灵活。
5. JVM 的内存结构是怎样的? - 程序计数器(Program Counter Register):是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。每个线程都有一个独立的程序计数器。 - Java 虚拟机栈(Java Virtual Machine Stacks):每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧,每个栈帧对应一个方法的调用。栈帧中存储局部变量表、操作数栈、动态链接、方法出口等信息。 - 本地方法栈(Native Method Stacks):与虚拟机栈类似,不过它是为虚拟机使用到的本地(Native)方法服务。 - Java 堆(Java Heap):是 Java 虚拟机所管理的内存中最大的一块,所有对象实例和数组都在堆上分配。堆是垃圾收集器管理的主要区域,因此也被称为“GC 堆”。 - 方法区(Method Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。在 JDK 1.8 之前,方法区也被称为永久代,JDK 1.8 及以后使用元空间(Metaspace)来替代永久代。 6. 多线程编程中,如何避免死锁? - 破坏互斥条件:一般来说,互斥条件是无法破坏的,因为某些资源本身就具有互斥性。 - 破坏占有并等待条件:可以采用一次性申请所有资源的方法,即线程在开始执行前就申请它所需要的全部资源,如果无法获取全部资源,则等待直到所有资源都可用。 - 破坏不剥夺条件:当一个线程已经持有了某些资源,并且又去请求其他资源而无法获取时,它必须释放已经持有的资源,待以后需要时再重新申请。 - 破坏循环等待条件:可以对资源进行编号,规定线程必须按照资源编号的顺序来申请资源,这样就不会出现循环等待的情况。 7. Spring 框架的核心特性有哪些? - 控制反转(Inversion of Control,IOC):是一种设计原则,将对象的创建和依赖关系的管理从代码中转移到 Spring 容器中。Spring 容器通过 XML 配置文件、注解等方式来创建和管理对象,实现对象之间的解耦。 - 面向切面编程(Aspect - Oriented Programming,AOP):允许在不修改原有代码的基础上,对程序的某些特定部分进行增强,例如日志记录、事务管理等。AOP 通过将横切关注点(如日志、事务)与业务逻辑分离,提高了代码的可维护性和可复用性。 8. Spring Boot 相比 Spring 有哪些优势? - 简化配置:Spring Boot 提供了自动配置功能,它会根据项目中添加的依赖自动配置 Spring 应用,减少了大量的 XML 配置文件和 Java 配置类。 - 快速搭建项目:Spring Boot 提供了 Spring Initializr 工具,可以快速生成一个基本的 Spring Boot 项目骨架,包含了必要的依赖和配置。 - 内置服务器:Spring Boot 内置了 Tomcat、Jetty 等服务器,无需手动部署到外部服务器,直接运行项目的 main 方法即可启动应用。 - 生产级特性:Spring Boot 提供了健康检查、指标监控、外部配置等生产级特性,方便应用的部署和管理。 9. MyBatis 的工作原理 - 加载配置文件:MyBatis 首先会加载全局配置文件(如 mybatis-config.xml)和映射文件(如 UserMapper.xml),这些配置文件包含了数据库连接信息、SQL 语句等。 - 创建 SqlSessionFactory:根据加载的配置文件创建 SqlSessionFactory,它是 MyBatis 的核心对象,用于创建 SqlSession。 - 创建 SqlSession:通过 SqlSessionFactory 创建 SqlSession,SqlSession 是一个会话对象,用于执行 SQL 语句。 - 执行 SQL 语句:通过 SqlSession 可以获取 Mapper 接口的代理对象,调用 Mapper 接口的方法来执行相应的 SQL 语句。 - 处理结果集:MyBatis 会将查询结果映射到 Java 对象中,方便开发者使用。 10. Dubbo、RabbitMq、xxl - job、Redis 这些技术的作用 - Dubbo:是一个高性能、轻量级的开源 Java RPC 框架,用于实现分布式服务调用。它提供了服务注册与发现、远程调用、集群容错、负载均衡等功能,帮助开发者构建分布式系统。 - RabbitMq:是一个开源的消息队列中间件,遵循 AMQP 协议。它可以实现异步通信、解耦系统组件、流量削峰等功能。生产者将消息发送到队列中,消费者从队列中获取消息进行处理。 - xxl - job:是一个分布式任务调度平台,支持任务的调度、执行、监控等功能。它可以将任务分配到不同的节点上执行,提高任务处理的效率和可靠性。 - Redis:是一个开源的内存数据结构存储系统,可作为数据库、缓存和消息中间件使用。它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,具有高性能、高并发、持久化等特点。常用于缓存热点数据、分布式锁、消息队列等场景。