键入安全异构容器模式以存储项目列表

时间:2011-06-30 22:07:06

标签: java design-patterns generics

我正在尝试实现一个类型安全的异构容器来存储异构对象列表。

我已经看到了几个类型安全的异构容器模式(link)的exameples,但它们都存储了一个类型的单个对象。

我试图按如下方式实现它:

public class EntityOrganizer {  

    private Map<Class<?>, List<Object>> entityMap = new HashMap<Class<?>, List<Object>>();

    public <T> List<T> getEntities(Class<T> clazz) {
        return entityMap.containsKey(clazz) ? entityMap.get(clazz) : Collections.EMPTY_LIST;
    }

    private <T> void addEntity(Class<T> clazz, T entity) {
        List<T> entityList = (List<T>) entityMap.get(clazz);
        if(entityList == null) {
            entityList = new ArrayList<T>();
            entityMap.put(clazz, (List<Object>) entityList);
        }
        entityList.add(entity);
    }   
}

但问题是这段代码充满了未经检查的强制转换。有人可以帮助更好地实现这个吗?

非常感谢

3 个答案:

答案 0 :(得分:6)

问题是,什么是“未选中的演员”?

有时,演员阵容可以证明是安全的,不幸的是,证据超出了javac的能力,这只是限制了规范中列举的静态分析。但程序员比javac更聪明。

在这种情况下,我认为这些是“经过检查的演员表”,并且非常适合禁止警告。

参见其他2个相关的例子:

Heterogeneous container to store genericly typed objects in Java

Typesafe forName class loading

答案 1 :(得分:1)

你不必演员:

  

(List<T>) entityMap.get(clazz)

当你说

  

entityMap.get(clazz)

你实际上有List<Object>这足以满足你的需求。

相同
  

entityList = new ArrayList<T>();

您应该使用entityList = new ArrayList<Object>();

方法声明确保您的类型安全

<T> void addEntity(Class<T> clazz, T entity) {

并使用Map作为关键类。

因此代码应如下所示:

 private <T> void addEntity(Class<T> clazz, T entity) {
            List<Object> entityList = entityMap.get(clazz);
            if(entityList == null) {
                entityList = new ArrayList<Object>();
                entityMap.put(clazz, entityList);
            }
            entityList.add(entity);
   } 

答案 2 :(得分:0)

对于非常小的列表,您可以对Java泛型的链接列表进行编码。

And<UUID, And<Integer, Of<String>>> x = Tuple.of("test").and(2).and(UUID.randomUUID());

AndOf的类型定义有点让人费解。为简洁起见,我省略了equals / hashCode。

import java.util.Objects;
import java.util.UUID;

public abstract class Tuple<T extends Tuple<T>> {
    public static final <E> Of<E> of(E e) {
        return new Of<>(e);
    }

    public abstract <E> And<E, T> and(E e);

    public static final class And<T, R extends Tuple<R>> extends Tuple<And<T, R>> {
        public final T t;
        public final R r;

        private And(T t, R rest) {
            this.t = t;
            this.r = rest;
        }

        public <N> And<N, And<T, R>> and(N next) {
            return new And<>(next, this);
        }
    }

    public static final class Of<T> extends Tuple<Of<T>> {
        public final T t;

        private Of(T t) {
            this.t = t;
        }

        public <N> And<N, Of<T>> and(N next) {
            return new And<>(next, this);
        }
    }
}