Item #29提供了一种实现“类型安全”异构集合的方法,基本上可以归结为:
public Class HeterogeneousContainer {
private Map<Class<?>, Object> container = new HashMap<>();
public <T> put(Class<T> type, T instance) {
container.put(type, instance);
}
public <T> T get(Class<T> type) {
//essentially just
// return (T) container.get(type);
return type.cast(container.get(type));
}
}
然后(我推测)将这样使用(由制作人):
List<HeterogeneousContainer> resultSet = new ArrayList<>();
...
resultSet.add(new HeterogeneousContainer());
...
resultSet.get(rowIndex).add(Column1.class, column1Value);
resultSet.get(rowIndex).add(Column2.class, column2Value);
...
并且像这样(由消费者):
for(HeterogeneousContainer row:resultSet) {
Column1 column1Value = row.get(Column1.class);
Column2 column2Value = row.get(Column2.class);
...
//do something with the columnValues
}
我现在的问题是为什么这被认为类型安全?这比仅仅将列名放入地图还是仅使用常规List
/ List<Object>
并按索引查找列更好?
这是否有效/实际上以任何方式改进了JDBC ResultsSets的.getString / .getInt / .getXXXX方法?
答案 0 :(得分:5)
这个类被认为是类型安全的,因为即使它在运行时进行类转换,这种不安全的行为也会被封装,你无法观察它。
container
字段是私有的,因此在考虑类型安全时,您只需要检查此类中的代码。put
方法会插入一对类型标记T
和类型为T
的元素。这是唯一更新container
的地方,并且(在编译时)保证插入的元素具有正确的类型标记。get
方法以不安全的方式进行类投射(return type.cast(container.get(type))
),但只要确保container
仅通过put
,它不会失败。在上面我们看到put
当然是唯一的方法,这个类对于其用户来说是类型安全。说实话,如果你真的想要,你可以打破这个类的类型安全性,例如使用反射。通常情况下这并不重要,因为你想要为意外滥用而不是故意损坏来保护你的课程。但是,当您进一步阅读 Effective Java 时,您将看到防范此类攻击的过程要复杂得多。