1. 集合与泛型
1.1. 什么是泛型?泛型的优势是什么?
泛型允许类、接口和方法在定义时不指定具体的类型,在使用时再指定类型。优势:
- 提高代码复用性。
- 提供类型安全,避免强制类型转换带来的
ClassCastException
。
public class Box<T> {
private T value;
public void set(T value) { this.value = value; }
public T get() { return value; }
}
1.2. HashMap
和 TreeMap
的区别是什么?
HashMap
:基于哈希表实现,时间复杂度为 O(1),无序存储。TreeMap
:基于红黑树实现,时间复杂度为 O(logN),按键的自然顺序或自定义排序存储。
1.3. 为什么 HashMap
不是线程安全的?如何让它线程安全?
HashMap
在并发环境下,可能出现数据不一致的情况。可以使用:
Collections.synchronizedMap
方法。ConcurrentHashMap
提供线程安全的HashMap
。
2. 多线程与并发
2.1. 解释线程安全和死锁。
- 线程安全:多个线程访问同一个资源时,不会破坏数据一致性。
- 死锁:两个或多个线程互相等待对方释放锁,导致程序无法继续执行。
2.2. 什么是 volatile
关键字?
volatile
关键字用于修饰变量,保证变量的可见性,即当一个线程修改变量时,其他线程立刻可以看到变化,但不能保证操作的原子性。
2.3. 什么是线程池?为什么要使用线程池?
线程池是一个预先创建并管理线程的工具,用于复用线程,减少创建和销毁线程的开销,提高性能。常见的线程池类有 ExecutorService
。
ExecutorService pool = Executors.newFixedThreadPool(5);
pool.execute(new RunnableTask());
3. 设计模式
3.1. 解释观察者模式。
观察者模式定义了对象间的一对多依赖关系,当一个对象状态改变时,所有依赖于它的对象都会收到通知并自动更新。
3.2. 什么是代理模式?如何实现?
代理模式通过代理类控制对目标对象的访问。可以通过静态代理和动态代理来实现。
public interface Service {
void perform();
}
public class ServiceImpl implements Service {
public void perform() {
System.out.println("Service performing");
}
}
public class ServiceProxy implements Service {
private Service service;
public ServiceProxy(Service service) {
this.service = service;
}
public void perform() {
System.out.println("Proxy: before");
service.perform();
System.out.println("Proxy: after");
}
}
想要更大提升,点击使用小奈AI,免费创造无限可能