所以这对我来说是个棘手的问题。
我有一个通用对象。称之为MyObject。该对象有一个返回T:
类型的方法public class MyObject<T>
{
private T _t;
public MyObject(T t)
{
_t = t;
}
//...
public T get()
{
return _t;
}
}
(显然我的&#34; MyObject&#34;做得多一些,但这是要点)。
现在,我想要一张这种类型的地图:
Map<String, MyObject<?>> m = new HashMap<>();
我希望能够使用一些预定义的字符串名称来获取地图,这些地图可以是任何MyObject。例如,我可以打电话:
m.put("map_1", new MyObject<String>("String"));
m.put("map_2", new MyObject<Integer>(new Integer(3));
m.put("map_3", new MyObject<Long>(new Long(5));
等
但是 - 这是棘手的部分 - 我希望地图能够记住&#34;当我从地图中获取一些值时,MyObject的参数化类型。使用
m.get("map_1");
会返回
MyObject<Object>
类型,因为地图被定义为包含
MyObject<?>
值。因此:
m.get("map_1").get() // <-- This is an Object, not a String!
可以进行哪些修改(如果有的话),以便能够获得有关MyObject获取对象的正确 - 完整信息,以便调用最后一行(m.get(&#34; map_1&#34; ))会返回
MyObject<String>
谢谢:)
阿米尔。
答案 0 :(得分:3)
来自Joshua Bloch的 Effective Java 的Typesafe异构容器可能适用于此处。基本上你添加一个Class
对象来表示类型。
public class MyObject<T>
{
private T _t;
private Class<T> type;
public MyObject( Class<T> type, T t)
{
_t = t;
this.type = type;
}
//...
public T get()
{
return _t;
}
public Class<T> getType() { return type; }
}
然后你可以这样做:
public <T> T get( Map<String, MyObject<?>> map, String key, Class<T> type ) {
return type.cast( m.get( key ).get() );
}
哪个是安全的并且会编译,但是如果你输入的类型错误会抛出运行时错误。
(注意我实际上没有编译它,所以我可能会出现语法错误。但大多数人都不知道如何使用Class
来投射对象。)
答案 1 :(得分:0)
你可以上课。
Class c = m.get("map_1").get().getClass();
if (String.class.equals(c)) {
System.out.println("its a String");
}
这是一个完整的测试。
public class GenericsTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Map<String, MyObject<?>> map = new HashMap<>();
MyObject<String> obj = new MyObject<>("hello");
map.put("greeting", obj);
Class c = map.get("greeting").get().getClass();
if (String.class.equals(c)) {
System.out.println("its a String");
}
}
static class MyObject<T> {
T t;
public MyObject(T t) {
this.t = t;
}
T get() {
return t;
}
}
}
答案 2 :(得分:0)
类型系统只知道类型而不是对象,因此无法区分"key1"
和"key2"
,因为它们都是String
类型。
如果键具有不同的类型,最简单的方法是封装弱类型的映射,并使用反射强制转换来向编译器证明类型是正确的:
class Favorites {
private Map<Class<?>,?> map = new HashMap<>();
<V> V get(Class<V> clazz) {
return clazz.cast(map.get(clazz));
}
<V> void put(Class<V> clazz, V value) {
map.put(clazz, value);
}
}
Favorites favs = new Favorites();
favs.put(String.class, "hello");
favs.put(Integer.class, 42);
favs.get(String.class).charAt(1);