《互联网大厂 Java 面试:核心知识、框架与中间件大考验》
王铁牛怀揣着紧张又期待的心情,坐在了互联网大厂的面试会议室里,对面坐着表情严肃的面试官,一场决定命运的面试即将开始。
第一轮提问 面试官:“首先问你几个 Java 核心知识的问题。Java 中基本数据类型有哪些?” 王铁牛:“Java 基本数据类型有 byte、short、int、long、float、double、char、boolean。” 面试官:“回答得不错。那 String 是基本数据类型吗,为什么?” 王铁牛:“String 不是基本数据类型,它是一个类。基本数据类型是 Java 语言内置的,而 String 类提供了很多操作字符串的方法,是引用数据类型。” 面试官:“很好。那说说面向对象的四大特性。” 王铁牛:“面向对象的四大特性是封装、继承、多态和抽象。封装是把数据和操作数据的方法绑定起来,隐藏内部实现细节;继承是子类继承父类的属性和方法;多态是同一个行为具有多个不同表现形式或形态的能力;抽象是将一类对象的共同特征总结出来构造类的过程。” 面试官:“非常棒,看来你对 Java 核心知识掌握得很扎实。那 Java 中异常分为哪几类?” 王铁牛:“Java 中异常分为检查性异常和非检查性异常。检查性异常是在编译阶段必须处理的异常,非检查性异常包括运行时异常和错误,运行时异常是程序运行过程中可能出现的异常,错误一般是系统级的问题。”
第二轮提问 面试官:“接下来考考你 JUC、JVM 和多线程的知识。JUC 包是什么,有什么作用?” 王铁牛:“JUC 是 java.util.concurrent 包的简称,它提供了在并发编程中很有用的工具类,比如线程池、锁、并发集合等,能帮助我们更方便地进行多线程编程。” 面试官:“回答正确。那说说 JVM 的内存结构。” 王铁牛:“JVM 内存结构主要包括堆、栈、方法区、本地方法栈和程序计数器。堆是存放对象实例的地方;栈主要存储局部变量等;方法区存储类的信息、常量等;本地方法栈为本地方法服务;程序计数器记录当前线程执行的字节码行号。” 面试官:“不错。多线程中如何实现线程同步?” 王铁牛:“可以使用 synchronized 关键字和 Lock 接口来实现线程同步。synchronized 可以修饰方法和代码块,Lock 接口有 ReentrantLock 等实现类。” 面试官:“很好。那线程池有哪些重要的参数?” 王铁牛:“线程池的重要参数有核心线程数、最大线程数、线程存活时间、时间单位、任务队列和线程工厂等。核心线程数是线程池保持的线程数量,最大线程数是线程池允许的最大线程数量。”
第三轮提问 面试官:“最后来考察一下你对框架和中间件的掌握。Spring 框架的核心特性有哪些?” 王铁牛:“Spring 框架的核心特性有 IoC(控制反转)和 AOP(面向切面编程)。IoC 是将对象的创建和依赖关系的管理交给 Spring 容器,AOP 是在不修改原有代码的基础上增加额外的功能。” 面试官:“回答得可以。Spring Boot 有什么优点?” 王铁牛:“Spring Boot 可以快速搭建项目,简化配置,内嵌服务器,还提供了很多启动器,方便集成各种组件。” 面试官:“那 MyBatis 中 #{} 和 {} 的区别是什么?” **王铁牛**:“#{} 是预编译处理,能防止 SQL 注入,它会将参数值进行占位符替换;{} 是直接替换,会有 SQL 注入风险,一般用于表名、列名等的替换。” 面试官:“Dubbo 是什么,有什么作用?” 王铁牛:“Dubbo 是一个高性能的分布式服务框架,它可以实现服务的注册与发现、远程调用等功能,提高系统的可扩展性和性能。” 面试官:“RabbitMQ、xxl - job 和 Redis 这几个中间件,你分别说说它们的主要用途。” 王铁牛:“RabbitMQ 是消息队列,用于异步通信、解耦和流量削峰;xxl - job 是分布式任务调度平台,用于定时任务的调度;Redis 是高性能的键值对数据库,可用于缓存、分布式锁等。”
面试官:“今天的面试就到这里,你先回家等通知吧。我们会综合评估后尽快给你反馈。”
问题答案详细解析
- Java 基本数据类型:Java 有 8 种基本数据类型,byte 占 1 个字节,用于表示较小的整数;short 占 2 个字节;int 占 4 个字节,是最常用的整数类型;long 占 8 个字节,用于表示较大的整数,定义时需在数字后面加 L;float 占 4 个字节,用于表示单精度浮点数,定义时需在数字后面加 F;double 占 8 个字节,是常用的双精度浮点数类型;char 占 2 个字节,用于表示单个字符;boolean 只有两个值 true 和 false,用于逻辑判断。
- String 不是基本数据类型:基本数据类型是 Java 语言内置的,只有 8 种,而 String 是一个类,属于引用数据类型。String 类位于 java.lang 包下,它提供了很多操作字符串的方法,如 length()、substring() 等。
- 面向对象的四大特性
- 封装:将数据和操作数据的方法绑定在一起,隐藏对象的内部实现细节,只对外提供必要的接口。例如,一个类中的成员变量可以使用 private 修饰,然后通过 public 的 getter 和 setter 方法来访问和修改这些变量,这样可以保证数据的安全性。
- 继承:子类可以继承父类的属性和方法,从而实现代码的复用。子类还可以重写父类的方法,实现自己的特定逻辑。例如,动物类是父类,狗类和猫类可以继承动物类,狗类和猫类除了拥有动物类的属性和方法外,还可以有自己独特的属性和方法。
- 多态:同一个行为具有多个不同表现形式或形态的能力。多态的实现方式有方法重载和方法重写。方法重载是在一个类中定义多个同名但参数不同的方法;方法重写是子类重写父类的方法。例如,一个动物类有一个叫的方法,狗类和猫类继承动物类并重写叫的方法,当调用不同子类对象的叫方法时,会有不同的表现。
- 抽象:将一类对象的共同特征总结出来构造类的过程。抽象类和接口是实现抽象的两种方式。抽象类中可以有抽象方法和具体方法,抽象方法只有方法声明,没有方法体,子类必须实现抽象方法;接口中只能有抽象方法和常量,接口的实现类必须实现接口中的所有方法。
- Java 中异常分为哪几类
- 检查性异常:也称为编译时异常,是在编译阶段必须处理的异常。例如,IOException、SQLException 等。如果程序中可能抛出检查性异常,就必须使用 try - catch 语句捕获并处理,或者使用 throws 关键字声明抛出该异常。
- 非检查性异常:包括运行时异常和错误。运行时异常是程序运行过程中可能出现的异常,如 NullPointerException、ArrayIndexOutOfBoundsException 等,这些异常通常是由于程序逻辑错误导致的,不需要在编译阶段进行处理。错误一般是系统级的问题,如 OutOfMemoryError、StackOverflowError 等,这些问题通常是由于系统资源不足或程序陷入无限递归等原因导致的,程序一般无法处理这些错误。
- JUC 包是什么,有什么作用:JUC 是 java.util.concurrent 包的简称,它是 Java 5 引入的用于支持并发编程的工具包。JUC 包提供了很多有用的类和接口,如线程池(ThreadPoolExecutor)、锁(ReentrantLock、ReadWriteLock)、并发集合(ConcurrentHashMap、CopyOnWriteArrayList)等。这些工具类可以帮助我们更方便地进行多线程编程,提高程序的性能和并发处理能力。
- JVM 的内存结构
- 堆:是 JVM 中最大的一块内存区域,用于存放对象实例。堆是所有线程共享的内存区域,垃圾回收主要就是针对堆进行的。堆又可以分为新生代和老年代,新生代又可以分为 Eden 区和两个 Survivor 区。
- 栈:主要存储局部变量、方法调用的上下文等。每个线程都有自己的栈,栈是线程私有的。栈中的数据以栈帧的形式存储,每个方法调用都会创建一个栈帧,方法执行完毕后,栈帧会被销毁。
- 方法区:用于存储类的信息、常量、静态变量等。方法区也是所有线程共享的内存区域。在 Java 8 之前,方法区也被称为永久代,Java 8 之后,方法区被元空间取代。
- 本地方法栈:为本地方法服务,本地方法是使用其他语言(如 C、C++)实现的方法。本地方法栈和栈的结构类似,也是线程私有的。
- 程序计数器:记录当前线程执行的字节码行号,是线程私有的。程序计数器是 JVM 中唯一不会出现 OutOfMemoryError 的内存区域。
- 多线程中如何实现线程同步
- synchronized 关键字:可以修饰方法和代码块。当修饰方法时,该方法在同一时间只能被一个线程访问;当修饰代码块时,需要指定一个对象作为锁,同一时间只有获得该锁的线程才能执行代码块中的代码。例如:
// 修饰方法
public synchronized void method() {
// 方法体
}
// 修饰代码块
public void method2() {
synchronized (this) {
// 代码块
}
}
- **Lock 接口**:Lock 接口有很多实现类,如 ReentrantLock。使用 Lock 接口可以更灵活地控制锁的获取和释放。例如:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
private Lock lock = new ReentrantLock();
public void method() {
lock.lock();
try {
// 代码块
} finally {
lock.unlock();
}
}
}
- 线程池有哪些重要的参数
- 核心线程数(corePoolSize):线程池保持的线程数量,当提交的任务数小于核心线程数时,线程池会创建新的线程来执行任务。
- 最大线程数(maximumPoolSize):线程池允许的最大线程数量,当任务队列满了,且线程数小于最大线程数时,线程池会创建新的线程来执行任务。
- 线程存活时间(keepAliveTime):当线程池中的线程数量大于核心线程数时,多余的空闲线程在等待新任务的最长时间,超过这个时间,线程会被销毁。
- 时间单位(unit):线程存活时间的单位,如 TimeUnit.SECONDS、TimeUnit.MILLISECONDS 等。
- 任务队列(workQueue):用于存储提交的任务,当线程池中的线程都在执行任务时,新提交的任务会被放入任务队列中等待执行。常见的任务队列有 ArrayBlockingQueue、LinkedBlockingQueue 等。
- 线程工厂(threadFactory):用于创建线程的工厂,通过线程工厂可以自定义线程的名称、优先级等属性。
- Spring 框架的核心特性
- IoC(控制反转):将对象的创建和依赖关系的管理交给 Spring 容器,而不是由对象本身来创建和管理。这样可以降低对象之间的耦合度,提高代码的可维护性和可测试性。例如,在 Spring 中可以通过 XML 配置文件或注解的方式来定义对象和对象之间的依赖关系,Spring 容器会根据配置来创建和管理这些对象。
- AOP(面向切面编程):在不修改原有代码的基础上,增加额外的功能,如日志记录、事务管理等。AOP 的实现原理是通过代理模式,在目标对象的方法执行前后插入额外的代码。在 Spring 中,可以使用 AspectJ 注解或 XML 配置来实现 AOP。
- Spring Boot 有什么优点
- 快速搭建项目:Spring Boot 提供了很多启动器,通过引入相应的启动器,就可以快速集成各种组件,减少了配置的工作量。
- 简化配置:Spring Boot 采用了约定大于配置的原则,很多配置都有默认值,只需要在必要时进行少量的配置即可。
- 内嵌服务器:Spring Boot 内嵌了 Tomcat、Jetty 等服务器,不需要额外部署服务器,直接运行项目即可。
- 监控和管理:Spring Boot 提供了 Actuator 模块,可以方便地对应用进行监控和管理,如查看应用的健康状态、性能指标等。
- MyBatis 中 #{} 和 ${} 的区别
- #{}:是预编译处理,MyBatis 会将 #{} 中的参数值进行占位符替换,然后使用 PreparedStatement 来执行 SQL 语句,这样可以防止 SQL 注入。例如:
<select id="getUserById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
- **${}**:是直接替换,MyBatis 会将 ${} 中的参数值直接替换到 SQL 语句中,这样会有 SQL 注入的风险。${} 一般用于表名、列名等的替换。例如:
<select id="getUserByColumn" parameterType="map" resultType="User">
SELECT * FROM users WHERE ${column} = #{value}
</select>
- Dubbo 是什么,有什么作用:Dubbo 是阿里巴巴开源的一个高性能的分布式服务框架,它可以实现服务的注册与发现、远程调用等功能。Dubbo 采用了分层架构,包括服务接口层、远程调用层、集群容错层、服务注册与发现层等。Dubbo 可以提高系统的可扩展性和性能,将一个大型系统拆分成多个服务,每个服务可以独立开发、部署和维护。
- RabbitMQ、xxl - job 和 Redis 这几个中间件的主要用途
- RabbitMQ:是一个开源的消息队列中间件,基于 AMQP 协议实现。它可以用于异步通信、解耦和流量削峰。例如,在一个电商系统中,用户下单后,订单系统可以将订单消息发送到 RabbitMQ 中,库存系统和支付系统可以从 RabbitMQ 中获取订单消息进行处理,这样可以提高系统的并发处理能力和可靠性。
- xxl - job:是一个分布式任务调度平台,它可以方便地实现定时任务的调度。xxl - job 采用了分布式架构,支持集群部署,具有任务管理、任务调度、任务监控等功能。例如,在一个数据处理系统中,可以使用 xxl - job 定时执行数据备份、数据清洗等任务。
- Redis:是一个高性能的键值对数据库,支持多种数据结构,如字符串、哈希、列表、集合、有序集合等。Redis 可以用于缓存、分布式锁、计数器、消息队列等场景。例如,在一个网站中,可以使用 Redis 缓存热门商品信息,减少数据库的访问压力;在分布式系统中,可以使用 Redis 实现分布式锁,保证多个节点对共享资源的互斥访问。