Java中泛型方法的递归调用
我正在处理下面这样的遗留代码Java中泛型方法的递归调用,java,generics,recursion,Java,Generics,Recursion,我正在处理下面这样的遗留代码 public Map myMethod(Map arg){ Map newMap = createMap(); //This method creates a new Map instance. Iterator entries = arg.entrySet().iterator(); while (entries.hasNext()) { Entry thisEntry = (Entry) entries.n
public Map myMethod(Map arg){
Map newMap = createMap(); //This method creates a new Map instance.
Iterator entries = arg.entrySet().iterator();
while (entries.hasNext()) {
Entry thisEntry = (Entry) entries.next();
Object key = thisEntry.getKey();
Object value = thisEntry.getValue();
if ( value instanceof Map){
Map newElement = myMethod((Map)value); // Recursive call here
newMap.put(key, newElement);
}else if ( value instanceof String ){
newMap.put(key, value);
}
}
return newMap;
}
显然,我想修改泛型。所以我改变了方法,比如
public <K,V> Map<K,V> myMethod(Map<K,V> arg){
Map<K,V> newMap = createMap(); //creates a new Map instance.
for ( Entry<K,V> entry : arg.entrySet()){
K key = entry.getKey();
V value = entry.getValue();
if ( value instanceof Map){
V newElement = myMethod(value); // Recursive call here
newMap.put(key, newElement);
}else if ( value instanceof String ){
newMap.put(key, value);
}
}
return newMap;
}
publicmap-myMethod(Map-arg){
Map newMap=createMap();//创建一个新的映射实例。
for(条目:arg.entrySet()){
K key=entry.getKey();
V value=entry.getValue();
if(映射的值实例){
V newElement=myMethod(value);//此处递归调用
newMap.put(键,新元素);
}else if(字符串的值实例){
newMap.put(键、值);
}
}
返回newMap;
}
我的问题是关于递归调用的行。到目前为止,我已经试过了
V newElement=myMethod(值)代码>->编译错误
Map newElement=myMethod(值)代码>->编译错误
V newElement=(V)myMethod((Map)值)代码>->类型安全警告
你的类型都搞砸了 你的方法需要一段时间
Map<K,V>
一定是
Map<K,V> newElement = myMethod(element); //element is of type Map<K,V>
意味着新元素也必须是V类型
所以你基本上需要String,Map和V来拥有一些通用的超类型。在原始代码中,Map实际上是
Map<Object, Object>
Map
所以超类型是Object
我会备份,并问自己为什么有一个同时存储地图和字符串的地图。您可能应该将它们重构为实际表示其类型的对象
例如,假设它是一个文件系统,映射是一个目录,字符串是一个文件,那么您应该真正创建一个FileObject,它可以是目录或文件,并且您的方法签名变成:
Map<K, FileObject> myMethod(Map<K, FileObject> map)
Map-myMethod(Map-Map)
代码的逻辑不是类型安全的,因此无法避免类型安全警告
您可以使用createMap()
创建一个新映射;该方法盲目地创建一个没有信息的新映射,因此它创建的映射类不一定与传入的arg
类相同。这意味着您的方法myMethod()
返回的映射不一定与传入的映射属于同一个实现类
在递归调用中,您将一个我们知道是
V
实例的映射传递到递归调用中,您希望返回的对象是V
。但这不一定是真的。例如,如果V
是TreeMap
,递归调用返回的东西是HashMap
,该怎么办?那么它应该不能转换为V
,并且您无法从中安全地获得V
。您确定值
是正确类型的映射吗?然后转换为该类型并忽略警告。问题是V
可以是String
或Map
本身递归<代码>映射将起作用,并且您将需要强制转换(带有安全警告,无法针对该警告执行任何操作)旁注:您的旧代码不在此处编译:映射新元素=myMethod(值)代码>因为值
是一个对象,而不是映射
@njzk2 I编辑。谢谢。因为这个方法被其他应用程序使用(超过100次调用这个方法),而且它是一种库方法,所以我不能改变异构元素的性质。这实际上是原始方法的简化版本。参数映射将整数、列表、双精度、映射作为元素。那么泛型在这里就帮不了你。您需要强制转换,它将被取消选中并发出警告。编译器无法事先知道V是否真的是正确的类型。有意义。假设我将createMap()更改为createMap(arg),它返回给定参数的新实例,那么该方法是否是类型安全的,并且我可以强制使用泛型?@exiter2000:这样会更安全。但是,即使您更改了方法的签名,我也不确定您是否可以避免未经检查的强制转换。
newMap.put(key, newElement);
Map<Object, Object>
Map<K, FileObject> myMethod(Map<K, FileObject> map)