经过以下链接,即link1和link2,我面临着提供一个类文字作为参数的挑战。以下是我的代码,我得到编译错误如下:
class GenericService {
public <T> List<T> serve(Class<T> clazz) {
if(clazz == Set.class) {
Set<String> inputs = new HashSet<>();
return implement(inputs, clazz);
} else if(clazz == Map.class) {
Map<String, Object> inputs = new HashMap<>();
return implement(inputs, clazz);
}
}
public List<Set<String>> implement(Set<String> inputs, Type clazz) {
//Based on clazz decide that the output will be of type 'List<Set<String>>'
List<Set<String>> result = new ArrayList<>();
//do something with inputs
//populate result
return result;
}
public List<Map<String, Object>> implement(Map<String, Object> inputs, Type clazz) {
//Based on clazz decide that the output will be of type 'List<Map<String, Object>>'
List<Map<String, Object>> result = new ArrayList<>();
//do something with inputs
//populate result
return result;
}
}
有几点需要注意:
List.class
或Map.class
而不是指定泛型类型。基于此确定结果类型(未提供实现细节)。class literal
派生的,我得到以下编译时错误。
Type mismatch: cannot convert from List<Set<String>> to List<T>
Type mismatch: cannot convert from List<Map<String,Object>> to List<T>
我怎样才能使这个工作?
首先要做的事情。
- 我只能传递List.class或Map.class,而不是指定泛型类型。基于此确定结果类型(未提供实现细节)。
您不能在类参数中指定泛型类型,因为(仔细阅读)运行时期间不存在泛型类型信息。在运行时,你没有得到List<String>
或List<Integer>
等。在运行时,一切都只是简单的List
。
关于它为何如此的简短历史。
仿制药直到Java 5才存在。所以当仿制药作为Java 5的一部分引入时,他们最不想做的就是告诉全世界从List
改为List<String>
或List<Whatever_Object_They_Want>
。
例如,假设您使用的是使用Java 4编译的依赖项,并且此依赖项中的方法只返回普通的旧List
,您仍然可以使用您的代码调用该方法,该代码是用Java 5编译的。你不能把它强制转换为任何泛型类型。
想象一下,如果Java5开始只支持像List <>这样的泛型类型而不支持普通的旧List。您必须依赖所有供应商来提供在Java5中编译的依赖项。这会导致混乱。因此,为了避免这种情况,并保持与使用以前版本的java的向后兼容性,当代码被编译为字节代码时,通用类型信息被剥离。这叫做Type Erasure
。
正是由于这个原因,您无法使用任何集合类型的类文字指定泛型类型。
来到你的第二点
- 因为,结果类型是使用类文字派生的,我得到以下编译时错误。
类型不匹配:无法从
List<Set<String>>
转换为List<T>
类型不匹配:无法从
List<Map<String,Object>>
转换为List<T>
如果您浏览泛型文档,通用类型List
与List< Map< String, Object >>>
不同。 (这就是为什么我们在Java中使用泛型。例如,List<String>
与List<Object>
不同。你不能将List<String>
转换为List<Object>
)
但是,由于你想在某些情况下返回List<Map<>>
而在某些其他情况下返回List<Set<>>
取决于参数,我建议你将方法serve
的返回类型更改为List<? extends Collection>
使用List<? extends Collection>
作为返回类型/方法参数意味着此列表可以是Collection的任何子类的List。请查看层次结构以获取更多信息。
希望这有帮助!