1. Java内存模型(JMM)
问题:请解释Java内存模型(JMM)的基本概念。
答案:
Java内存模型(JMM)定义了多线程程序中变量的访问规则。JMM的主要目标是确保程序在多线程环境下的正确性和性能。JMM主要包括以下几点:
- 主内存与工作内存:所有变量都存储在主内存中,每个线程有自己的工作内存,线程对变量的所有操作都必须在自己的工作内存中进行。
- 内存可见性:通过volatile关键字、synchronized关键字和final关键字来保证内存可见性。
- 原子性:通过synchronized关键字和Lock接口来保证操作的原子性。
- 有序性:通过volatile关键字和synchronized关键字来禁止指令重排序,保证操作的有序性。
2. 多线程
问题:请解释synchronized关键字的工作原理。
答案:synchronized
关键字用于控制多线程对共享资源的访问,它有以下几种使用方式:
- 同步方法:作用于实例方法,锁住的是对象实例。
public synchronized void method() { // 同步代码块 }
- 同步代码块:作用于代码块,锁住的是指定的对象。
public void method() { synchronized (this) { // 同步代码块 } }
- 静态同步方法:作用于静态方法,锁住的是类的Class对象。
public static synchronized void method() { // 同步代码块 }
synchronized
关键字通过在对象头中设置锁标志位来实现锁机制,当一个线程获取到锁后,其他线程必须等待锁释放才能继续执行。
3. JVM
问题:请解释JVM的内存结构。
答案:
JVM的内存结构主要包括以下几个部分:
- 堆(Heap):存放对象实例,是垃圾收集器管理的主要区域。
- 方法区(Method Area):存储类信息、常量池、静态变量等。
- 虚拟机栈(VM Stack):每个线程都有一个私有的虚拟机栈,存储局部变量表、操作数栈、动态链接、方法出口等信息。
- 本地方法栈(Native Method Stack):与虚拟机栈类似,但为本地方法服务。
- 程序计数器(Program Counter Register):每个线程都有一个程序计数器,存储下一条要执行的字节码指令的地址。
4. 设计模式
问题:请解释单例模式的几种实现方式。
答案:
单例模式确保一个类只有一个实例,并提供一个全局访问点。常见的实现方式有:
- 懒汉式:线程不安全,需要加锁。
- 双重检查锁定(Double-Check Locking):线程安全,延迟初始化。
-
public class Singleton { private volatile static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
-
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记及答案【点击此处即可】免费获取
- 静态内部类:线程安全,延迟初始化。
-
public class Singleton { private Singleton() {} private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } }
- 枚举:线程安全,防止反射和序列化攻击。
public enum Singleton { INSTANCE; public void doSomething() { // 方法实现 } }
5. 常见框架
问题:请解释Spring框架中的IoC和DI。
答案:
- IoC(控制反转):IoC是一种设计思想,将对象的创建和依赖关系的管理交给容器来完成,而不是由程序代码直接管理。这样可以降低耦合度,提高灵活性。
- DI(依赖注入):DI是IoC的具体实现方式,通过构造函数、setter方法或字段注入的方式,将依赖的对象注入到目标对象中。
@Service public class UserService { private final UserRepository userRepository; @Autowired public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public User getUserById(Long id) { return userRepository.findById(id).orElse(null); } }
6. 性能优化
问题:请解释如何优化Java应用程序的性能。
答案:
优化Java应用程序的性能可以从多个方面入手:
- 代码优化:避免不必要的计算,减少循环次数,使用合适的数据结构和算法。
- 多线程优化:合理使用多线程,避免过度竞争,使用并发集合和线程池。
- JVM调优:调整JVM参数,如堆大小、垃圾回收器类型等。
- 缓存优化:使用缓存减少数据库访问,如Redis、Memcached。
- 数据库优化:优化SQL查询,使用索引,合理设计表结构。
- 网络优化:减少网络请求,使用异步通信,压缩传输数据。
7. 安全
问题:请解释Java中的常见安全漏洞及其防范措施。
答案:
常见的Java安全漏洞包括:
- SQL注入:通过用户输入构造恶意SQL语句。防范措施:使用预编译语句(PreparedStatement)。
String sql = "SELECT * FROM users WHERE username = ? AND password = ?"; PreparedStatement pstmt = connection.prepareStatement(sql); pstmt.setString(1, username); pstmt.setString(2, password); ResultSet rs = pstmt.executeQuery();
- XSS(跨站脚本攻击):通过用户输入插入恶意脚本。防范措施:对用户输入进行转义。
String safeOutput = HtmlUtils.htmlEscape(userInput);
- 1
- CSRF(跨站请求伪造):通过伪造用户的请求进行恶意操作。防范措施:使用CSRF令牌。
@PostMapping("/submit") public String submit(@RequestParam("token") String token, @ModelAttribute("form") Form form) { if (isValidToken(token)) { // 处理表单提交 } else { // 处理无效令牌 } return "result"; }
8. 分布式系统
问题:请解释CAP理论及其权衡。
答案:
CAP理论指出,在分布式系统中,一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)三者不可兼得,最多只能同时满足其中的两个。
- 一致性:所有节点在同一时间看到相同的数据。
- 可用性:每个请求都能在有限时间内返回结果。
- 分区容忍性:系统在部分节点之间通信失败时仍能正常运行。
常见的权衡策略:
- CP系统:牺牲可用性,保证一致性和分区容忍性,如Zookeeper。
- AP系统:牺牲一致性,保证可用性和分区容忍性,如Cassandra。
- CA系统:牺牲分区容忍性,保证一致性和可用性,但在实际分布式环境中难以实现。
9. 设计原则
问题:请解释SOLID原则。
答案:
SOLID原则是面向对象设计的五个基本原则:
- 单一职责原则(SRP):一个类应该只有一个改变的理由。
- 开放封闭原则(OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
- 里氏替换原则(LSP):子类可以替换父类出现在程序中的地方。
- 接口隔离原则(ISP):客户端不应该依赖它不需要的接口。
- 依赖倒置原则(DIP):高层模块不应该依赖低层模块,两者都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。
10. 数据结构和算法
问题:请解释二叉树的前序、中序和后序遍历。
答案:
二叉树的遍历有三种基本方式:
- 前序遍历:访问根节点 -> 遍历左子树 -> 遍历右子树。
public void preOrder(TreeNode node) { if (node == null) return; System.out.print(node.val + " "); preOrder(node.left); preOrder(node.right); }
- 中序遍历:遍历左子树 -> 访问根节点 -> 遍历右子树。
public void inOrder(TreeNode node) { if (node == null) return; inOrder(node.left); System.out.print(node.val + " "); inOrder(node.right); }
- 后序遍历:遍历左子树 -> 遍历右子树 -> 访问根节点。
public void postOrder(TreeNode node) { if (node == null) return; postOrder(node.left); postOrder(node.right); System.out.print(node.val + " "); }
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记及答案【点击此处即可】免费获取