我需要一个包含
的Map容器
Item Object
或
List<Item> Object
作为它的价值,而且我可以在没有施放的情况下得到它,是否可能?
答案 0 :(得分:3)
简短回答:不。
Java中不存在 Union types。为了获得编译时类型检查,你可以做的最接近的事情是创建一些包含 A
或List<A>
的自定义包装类的列表,如下:
public class UnionListWrapper<A> {
private final A item;
private final List<A> list;
public UnionListWrapper(A value) {
item = value;
list = null;
}
public UnionListWrapper(List<A> value) {
item = null;
list = value;
}
public Object getValue() {
if (item != null) return item;
else return list;
}
}
至少你不能创建这个类的实例,这些实例不是A
或List<A>
,但是将值重新输出将会仍然必须只是Object
,与关联铸造。这可能会非常笨拙,总的来说可能不值得。
在实践中,我可能只有一个List<Object>
,并且对于接受哪些数据类型非常谨慎。问题是即使是运行时检查(次优)也是不可能的,因为Java的通用擦除意味着你不能在运行时进行instanceof A
检查(在通用参数上加倍) List
)。
答案 1 :(得分:3)
不,你不能以类型安全的方式做到这一点。
从设计的角度来看,我建议仅使用List<Item>
作为值。如果其中一些是单元素列表,那就没问题;如果以相同的方式处理所有值,您的代码可能会更加清晰。
事实上,我很好奇你打算如何使用带有元素和元素列表的地图。您是否知道某个给定密钥的先验类型?
答案 2 :(得分:2)
听起来你想要一个MultiMap - 有一个Apache implementation和一个Google implementation
答案 3 :(得分:1)
可能是您正在寻找的类型安全的异构容器模式
解决下面评论中提到的优点:重新键入擦除 - 使用超类型令牌。取自http://gafter.blogspot.com/2007/05/limitation-of-super-type-tokens.html,突出了该方法的问题。
import java.lang.reflect.*;
public abstract class TypeRef<T> {
private final Type type;
protected TypeRef() {
ParameterizedType superclass = (ParameterizedType)
getClass().getGenericSuperclass();
type = superclass.getActualTypeArguments()[0];
}
@Override public boolean equals (Object o) {
return o instanceof TypeRef &&
((TypeRef)o).type.equals(type);
}
@Override public int hashCode() {
return type.hashCode();
}
}
public class Favorites2 {
private Map<TypeRef<?>, Object> favorites =
new HashMap< TypeRef<?> , Object>();
public <T> void setFavorite(TypeRef<T> type, T thing) {
favorites.put(type, thing);
}
@SuppressWarning("unchecked")
public <T> T getFavorite(TypeRef<T> type) {
return (T) favorites.get(type);
}
public static void main(String[] args) {
Favorites2 f = new Favorites2();
List<String> stooges = Arrays.asList(
"Larry", "Moe", "Curly");
f.setFavorite(new TypeRef<List<String>>(){}, stooges);
List<String> ls = f.getFavorite(
new TypeRef<List<String>>(){});
}
}
答案 4 :(得分:0)
不是没有编写包含单个A或List的包装类(WrapsA),并且使列表成为List
答案 5 :(得分:0)
Functional Java提供了一个名为Either<A, B>
的不相交联合数据类型,因此您可以定义Map<Key, Either<Item, List<Item>>>
。