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

32 阅读8分钟

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

严肃的面试官坐在桌前,面前放着求职者王铁牛的简历。王铁牛有些紧张地走进面试房间,坐在面试官对面。

第一轮提问

  • 面试官:首先问几个Java核心知识的问题。Java中基本数据类型有哪些?
  • 王铁牛:这个我知道,有 byte、short、int、long、float、double、char、boolean。
  • 面试官:不错,回答得很准确。那 Java 中多态的实现方式有哪些?
  • 王铁牛:多态的实现方式主要有继承和接口。通过父类引用指向子类对象,或者接口引用指向实现类对象。
  • 面试官:很好。那说说 Java 中 static 关键字的作用。
  • 王铁牛:static 关键字可以修饰变量、方法和代码块。修饰变量时,该变量属于类,所有对象共享;修饰方法时,该方法可以直接通过类名调用;修饰代码块时,会在类加载时执行,且只执行一次。
  • 面试官:非常棒,看来你对 Java 核心知识掌握得很扎实。

第二轮提问

  • 面试官:接下来聊聊 JUC 和多线程。什么是线程安全?
  • 王铁牛:线程安全就是在多线程环境下,对共享资源的访问不会出现数据不一致等问题。
  • 面试官:对的。那 Java 中实现线程安全的方式有哪些?
  • 王铁牛:可以使用 synchronized 关键字,还有 Lock 接口的实现类,像 ReentrantLock。
  • 面试官:不错。那线程池有哪些核心参数?
  • 王铁牛:线程池的核心参数有核心线程数、最大线程数、线程存活时间、时间单位、任务队列和拒绝策略。
  • 面试官:回答得很全面。那说说常见的线程池有哪些?
  • 王铁牛:有 FixedThreadPool、CachedThreadPool、ScheduledThreadPool 和 SingleThreadExecutor。

第三轮提问

  • 面试官:现在来谈谈一些框架和中间件。Spring 的核心特性有哪些?
  • 王铁牛:Spring 的核心特性有 IoC(控制反转)和 AOP(面向切面编程)。
  • 面试官:很好。那 Spring Boot 的优点是什么?
  • 王铁牛:Spring Boot 可以快速搭建项目,简化配置,内置 Tomcat 等服务器,还能自动配置。
  • 面试官:不错。MyBatis 中 #{} 和 ${} 的区别是什么?
  • 王铁牛:这个……嗯……好像一个是预编译,一个不是,但具体我有点说不太清楚。
  • 面试官:再问一个,Dubbo 的集群容错策略有哪些?
  • 王铁牛:这个……我好像有点印象,但记不太全了。
  • 面试官:最后问一下,Redis 的数据类型有哪些?
  • 王铁牛:有 String、Hash、List、Set、ZSet。

面试总结 面试官推了推眼镜,看着王铁牛说:“通过这三轮的提问,可以看出你对 Java 核心知识、JUC、多线程和线程池等方面掌握得比较扎实,回答得都很准确,基础还是很不错的。在 Spring 和 Spring Boot 这些框架的基础概念上也有清晰的认识。不过,在一些框架和中间件的细节问题上,比如 MyBatis 中 #{} 和 ${} 的区别,Dubbo 的集群容错策略等,回答得不够清晰准确,说明你对这些部分的理解还不够深入。整体来看,你有一定的技术基础,但对于一些复杂的技术点还需要进一步学习和巩固。你先回家等通知吧,后续如果有消息会及时联系你。”

问题答案

  1. Java 中基本数据类型有哪些
    • Java 中有 8 种基本数据类型,分为 4 类。
    • 整数类型:byte(1 字节,-128 到 127)、short(2 字节,-32768 到 32767)、int(4 字节,-2147483648 到 2147483647)、long(8 字节,范围很大)。
    • 浮点类型:float(4 字节,单精度浮点数)、double(8 字节,双精度浮点数)。
    • 字符类型:char(2 字节,用于表示单个字符)。
    • 布尔类型:boolean(1 位,只有 true 和 false 两个值)。
  2. Java 中多态的实现方式有哪些
    • 继承:通过父类引用指向子类对象。例如,有一个父类 Animal,子类 Dog 和 Cat,我们可以这样写:Animal animal = new Dog(); 然后调用 animal 的方法时,如果该方法在子类中被重写,会执行子类的实现。
    • 接口:接口引用指向实现类对象。比如有一个接口 Flyable,有一个实现类 Bird 实现了该接口,我们可以这样写:Flyable flyable = new Bird(); 调用 flyable 的方法时会执行 Bird 类中实现的方法。
  3. Java 中 static 关键字的作用
    • 修饰变量:static 变量属于类,而不属于类的任何一个对象。所有对象共享该变量。例如:
class StaticExample {
    static int staticVar = 10;
}
- 修饰方法:static 方法可以直接通过类名调用,不需要创建对象。例如:
class StaticExample {
    static void staticMethod() {
        System.out.println("This is a static method.");
    }
}
// 调用方式
StaticExample.staticMethod();
- 修饰代码块:static 代码块会在类加载时执行,且只执行一次。例如:
class StaticExample {
    static {
        System.out.println("Static block is executed.");
    }
}
  1. 什么是线程安全
    • 在多线程环境下,如果对共享资源的访问不会导致数据不一致、脏读、幻读等问题,就称该资源是线程安全的。例如,一个计数器变量,如果多个线程同时对其进行自增操作,可能会出现数据不一致的情况,这就不是线程安全的;如果通过加锁等机制保证每次只有一个线程可以对其进行操作,就是线程安全的。
  2. Java 中实现线程安全的方式有哪些
    • synchronized 关键字:可以修饰方法或代码块。修饰方法时,该方法在同一时间只能被一个线程访问;修饰代码块时,该代码块在同一时间只能被一个线程执行。例如:
