我有一个指定为:MyClass< U>的POJO,其中U是泛型类型参数.
我正在尝试编写一个实用方法,它接受类引用Class< T>并填充Map< String,T>类型的地图(接受填充的地图).
我正在尝试编写一个实用方法,它接受类引用Class< T>并填充Map< String,T>类型的地图(接受填充的地图).
这种方法实现如下:
static void populateMap(Map<String,T> map,Class<T> type) { ... // Parses into the specified type and returns an object of that type. T obj = parse(...,type); map.put (key,obj); ... return map; }
编译好了.在我的调用者中,我尝试使用任何MyClass实例(无论类型)填充地图作为值.因此我使用以下代码:
// Loses type information Map<String,MyClass<?>> m = new HashMap<>(); populateMap(m,MyClass.class);
这不编译.编译错误:
The method
populate(Map<String,T>,Class<T>)
in the type … is not applicable for the arguments(Map<String,MyClass<?>>,Class<MyClass>)
我怎样才能解决这个问题?
解决方法
在这种情况下,对Class< MyClass<?>>进行未经检查的强制转换应该是安全的:
// This is okay because we're switching to a type with an unbounded wildcard - // the behaviors of Class.newInstance and Class.cast are still safe. @SuppressWarnings("unchecked") Class<MyClass<?>> classWithNarrowedType = (Class<MyClass<?>>)(Class<?>)MyClass.class; populateMap(m,classWithNarrowedType);
这是一个非常重要的解决方案,特别是如果你有很多像这样的调用网站,但是没有解决类文字用原始类型参数化的事实,使它们被用作参数化类型的工厂,如MyClass< T>本质上很尴尬.
一个可能更清晰的解决方案是将populateMap与类文字的使用分离:
interface Parser<T> { T parse(); } static void populateMap(Map<String,Parser<T> parser) { ... } ... Map<String,MyClass<?>> m = new HashMap<>(); Parser<MyClass<?>> myClassParser = new Parser<MyClass<?>>() { @Override public MyClass<?> parse() { return parse(...,MyClass.class); } }; populateMap(m,myClassParser);
另外,我建议使用更灵活的签名(有关详细信息,请参阅What is PECS (Producer Extends Consumer Super)?):
static void populateMap(Map<String,? super T> map,Parser<T> parser)