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

47 阅读11分钟

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

王铁牛怀揣着忐忑又期待的心情,走进了这家互联网大厂的面试间。严肃的面试官早已坐在那里,一场关于 Java 知识的严峻考验即将拉开帷幕。

第一轮提问 面试官:我们先从 Java 核心知识开始。Java 中基本数据类型有哪些? 王铁牛:这个我知道,有 byte、short、int、long、float、double、char、boolean。 面试官:回答得不错。那说说面向对象的四大特性是什么? 王铁牛:是封装、继承、多态和抽象。 面试官:很好。那 String、StringBuilder 和 StringBuffer 有什么区别? 王铁牛:String 是不可变的,每次对 String 的操作都会生成新的对象。StringBuilder 是非线程安全的,性能较高,而 StringBuffer 是线程安全的,性能相对低一些,因为它的方法加了同步锁。 面试官:非常棒,基础很扎实。

第二轮提问 面试官:接下来聊聊 JUC 和多线程。什么是线程池?为什么要使用线程池? 王铁牛:线程池就是预先创建好一定数量的线程,当有任务提交时,从线程池中获取线程来执行任务。使用线程池可以减少线程创建和销毁的开销,提高系统的性能和稳定性。 面试官:不错。那线程池有哪些常用的创建方式? 王铁牛:可以通过 Executors 工具类创建,比如 newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor 等。 面试官:那你说说这些创建方式各自的特点。 王铁牛:newFixedThreadPool 会创建固定大小的线程池,当有新任务提交时,如果线程池中有空闲线程就执行,没有就放入队列等待。newCachedThreadPool 是可缓存的线程池,会根据任务数量动态创建和销毁线程。newSingleThreadExecutor 是单线程的线程池,保证任务按顺序执行。 面试官:回答得很清晰,对线程池有一定的理解。

第三轮提问 面试官:现在说说框架相关的。Spring 的核心特性有哪些? 王铁牛:Spring 的核心特性有 IoC(控制反转)和 AOP(面向切面编程)。IoC 是把对象的创建和依赖关系的管理交给 Spring 容器,AOP 是在不修改原有代码的基础上增加额外的功能。 面试官:那 Spring Boot 相比 Spring 有什么优势? 王铁牛:Spring Boot 简化了 Spring 项目的配置,它有自动配置功能,能快速搭建项目,还内置了服务器,比如 Tomcat 等。 面试官:MyBatis 中 #{} 和 {} 的区别是什么? **王铁牛**:这个……嗯……好像 #{} 是预编译的,能防止 SQL 注入,{} 是直接替换,可能存在 SQL 注入风险,但是具体的使用场景我有点不太确定。 面试官:虽然回答不太完整,但大致方向是对的。Dubbo 是什么?它的核心组件有哪些? 王铁牛:Dubbo 是一个分布式服务框架。核心组件嘛……我记得有注册中心、远程调用、集群容错,具体的细节我有点模糊了。 面试官:看来你对框架有一定的了解,但有些细节还需要加强。

面试接近尾声,面试官看着王铁牛,严肃地说:“今天的面试就到这里了,你回家等通知吧。通过这次面试,能看出你对 Java 基础知识掌握得还不错,像 Java 核心知识和线程池相关的内容回答得很准确,这是你的优势。但在一些框架和中间件的细节方面,比如 MyBatis 和 Dubbo 的具体使用和原理,你还有所欠缺。我们后续会综合评估你的表现,有结果会及时通知你。”

