[英]Recursive call with Generic method in Java
我正在处理如下的旧代码
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;
}
我的问题是关于递归调用的行。 到目前为止,我已经尝试过
V newElement = myMethod(value);
->编译错误 Map<K,V> newElement = myMethod(value);
->编译错误 V newElement = (V) myMethod((Map<?,?>)value);
->输入安全警告 ---------编辑----------
我可以做的进一步假设是
代码的逻辑不是类型安全的,因此无法避免类型安全警告。
您可以使用createMap()
创建一个新地图; 该方法正在盲目创建新地图,没有任何信息,因此它创建的地图类不必与传入的arg
类相同。这意味着您的方法myMethod()
返回的地图不一定是与传入的类相同的实现类。
在递归调用中,您将一个我们知道是V
的实例的映射传递到递归调用中,并且您希望返回的对象是V
但这不一定是正确的。 例如,如果V
是TreeMap
,而递归调用返回的是HashMap
呢? 这样它就不能转换为V
,并且您不可能从中安全地获得V
您的类型都在这里弄乱了。
您的方法需要
Map<K,V>
并返回一个
Map<K,V>
那意味着电话
V newElement = myMethod(element);
一定是
Map<K,V> newElement = myMethod(element); //element is of type Map<K,V>
和电话
newMap.put(key, newElement);
表示newElement也必须为V类型。
因此,您基本上都需要String,Map和V来具有某种通用的超级类型。 在原始代码中,Map实际上是
Map<Object, Object>
所以超级类型是Object。
我会备份并问自己,为什么您有一个同时存储Maps和Strings的映射。 您可能应该将它们重构为实际代表其类型的对象。
例如,假设它是一个文件系统,而Map是一个目录,而String是一个文件,那么您实际上应该创建一个既可以是目录也可以是文件的FileObject,并且您的方法签名变为:
Map<K, FileObject> myMethod(Map<K, FileObject> map)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.