【发布时间】:2013-12-18 06:44:36
【问题描述】:
我有几个Maps,它们本身可能又包含Maps(任何类型)。我写了一个带有签名的方法:
public static <K,V> HashMap<K,V> deepCopyHashMap(HashMap<K,V> s);
但是,我现在想概括此代码以支持Maps,但仍返回与参数相同类型的对象。所以而不是:
public static <K,V> HashMap<K,V> deepCopyHashMap(HashMap<K,V> s);
public static <K,V> CheckedMap<K,V> deepCopyCheckedMap(CheckedMap<K,V> s);
public static <K,V> TreeMap<K,V> deepCopyTreeMap(TreeMap<K,V> s);
...
etc.
我想要这样的东西:
public static <K,V, M extends Map<K,V>> M<K,V> deepCopyMap(M<K,V> s);
但是,这给了我:
Multiple markers at this line
- The type M is not generic; it cannot be parameterized with arguments <K,
V>
- The type M is not generic; it cannot be parameterized with arguments <K,
V>
如何正确声明方法签名并仍然返回正确类型的对象(内部不使用反射)?
对于这个项目,添加更多依赖项确实不是一种选择,所以我更喜欢不依赖外部库的解决方案。另外,我研究了Cloneable 接口,但是它只是一个标记接口(一般没有实现Maps),它对我没有多大用处。
编辑:
作为参考,这是我用于深度复制嵌套HashMaps 的代码(代码可以正常工作):
public static <K,V> HashMap<K,V> deepCopyHashMap(HashMap<K,V> source){
HashMap<K,V> result = new HashMap<K, V>();
for(Map.Entry<K, V> entry : source.entrySet()){
K k = entry.getKey();
V v = entry.getValue();
if(k instanceof HashMap<?,?>){
k = (K) deepCopyHashMap((HashMap<?,?>) k);
}
if(v instanceof HashMap<?,?>){
v = (V) deepCopyHashMap((HashMap<?,?>) v);
}
result.put(k, v);
}
return result;
}
编辑:解决方案
-
这不是一个理想的解决方案。如果嵌套
Map的运行时类型没有默认构造函数,它将失败。我已经用嵌套的HashMaps 对其进行了测试,并且运行时类型被正确复制。@SuppressWarnings("unchecked") public static <K,V, M extends Map<K,V>> M deepCopyMap(M source) throws InstantiationException, IllegalAccessException{ M result = (M) source.getClass().newInstance(); for(Map.Entry<K, V> entry : source.entrySet()){ K k = entry.getKey(); V v = entry.getValue(); if(k instanceof Map<?,?>){ k = (K) deepCopyMap((Map<?,?>) k); } if(v instanceof Map<?,?>){ v = (V) deepCopyMap((Map<?,?>) v); } result.put(k, v); } return result; } -
这样更安全,但所有已知类型都需要明确列出:
@SuppressWarnings("unchecked") public static <K,V, M extends Map<K,V>> M deepCopyMap(M source){ M result; if(source instanceof HashMap){ result = (M) new HashMap<K,V>(); } else { //fail } // etc. add more types here for(Map.Entry<K, V> entry : source.entrySet()){ K k = entry.getKey(); V v = entry.getValue(); if(k instanceof Map<?,?>){ k = (K) deepCopyMap((Map<?,?>) k); } if(v instanceof Map<?,?>){ v = (V) deepCopyMap((Map<?,?>) v); } result.put(k, v); } return result; }
【问题讨论】:
-
好问题!条理清晰,条理清晰!
标签: java generics map deep-copy