class SynchronizedExample {
    // 同步方法
    public synchronized void syncMethod() {
        // 方法体
    }

    // 同步代码块
    public void syncBlock() {
        synchronized (this) {
            // 代码块
        }
    }
}
- Lock 接口的实现类:如 ReentrantLock。使用时需要手动加锁和解锁。例如:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class LockExample {
    private Lock lock = new ReentrantLock();

    public void lockMethod() {
        lock.lock();
        try {
            // 业务逻辑
        } finally {
            lock.unlock();
        }
    }
}
  1. 线程池有哪些核心参数
    • 核心线程数(corePoolSize):线程池的基本大小,当提交的任务数小于核心线程数时,线程池会创建新的线程来执行任务。
    • 最大线程数(maximumPoolSize):线程池允许创建的最大线程数。
    • 线程存活时间(keepAliveTime):当线程池中的线程数量超过核心线程数时,多余的空闲线程在被销毁之前等待新任务的最长时间。
    • 时间单位(unit):keepAliveTime 的时间单位,如 TimeUnit.SECONDS 等。
    • 任务队列(workQueue):用于存储等待执行的任务的队列。常见的有 ArrayBlockingQueue、LinkedBlockingQueue 等。
    • 拒绝策略(handler):当任务队列已满且线程池中的线程数量达到最大线程数时,新提交的任务会执行拒绝策略。常见的有 AbortPolicy(直接抛出异常)、CallerRunsPolicy(由调用线程处理)等。
  2. 常见的线程池有哪些
    • FixedThreadPool:固定大小的线程池,核心线程数和最大线程数相等。适用于需要控制并发线程数量的场景。
    • CachedThreadPool:可缓存的线程池,核心线程数为 0,最大线程数为 Integer.MAX_VALUE。线程空闲时间超过 60 秒会被回收。适用于执行大量短期异步任务的场景。
    • ScheduledThreadPool:用于执行定时任务和周期性任务的线程池。
    • SingleThreadExecutor:单线程的线程池,只有一个核心线程,保证所有任务按顺序执行。适用于需要顺序执行任务的场景。
  3. Spring 的核心特性有哪些
    • IoC(控制反转):也称为依赖注入(DI),是指将对象的创建和依赖关系的管理从代码中转移到 Spring 容器中。Spring 容器负责创建对象并注入其依赖,降低了代码的耦合度。例如,一个类需要依赖另一个类的对象,不需要在该类中手动创建依赖对象,而是通过 Spring 容器注入。
    • AOP(面向切面编程):允许我们在不修改原有代码的情况下,对程序进行增强。可以将一些通用的功能(如日志记录、事务管理等)从业务逻辑中分离出来,以切面的形式进行处理。
  4. Spring Boot 的优点是什么
    • 快速搭建项目:通过 Spring Initializr 可以快速生成项目骨架,减少了手动配置的时间。
    • 简化配置:Spring Boot 提供了大量的自动配置,大部分情况下不需要手动编写复杂的配置文件。
    • 内置服务器:内置了 Tomcat、Jetty 等服务器,无需额外配置服务器即可运行项目。
    • 自动配置:根据项目中引入的依赖,Spring Boot 会自动进行相应的配置,提高开发效率。
  5. MyBatis 中 #{} 和 ${} 的区别是什么
    • #{} 是预编译处理,MyBatis 会将 #{} 替换为占位符 ?,然后使用 PreparedStatement 进行参数设置,能有效防止 SQL 注入攻击。例如:
<select id="getUserById" parameterType="int" resultType="User">
    SELECT * FROM users WHERE id = #{id}
</select>
- ${} 是字符串替换,MyBatis 会将 ${} 直接替换为参数的值,可能会导致 SQL 注入攻击。一般用于动态表名、动态列名等场景。例如:
<select id="getUserByColumnName" parameterType="map" resultType="User">
    SELECT ${columnName} FROM users
</select>
  1. Dubbo 的集群容错策略有哪些
    • Failover Cluster(失败自动切换):当调用失败时,会自动切换到其他可用的服务提供者进行重试,默认重试 2 次。适用于读操作。
    • Failfast Cluster(快速失败):只调用一次,失败后立即抛出异常,不进行重试。适用于非幂等性的写操作。
    • Failsafe Cluster(失败安全):出现异常时,直接忽略异常,返回一个空结果。适用于对稳定性要求较高的场景。
    • Failback Cluster(失败自动恢复):失败后,会将请求记录下来,定时重试。适用于消息通知等场景。
    • Forking Cluster(并行调用多个服务提供者):并行调用多个服务提供者,只要有一个成功就返回结果。适用于对实时性要求较高的场景。
    • Broadcast Cluster(广播调用):广播调用所有服务提供者,逐个调用,任意一个报错则报错。适用于更新缓存等场景。
  2. Redis 的数据类型有哪些
    • String(字符串):最基本的数据类型,可以存储字符串、整数、浮点数等。常见操作有 set、get 等。
    • Hash(哈希):用于存储键值对的集合,适合存储对象。常见操作有 hset、hget 等。
    • List(列表):有序的字符串列表,可以从两端进行插入和删除操作。常见操作有 lpush、rpop 等。
    • Set(集合):无序且唯一的字符串集合。常见操作有 sadd、sismember 等。
    • ZSet(有序集合):有序且唯一的字符串集合,每个元素都有一个分数,根据分数排序。常见操作有 zadd、zrange 等。