我有几个Map
,它们本身可能包含任何类型的Map
。我编写了一个带有以下签名的方法:
public static <K,V> HashMap<K,V> deepCopyHashMap(HashMap<K,V> s);
然而,我现在希望将这段代码概括为支持一般的Map
,但仍返回与参数相同类型的对象。因此,代码不再是:
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接口,但它只是一个标记接口(对于Map来说没有实现),对我没什么用处。
编辑: 为了参考,这是我深度复制嵌套HashMap的代码(代码可以正常工作):
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;
}
编辑:解决方案
This is not an ideal solution.. It will fail if the there is no default constructor for the runtime type of the nested
Map
. I have tested it with nestedHashMap
s and the runtime type is correctly copied.@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; }
This is much safer, but all the known types need to be listed explicitly:
@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; }