我正在尝试实现一个类型安全的异构容器来存储异构对象列表。
我已经看到了几个类型安全的异构容器模式(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);
}
}
但问题是这段代码充满了未经检查的强制转换。有人可以帮助更好地实现这个吗?
非常感谢
答案 0 :(得分:6)
问题是,什么是“未选中的演员”?
有时,演员阵容可以证明是安全的,不幸的是,证据超出了javac的能力,这只是限制了规范中列举的静态分析。但程序员比javac更聪明。
在这种情况下,我认为这些是“经过检查的演员表”,并且非常适合禁止警告。
参见其他2个相关的例子:
Heterogeneous container to store genericly typed objects in Java
答案 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());
And
和Of
的类型定义有点让人费解。为简洁起见,我省略了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);
}
}
}