为什么“TypeToken Collections”被认为是Typesafe? (有效的Java#29)

时间:2014-02-25 23:07:27

标签: java generics collections type-safety parametric-polymorphism

Effective Java中的

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方法?

1 个答案:

答案 0 :(得分:5)

这个类被认为是类型安全的,因为即使它在运行时进行类转换,这种不安全的行为也会被封装,你无法观察它。

  • container字段是私有的,因此在考虑类型安全时,您只需要检查此类中的代码。
  • put方法会插入一对类型标记T 类型为T的元素。这是唯一更新container的地方,并且(在编译时)保证插入的元素具有正确的类型标记。
  • get方法以不安全的方式进行类投射(return type.cast(container.get(type))),但只要确保container仅通过put,它不会失败。在上面我们看到put当然是唯一的方法,这个类对于其用户来说是类型安全。

说实话,如果你真的想要,你可以打破这个类的类型安全性,例如使用反射。通常情况下这并不重要,因为你想要为意外滥用而不是故意损坏来保护你的课程。但是,当您进一步阅读 Effective Java 时,您将看到防范此类攻击的过程要复杂得多。