题目
设计一个通用的类型安全缓存类
信息
- 类型:问答
- 难度:⭐⭐
考点
泛型类定义,类型擦除,泛型边界,类型安全
快速回答
实现要点:
- 使用泛型类
GenericCache<T>确保类型安全 - 通过
Map<String, T>存储数据 - 添加
<T extends Cacheable>边界限制 - 实现
put/get方法并处理空值 - 注意类型擦除对运行时类型检查的影响
问题背景
在实际开发中,经常需要实现缓存功能。使用泛型可以创建类型安全的缓存类,避免强制类型转换错误,同时保证代码复用性。
解决方案
// 定义缓存对象接口
interface Cacheable {
String getId();
}
// 泛型缓存类实现
public class GenericCache<T extends Cacheable> {
private final Map<String, T> cache = new HashMap<>();
public void put(T item) {
if (item == null) throw new IllegalArgumentException("Item cannot be null");
cache.put(item.getId(), item);
}
public T get(String id) {
return cache.get(id);
}
public void remove(String id) {
cache.remove(id);
}
}
// 使用示例
class User implements Cacheable {
private String id;
private String name;
public User(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getId() { return id; }
}
public class Main {
public static void main(String[] args) {
GenericCache<User> userCache = new GenericCache<>();
userCache.put(new User("U1", "Alice"));
// 类型安全获取(无需强制转换)
User user = userCache.get("U1");
// 错误示例(编译时报错)
// Integer num = userCache.get("U1");
}
}核心原理
- 类型安全:泛型在编译时检查类型一致性,避免
ClassCastException - 类型擦除:运行时泛型类型信息被擦除,
GenericCache<User>和GenericCache<Product>的 Class 对象相同 - 边界限制:
<T extends Cacheable>确保只有实现指定接口的类型可用
最佳实践
- 始终使用泛型类型参数声明变量(如
Map<String, T>) - 对可能为 null 的返回值进行显式处理
- 在泛型类中避免使用原始类型(Raw Types)
- 优先使用接口(如
Cacheable)定义边界
常见错误
- 忽略空值检查:
cache.get("invalid")返回 null 可能导致 NPE - 错误处理类型擦除:尝试在运行时获取泛型类型(如
if(data instanceof T)) - 不当使用原始类型:
GenericCache rawCache = new GenericCache();会绕过类型检查
扩展知识
- 通配符:使用
GenericCache<? extends Cacheable>增加灵活性 - 类型令牌:通过
Class<T>参数保留类型信息(如class GenericCache<T> { private Class<T> type; }) - 泛型方法:在静态方法中使用独立泛型参数(如
<U> void mergeCache(GenericCache<U> other))