问题答案详细解析

  1. Java 中基本数据类型有哪些? Java 中有 8 种基本数据类型,可分为 4 类:

    • 整数类型
      • byte:占 1 个字节,取值范围 -128 到 127。
      • short:占 2 个字节,取值范围 -32768 到 32767。
      • int:占 4 个字节,取值范围 -2147483648 到 2147483647。
      • long:占 8 个字节,取值范围 -9223372036854775808 到 9223372036854775807,定义 long 类型变量时需要在数字后面加 L 或 l。
    • 浮点类型
      • float:占 4 个字节,单精度浮点数,定义 float 类型变量时需要在数字后面加 F 或 f。
      • double:占 8 个字节,双精度浮点数,是浮点数的默认类型。
    • 字符类型
      • char:占 2 个字节,用于表示单个字符,使用单引号括起来,如 'A'。
    • 布尔类型
      • boolean:只有两个值,true 和 false,占 1 位。
  2. 面向对象的四大特性是什么?

    • 封装:将数据和操作数据的方法绑定在一起,隐藏对象的内部实现细节,只对外提供必要的接口。这样可以提高代码的安全性和可维护性,例如 Java 中的类和访问修饰符(private、protected、public)就是封装的体现。
    • 继承:允许一个类继承另一个类的属性和方法,被继承的类称为父类(基类),继承的类称为子类(派生类)。继承可以实现代码的复用,提高开发效率。Java 中使用 extends 关键字实现继承,一个子类只能继承一个父类(单继承)。
    • 多态:指同一个方法可以根据调用对象的不同而表现出不同的行为。多态的实现方式有两种:方法重载和方法重写。方法重载是指在同一个类中,多个方法具有相同的名称,但参数列表不同;方法重写是指子类重写父类的方法,方法名、参数列表和返回值类型都相同,但方法体不同。
    • 抽象:抽象是指将一类对象的共同特征总结出来,形成抽象类或接口。抽象类不能实例化,只能被继承;接口是一种特殊的抽象类,接口中的方法都是抽象方法。抽象可以提高代码的可扩展性和可维护性。
  3. String、StringBuilder 和 StringBuffer 有什么区别?

    • 可变性
      • String 类是不可变的,它的内部使用一个 final 修饰的字符数组来存储字符串,一旦创建,其值不能被修改。如果对 String 进行修改操作,实际上是创建了一个新的 String 对象。
      • StringBuilder 和 StringBuffer 是可变的,它们内部使用一个动态的字符数组来存储字符串,可以通过 append、insert 等方法对字符串进行修改,不会创建新的对象。
    • 线程安全性
      • String 是不可变的,所以是线程安全的。
      • StringBuffer 的方法都使用了 synchronized 关键字进行同步,所以是线程安全的,但由于同步会带来一定的性能开销,所以性能相对较低。
      • StringBuilder 没有使用同步机制,所以是非线程安全的,但性能较高。
    • 使用场景
      • 如果字符串很少进行修改操作,建议使用 String。
      • 如果字符串需要频繁修改,且是在单线程环境下,建议使用 StringBuilder。
      • 如果字符串需要频繁修改,且是在多线程环境下,建议使用 StringBuffer。
  4. 什么是线程池?为什么要使用线程池?

    • 线程池的定义:线程池是一种线程使用模式,它预先创建一定数量的线程,当有任务提交时,从线程池中获取线程来执行任务,任务执行完毕后线程不会销毁,而是返回线程池等待下一个任务。
    • 使用线程池的原因
      • 减少线程创建和销毁的开销:线程的创建和销毁需要消耗系统资源和时间,使用线程池可以避免频繁创建和销毁线程,提高系统的性能。
      • 提高响应速度:当有任务提交时,线程池中可能已经有空闲线程,任务可以立即执行,无需等待线程的创建。
      • 便于线程管理:线程池可以控制线程的数量,避免创建过多的线程导致系统资源耗尽。同时,线程池还可以对线程进行监控和管理。
  5. 线程池有哪些常用的创建方式?各自的特点是什么?

    • 通过 Executors 工具类创建
      • newFixedThreadPool:创建一个固定大小的线程池,线程池中的线程数量是固定的,当有新任务提交时,如果线程池中有空闲线程就执行,没有就放入队列等待。适用于需要控制并发线程数量的场景。
      • newCachedThreadPool:创建一个可缓存的线程池,线程池中的线程数量是动态的,根据任务数量自动创建和销毁线程。如果线程池中有空闲线程且空闲时间超过 60 秒,线程会被销毁。适用于执行大量短期异步任务的场景。
      • newSingleThreadExecutor:创建一个单线程的线程池,线程池中只有一个线程,保证任务按顺序执行。适用于需要保证任务顺序执行的场景。
      • newScheduledThreadPool:创建一个可定时执行任务的线程池,可以定时或周期性地执行任务。适用于需要定时执行任务的场景。
  6. Spring 的核心特性有哪些?

    • IoC(控制反转):也称为依赖注入(DI),是指将对象的创建和依赖关系的管理交给 Spring 容器,而不是由对象自己来创建和管理依赖。通过 IoC,对象之间的耦合度降低,代码的可维护性和可测试性提高。Spring 容器通过 XML 配置文件、注解等方式来管理对象的创建和依赖关系。
    • AOP(面向切面编程):是一种编程范式,它允许在不修改原有代码的基础上,对程序的某些特定部分进行增强。AOP 主要用于处理一些与业务逻辑无关的横切关注点,如日志记录、事务管理、权限验证等。Spring AOP 基于代理模式实现,有两种代理方式:JDK 动态代理和 CGLIB 代理。
  7. Spring Boot 相比 Spring 有什么优势?

    • 简化配置:Spring Boot 提供了自动配置功能,它会根据项目中引入的依赖自动配置 Spring 应用的各种组件,减少了大量的 XML 配置文件和 Java 配置类,使开发人员可以更专注于业务逻辑的实现。
    • 快速搭建项目:Spring Boot 提供了 Spring Initializr 工具,可以快速生成项目骨架,包含了项目所需的依赖和基本配置,开发人员可以立即开始编写代码。
    • 内置服务器:Spring Boot 内置了 Tomcat、Jetty 等服务器,开发人员可以直接运行 Spring Boot 应用,无需手动部署到服务器上。
    • 监控和管理:Spring Boot Actuator 提供了丰富的监控和管理功能,如健康检查、性能监控、日志管理等,方便开发人员对应用进行监控和维护。
  8. MyBatis 中 #{} 和 ${} 的区别是什么?

    • 语法和处理方式
      • #{} 是预编译处理,MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为占位符 ?,然后使用 PreparedStatement 进行预编译,防止 SQL 注入。
      • 是直接替换,MyBatis在处理{} 是直接替换,MyBatis 在处理 {} 时,会将 ${} 直接替换为变量的值,不会进行预编译,可能存在 SQL 注入风险。
    • 使用场景
      • #{} 适用于传入参数作为查询条件的场景,如 WHERE name = #{name}。
      • 适用于传入参数作为表名、列名等SQL语句的一部分的场景,如SELECTFROM{} 适用于传入参数作为表名、列名等 SQL 语句的一部分的场景,如 SELECT * FROM {tableName}。
  9. Dubbo 是什么?它的核心组件有哪些?

    • Dubbo 的定义:Dubbo 是阿里巴巴开源的一个高性能、轻量级的分布式服务框架,用于实现服务的远程调用和服务治理。它可以帮助开发人员构建分布式系统,提高系统的可扩展性和可维护性。
    • Dubbo 的核心组件
      • 服务提供者(Provider):暴露服务的一方,将自己的服务注册到注册中心。
      • 服务消费者(Consumer):调用服务的一方,从注册中心获取服务提供者的地址信息,然后远程调用服务。
      • 注册中心(Registry):负责服务的注册和发现,服务提供者将自己的服务信息注册到注册中心,服务消费者从注册中心获取服务提供者的地址信息。常用的注册中心有 ZooKeeper、Redis 等。
      • 监控中心(Monitor):负责统计服务的调用次数、调用时间等信息,为服务的性能优化提供依据。
      • 远程调用(RPC):实现服务的远程调用,Dubbo 支持多种远程调用协议,如 Dubbo 协议、HTTP 协议等。
      • 集群容错(Cluster):当服务提供者出现故障时,Dubbo 提供了多种集群容错策略,如失败重试、快速失败等,保证服务的高可用性。