4

Effective Java 中的第 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 方法?

4

1 回答 1

5

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

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

说实话,如果你真的想要,你可以打破这个类的类型安全,例如使用反射。通常这无关紧要,因为你想保护你的类被意外滥用而不是故意损坏。但是,当您进一步阅读Effective Java时,您会发现防御此类攻击要复杂得多。

于 2014-02-26T00:10:16.323 回答