让我们说我想要某种类似
的缓存Map<Class<T extends SomeBaseClass>, List<T>> cache = new ...
当我尝试这样做时会抛出编译错误。我不想让他们成为我工作的班级的仿制药,因为他们不属于那里。我也会有很多种不同的T.但是我也不想使用<? extends SomeBaseClass>
,因为你没有编译时保证进入的列表与映射到它的类相同类型......
我有什么选择?这些条款在这里过度使用,在谷歌我似乎无法搜索它们: - (
答案 0 :(得分:3)
没有选择。这是不可避免的,虽然你可以将它包装在你自己的隐藏类型转换的API中......但是在编译时没有办法在Java中保证这种东西。
也就是说,您可以创建一个在外部使用的类型安全的API,并在内部禁止警告。 (@ysdx建议查看Guava的ClassToInstanceMap,这确实是一个很好的例子。)但是你不会得到内部类型安全的东西:将会被施放里面。
答案 1 :(得分:3)
我也会有很多种不同的T。
如果我理解正确,你想要的是使用泛型以某种方式保证地图中的每个条目都将Class对象与相关类的某个对象相关联。
泛型无法做到这一点。让我们引用你的代码片段:
Map<Class<T extends SomeBaseClass>, List<T>> cache = new ...
看起来您希望Map
中的每个条目都将Class
对象与该类的实例相关联。好吧,泛型无法做任何事情来帮助你,因为T
中的类型参数Map<Class<T>,T>
将具有一个且仅当一个类型替换它时类型专用于特定T
}。这意味着该类的专用Map<Class<Foo>,Foo>
版本将具有带此签名的方法:
public Set<Map.Entry<Class<Foo>,Foo>> entries();
您从Map.Entry<Class<Foo>,Foo>>
的{{1}}方法中获得的Set
引用将包含以下方法:
iterator
在这种情况下,public Class<Foo> getKey();
public Foo getValue();
只有一个值,它是Class<Foo>
类的类对象。但是如果我们按照你的例子使用Foo
并没有真正增加太多; Class<T extends SomeBaseClass>
会为您提供一些getKey()
对象,其Class
方法会生成可以投放到newInstance
的内容,但无法保证Foo
会让您获得相同运行时类的值,甚至可以转换为与getValue()
返回的类相同的类的类。
编辑:你可能想要这样的东西(未经测试,甚至没有尝试过编译):
getKey()
在您使用public class InstanceTable {
private final Map<Class,Object> table =
new ConcurrentHashMap<Class,Object>();
public <T> void put(Class<T> klass, T value)
throws ClassCastException {
table.put(klass.cast(value));
}
public <T> T get(Class<T> klass) {
return klass.cast(table.get(klass))
}
}
语法静态命名源代码中使用的类的情况下,这提供了编译时类型安全 :
Foo.class
但要明白,除此之外,它没有使用类型系统在编译时强制执行你想要的不变量 - 它仍在运行时检查它(对Class.cast()
的调用)。
答案 2 :(得分:0)
所以你想要一张
的地图String.class --> list of strings
Int.class --> List of Integers
好的,没有概率。但是:在地图的特定实例中:
Map<K, V> x = …;
具体的特定班级是什么?你想让它同时成为不同的一部分,这不会发生。
你将不得不做一些演员。
答案 3 :(得分:0)
我已在TypedMap
:http://blog.pdark.de/2010/05/28/type-safe-object-map/
以下是一些演示代码:
TypedMap map = new TypedMap();
String expected = "Hallo";
map.set( KEY1, expected );
String value = map.get( KEY1 ); // Look Ma, no cast!
assertEquals( expected, value );
List<String> list = new ArrayList<String> ();
map.set( KEY2, list );
List<String> valueList = map.get( KEY2 ); // Even with generics
assertEquals( list, valueList );
魔法在关键:
final static TypedMapKey<String> KEY1 = new TypedMapKey<String>( "key1" );
final static TypedMapKey<List<String>> KEY2 = new TypedMapKey<List<String>>( "key2" );