《互联网大厂 Java 面试:核心知识、框架与中间件大考验》
王铁牛怀揣着对互联网大厂的憧憬,来到了面试现场。面试官表情严肃,一场紧张的面试即将拉开帷幕。
第一轮面试开始 面试官:“首先问你几个 Java 核心知识的问题。Java 中基本数据类型有哪些?” 王铁牛:“有 byte、short、int、long、float、double、char、boolean。” 面试官:“回答正确,不错。那 String 是基本数据类型吗?” 王铁牛:“不是,String 是引用数据类型。” 面试官:“很好。那说说 Java 中多态的实现方式有哪些?” 王铁牛:“主要有继承和接口实现,还有方法的重载和重写。” 面试官:“回答得很全面,看来基础很扎实。”
第二轮面试开始 面试官:“接下来聊聊 JUC 和多线程。什么是线程安全?” 王铁牛:“就是在多线程环境下,对共享资源的操作不会出现数据不一致等问题。” 面试官:“回答正确。那线程池有哪些常用的创建方式?” 王铁牛:“可以通过 Executors 工具类创建,比如 newFixedThreadPool、newCachedThreadPool 等。” 面试官:“那说说 ThreadLocal 的作用。” 王铁牛:“它可以为每个使用该变量的线程都提供一个独立的变量副本,每个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。” 面试官:“非常棒,对多线程这块掌握得不错。”
第三轮面试开始 面试官:“现在考察一些框架和中间件的知识。Spring 的核心特性有哪些?” 王铁牛:“有依赖注入和面向切面编程。” 面试官:“不错。那 Spring Boot 有什么优点?” 王铁牛:“它可以快速搭建项目,简化配置,内置 Tomcat 等服务器。” 面试官:“那 MyBatis 中 #{} 和 {} 的区别是什么?” **王铁牛**:“#{} 是预编译处理,{} 是字符串替换。#{} 可以防止 SQL 注入,而 ${} 可能存在 SQL 注入风险。” 面试官:“回答得很准确。再问你,Dubbo 是什么,有什么作用?” 王铁牛:“Dubbo 是一个分布式服务框架,能实现服务的注册与发现、远程调用等功能。” 面试官:“看来你对框架这块也有一定了解。最后问你,Redis 有哪些数据结构?” 王铁牛:“有字符串、哈希、列表、集合、有序集合。”
面试接近尾声,面试官放下手中的笔,说道:“今天的面试就到这里,你整体表现有好的地方,基础问题回答得比较准确,但对于一些更深入的场景应用还需要加强。你先回家等通知吧,我们后续会综合评估后给你反馈。”
问题答案详细解析
- Java 中基本数据类型有哪些? Java 中的基本数据类型分为四类八种。
- 整数类型:byte(1 字节)、short(2 字节)、int(4 字节)、long(8 字节)。
- 浮点类型:float(4 字节)、double(8 字节)。
- 字符类型:char(2 字节)。
- 布尔类型:boolean(只有 true 和 false 两个值)。
- String 是基本数据类型吗? String 不是基本数据类型,而是引用数据类型。基本数据类型是 Java 语言中最基础的数据类型,而引用数据类型是指向对象的引用。String 类是 Java 中用来表示字符串的类,通过创建对象来存储字符串。
- Java 中多态的实现方式有哪些?
- 继承:子类继承父类,重写父类的方法,通过父类引用指向子类对象,调用重写的方法实现多态。例如:
class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Dog();
animal.sound();
}
}
- 接口实现:类实现接口,不同的类可以实现同一个接口并提供不同的实现方式,通过接口引用指向实现类对象实现多态。
- 方法重载:在一个类中,方法名相同但参数列表不同,根据调用时传入的参数不同来决定调用哪个方法。
- 方法重写:子类重写父类的方法,方法签名相同但实现不同。
- 什么是线程安全? 在多线程环境下,当多个线程同时访问共享资源时,如果对共享资源的操作不会导致数据不一致、脏读、幻读等问题,就称这个操作是线程安全的。例如,一个线程在读取一个共享变量的同时,另一个线程对该变量进行写操作,如果没有适当的同步机制,就可能出现数据不一致的问题。
- 线程池有哪些常用的创建方式?
Executors.newFixedThreadPool(int nThreads):创建一个固定大小的线程池,线程池中的线程数量固定,当有新任务提交时,如果线程池中有空闲线程则执行任务,否则任务会在队列中等待。Executors.newCachedThreadPool():创建一个可缓存的线程池,线程池中的线程数量会根据需要自动调整,如果线程池中的线程在 60 秒内没有被使用,则会被回收。Executors.newSingleThreadExecutor():创建一个单线程的线程池,线程池中只有一个线程,任务会按照提交的顺序依次执行。Executors.newScheduledThreadPool(int corePoolSize):创建一个可以执行定时任务和周期性任务的线程池。
- ThreadLocal 的作用 ThreadLocal 为每个使用该变量的线程都提供一个独立的变量副本,每个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。例如,在一个多线程的 Web 应用中,每个线程可能需要处理不同的用户请求,使用 ThreadLocal 可以为每个线程保存该用户的信息,方便在整个请求处理过程中使用。
public class ThreadLocalExample {
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
threadLocal.set(1);
System.out.println("Thread 1: " + threadLocal.get());
});
Thread t2 = new Thread(() -> {
threadLocal.set(2);
System.out.println("Thread 2: " + threadLocal.get());
});
t1.start();
t2.start();
}
}
- Spring 的核心特性有哪些?
- 依赖注入(DI):通过外部容器来管理对象之间的依赖关系,而不是在对象内部直接创建依赖对象。例如,一个 Service 类依赖一个 DAO 类,通过依赖注入可以将 DAO 对象注入到 Service 类中,降低了类之间的耦合度。
- 面向切面编程(AOP):可以在不修改原有代码的情况下,对程序进行增强,比如在方法执行前后添加日志记录、事务管理等功能。
- Spring Boot 有什么优点?
- 快速搭建项目:Spring Boot 提供了大量的 Starter 依赖,只需要添加相应的依赖,就可以快速搭建一个项目,减少了配置的工作量。
- 简化配置:Spring Boot 采用了约定大于配置的原则,很多配置都有默认值,不需要开发者手动配置。
- 内置服务器:Spring Boot 内置了 Tomcat、Jetty 等服务器,不需要额外部署服务器,直接运行项目即可。
- MyBatis 中 #{} 和 ${} 的区别是什么?
#{}:是预编译处理,MyBatis 在处理#{}时,会将 SQL 中的#{}替换为?占位符,然后使用 PreparedStatement 来执行 SQL 语句,这样可以防止 SQL 注入。例如:
<select id="getUserById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
${}:是字符串替换,MyBatis 在处理${}时,会将${}中的内容直接替换到 SQL 语句中,可能存在 SQL 注入风险。例如:
<select id="getUserByColumnName" parameterType="String" resultType="User">
SELECT * FROM users WHERE ${columnName} = 'value'
</select>
- Dubbo 是什么,有什么作用? Dubbo 是一个高性能、轻量级的分布式服务框架,主要用于解决分布式系统中服务之间的调用问题。它的主要作用有:
- 服务注册与发现:通过注册中心(如 Zookeeper),服务提供者可以将自己提供的服务注册到注册中心,服务消费者可以从注册中心获取服务提供者的地址信息,实现服务的发现。
- 远程调用:Dubbo 提供了多种远程调用协议(如 Dubbo 协议、HTTP 协议等),可以实现服务消费者和服务提供者之间的远程调用。
- 负载均衡:Dubbo 支持多种负载均衡策略(如随机、轮询、最少活跃调用数等),可以将请求均匀地分发到多个服务提供者上,提高系统的性能和可用性。
- Redis 有哪些数据结构?
- 字符串(String):可以存储字符串、整数或浮点数,支持对字符串的追加、修改、自增等操作。
- 哈希(Hash):类似于 Java 中的 HashMap,是一个键值对的集合,适合存储对象。
- 列表(List):是一个双向链表,可以在列表的两端进行插入和删除操作,常用于消息队列。
- 集合(Set):是一个无序且唯一的元素集合,支持集合的交集、并集、差集等操作。
- 有序集合(Sorted Set):和集合类似,但每个元素都有一个分数,根据分数对元素进行排序,常用于排行榜等场景。