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

55 阅读7分钟

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

王铁牛怀揣着对互联网大厂的憧憬,走进了面试室。严肃的面试官正襟危坐,一场紧张的面试拉开了帷幕。

第一轮面试

面试官:“我们先从 Java 核心知识开始。你能说说 Java 中基本数据类型有哪些吗?” 王铁牛:“这我知道,有 byte、short、int、long、float、double、char、boolean。” 面试官:“回答得不错。那 String 是基本数据类型吗?” 王铁牛:“不是,String 是引用数据类型。” 面试官:“很好。那在 Java 中,什么是自动装箱和拆箱?” 王铁牛:“自动装箱就是把基本数据类型转换为对应的包装类,拆箱就是把包装类转换为基本数据类型。比如 Integer i = 10 就是自动装箱,int j = i 就是拆箱。” 面试官:“非常棒,看来你对 Java 核心基础掌握得很扎实。”

第二轮面试

面试官:“接下来聊聊多线程和 JUC 相关的。什么是线程安全?” 王铁牛:“线程安全就是在多线程环境下,程序的执行结果和单线程环境下是一样的,不会出现数据不一致等问题。” 面试官:“那你能说一个 Java 中实现线程安全的方式吗?” 王铁牛:“可以使用 synchronized 关键字,它可以保证同一时刻只有一个线程可以访问被它修饰的代码块或方法。” 面试官:“不错。那 JUC 中的 CountDownLatch 是做什么用的?” 王铁牛:“呃……这个……好像是和线程计数有关吧,具体的我有点不太清楚。” 面试官:“CountDownLatch 主要用于让一个或多个线程等待其他线程完成操作。你后续还需要加强对 JUC 相关知识的学习。”

第三轮面试

面试官:“现在问你一些框架和中间件的问题。Spring 框架的核心特性有哪些?” 王铁牛:“有依赖注入和面向切面编程。依赖注入就是把对象的创建和管理交给 Spring 容器,面向切面编程可以在不修改原有代码的情况下,对程序进行增强。” 面试官:“回答得还行。那 Spring Boot 相比于 Spring 有什么优势?” 王铁牛:“Spring Boot 简化了 Spring 的配置,它有自动配置的功能,能快速搭建项目。” 面试官:“很好。那 MyBatis 中 #{} 和 {} 的区别是什么?” **王铁牛**:“这个……我只记得它们好像用法不太一样,具体区别我有点说不清楚。” **面试官**:“#{} 是预编译处理,能防止 SQL 注入,而 {} 是直接替换,可能存在 SQL 注入风险。你对框架细节的掌握还不够。”

面试结束,面试官表情严肃地说:“王铁牛,今天的面试就到这里。你对一些基础的 Java 知识掌握得还可以,但对于 JUC、框架和中间件的一些细节问题回答得不够准确和清晰。我们会综合评估你的表现,你先回家等通知吧。”

问题答案详解

  1. Java 中基本数据类型有哪些:Java 中有 8 种基本数据类型,可分为 4 类。整数类型:byte(1 字节)、short(2 字节)、int(4 字节)、long(8 字节);浮点类型:float(4 字节)、double(8 字节);字符类型:char(2 字节);布尔类型:boolean(理论上 1 位,但 JVM 处理时通常按 1 字节)。基本数据类型存储的是具体的值。
  2. String 是基本数据类型吗:String 不是基本数据类型,而是引用数据类型。引用数据类型存储的是对象的引用地址,而不是对象本身。String 类是 Java 中用于处理字符串的类,它是不可变的,即一旦创建,其值不能被修改。
  3. 什么是自动装箱和拆箱:自动装箱是 Java 编译器在基本数据类型和对应的包装类之间进行的自动转换。例如,当把一个基本数据类型赋值给对应的包装类对象时,编译器会自动调用包装类的 valueOf() 方法进行装箱操作。拆箱则相反,当把一个包装类对象赋值给基本数据类型时,编译器会自动调用包装类的 xxxValue() 方法进行拆箱操作。这样可以使代码编写更加简洁。
  4. 什么是线程安全:在多线程环境下,多个线程可能会同时访问和修改共享资源。如果程序没有进行适当的同步控制,就可能会导致数据不一致、脏读、幻读等问题。线程安全的程序会通过各种同步机制(如锁、原子类等)来保证在多线程环境下程序的执行结果和单线程环境下一致,不会出现上述问题。
  5. Java 中实现线程安全的方式
    • synchronized 关键字:可以修饰方法或代码块。当修饰方法时,同一时刻只有一个线程可以访问该方法;当修饰代码块时,同一时刻只有一个线程可以进入该代码块。它是基于对象头的 Mark Word 实现的锁机制。
    • Lock 接口:如 ReentrantLock,它提供了比 synchronized 更灵活的锁控制,例如可以实现公平锁、可中断锁等。
    • 原子类:JUC 包中的原子类(如 AtomicInteger、AtomicLong 等),基于 CAS(Compare-And-Swap)操作实现,保证对变量的操作是原子性的,从而实现线程安全。
  6. JUC 中的 CountDownLatch 是做什么用的:CountDownLatch 是一个同步辅助类,它允许一个或多个线程等待其他线程完成操作。它通过一个计数器来实现,初始化时设置计数器的值,每当一个线程完成任务时,计数器减 1,当计数器的值为 0 时,等待的线程将被唤醒继续执行。常用于主线程等待多个子线程完成任务的场景。
  7. Spring 框架的核心特性有哪些
    • 依赖注入(DI):将对象之间的依赖关系交给 Spring 容器来管理,而不是在对象内部直接创建依赖对象。这样可以降低代码的耦合度,提高代码的可维护性和可测试性。例如,一个类需要使用另一个类的对象时,不需要在该类内部使用 new 关键字创建,而是通过 Spring 容器注入。
    • 面向切面编程(AOP):允许在不修改原有代码的情况下,对程序进行增强。它将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高了代码的复用性和可维护性。AOP 通过代理模式实现,有基于 JDK 动态代理和 CGLIB 代理两种方式。
  8. Spring Boot 相比于 Spring 有什么优势
    • 简化配置:Spring Boot 提供了自动配置的功能,它会根据项目中引入的依赖自动配置 Spring 应用,减少了大量的 XML 配置文件或 Java 配置类。
    • 快速搭建项目:通过 Spring Initializr 可以快速生成项目骨架,集成了常见的依赖和插件,开发者可以专注于业务逻辑的开发。
    • 内嵌服务器:Spring Boot 内置了 Tomcat、Jetty 等服务器,无需额外配置服务器就可以直接运行项目。
    • 生产就绪特性:提供了健康检查、指标监控、外部配置等生产就绪特性,方便在生产环境中管理和监控应用。
  9. MyBatis 中 #{} 和 ${} 的区别是什么
    • #{}:是预编译处理,MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为占位符?,然后使用 PreparedStatement 进行预编译,能有效防止 SQL 注入攻击。例如,当传入的参数包含特殊字符时,会被正确处理,不会影响 SQL 的执行。
    • **:是直接替换,MyBatis在处理{}**:是直接替换,MyBatis 在处理 {} 时,会直接将 ${} 替换为传入的参数值。这种方式可能会导致 SQL 注入风险,因为如果传入的参数包含恶意的 SQL 语句,会直接拼接到 SQL 中执行。通常用于动态表名、动态列名等场景。