I have a few Maps that themselves again may contain Maps (of any type). I wrote a method with the signature:
public static <K,V> HashMap<K,V> deepCopyHashMap(HashMap<K,V> s);
However, I would now like to generalize this code to support Maps in general, but still return an object of the same type as the argument. So instead of:
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.
I would like something like this:
public static <K,V, M extends Map<K,V>> M<K,V> deepCopyMap(M<K,V> s);
However, this gives me:
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>
How do I properly declare the method signature and still return an object of the correct type (without using reflection internally)?
For this project adding more dependencies is really not an option, so I would prefer a solution that does not rely on external libraries. Also, I have looked into the Cloneable interface, however with it being only a marker interface (with no implementation for Maps in general) it is not of much use to me.
Edit:
For reference, this is my code for deep-copying nested HashMaps (code works properly):
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;
}
Edit: Solutions
- 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 nested- HashMaps 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; }
 
     
    