使用变量泛型作为值的 Java Map

ami*_*rkr 0 java generics type-safety

所以这是一个有点棘手的问题(对我来说)。

我有一个通用对象。将其命名为 MyObject。该对象有一个返回 T 类型的方法:

public class MyObject<T>
{
    private T _t;

    public MyObject(T t)
    {
        _t = t;
    }

    //...

    public T get()
    {
        return _t;
    }
}
Run Code Online (Sandbox Code Playgroud)

(显然我的“MyObject”做了更多的事情,但这就是要点)。

现在,我想要一张这种类型的地图:

Map<String, MyObject<?>> m = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)

我希望能够使用一些预定义的字符串名称来获取地图,并且这些地图可以是任何 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));
Run Code Online (Sandbox Code Playgroud)

ETC。

但是 - 这是棘手的部分 - 当我从地图中获取某些值时,我希望地图“记住” MyObject 的参数化类型。使用

m.get("map_1");
Run Code Online (Sandbox Code Playgroud)

会返回一个

MyObject<Object> 
Run Code Online (Sandbox Code Playgroud)

类型,因为地图被定义为包含

MyObject<?> 
Run Code Online (Sandbox Code Playgroud)

价值观。因此:

m.get("map_1").get() // <-- This is an Object, not a String! 
Run Code Online (Sandbox Code Playgroud)

可以进行哪些修改(如果有),以便能够获得有关 MyObject 获取的对象的正确完整信息,以便调用最后一行 (m.get("map_1")) 将返回

MyObject<String>
Run Code Online (Sandbox Code Playgroud)

谢谢 :)

阿米尔。

mar*_*ace 5

Joshua Bloch 的《Effective Java》中的类型安全异构容器可能适用于此。基本上,您添加一个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; }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以做这样的事情:

public <T> T get( Map<String, MyObject<?>> map, String key, Class<T> type ) {
   return type.cast( m.get( key ).get() );
}
Run Code Online (Sandbox Code Playgroud)

这是安全的并且可以编译,但如果类型错误,则会抛出运行时错误。

(请注意,我实际上并没有编译它,所以我可能会出现语法错误。但大多数人不知道如何使用Class来转换对象。)