0

I need to know how to for loop through a Hashtable, check for cloneability on each value, and clone if possible. This Hashtable has all String keys, but the values can be of any class. I have come across the following Hashmap example on another Stack Overflow page, but I need to do this with a Hashtable. More specifically, one without brackets. (Hashtable instead of Hashtable<Type, Type>.) I have also seen examples for looping through an ArrayList and cloning each element, but I need to do this with a hashtable. I have posted two pieces of code below: the first is the HashMap example I found and the second is my current proposal and the issues I'm running into.

The HashMap

public Map<String,C> deepCopy(Map<String, C> original) {
    Map<String, C> copy = new HashMap<String, C>(original.size());
    for(Map.Entry<String, C> entry : original.entries()) {
        copy.put(entry.getKey(), entry.getValue().clone());
    }
}

My proposal

public class _HashtableCloningTest {
    public Hashtable deepClone(Hashtable original) {
        Hashtable newH = new Hashtable(original.size())
        Set<String> keys = original.keySet();
            for (String key : keys)
                if (original.get(key) instanceof Cloneable)
                    newH.put(key, original.get(key).clone());
        return newH;
    }
}

This code won't compile. The error says the clone method is on the object class, and the method on that class is protected. I need it to clone on the class of the current value, but since I as the programmer don't know that class, I don't know how to cast it to the proper class.

Any insight and help around this hurdle is greatly appreciated.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
user1567060
  • 179
  • 1
  • 3
  • 11
  • 1
    Why are you cloning arbitrary objects at all? This is generally a code smell, IME. – Matt Ball Nov 04 '13 at 05:41
  • It's the way my client wants it done. I realize there might be better ways but I need to know how to do it this way. I've been told it's possible, even if not the best solution. – user1567060 Nov 04 '13 at 05:50
  • The problem with your code is, that Cloneable is very hard to implement right, so for a lot of people it isn't the reliable way cloning you object. Read http://stackoverflow.com/questions/4081858/about-java-cloneable To solve your problem you need to know what type of instances are put in this map and cast it properly. – Christian Nov 04 '13 at 05:57
  • `Cloneable` is basically a disaster in Java. Why does your client know enough about Java to care about `Cloneable`, but not enough to know how terrible `Cloneable` is? – Matt Ball Nov 04 '13 at 06:06

1 Answers1

1

The clone() method is protected precisely to prevent you from cloning arbitrary objects, which is generally an indication that you are trying to do something strange.

It is somewhat inconvenient that Cloneable does not contain clone(). See the answer at Why is the clone() method protected in java.lang.Object? for a bit of a discussion on the matter.

See also the answer at https://stackoverflow.com/a/10083129/616460 for a few good pointers on issues with clone() in general.

In any case, if you have to do this...

One option may be to define an interface that marks objects as being able to be copied for your hash table and also provides clone(), e.g.:

public interface Copiable extends Cloneable {
    public Object clone ();
}

A second option is to create some interface that provides a method to make deep copies of an object, and have your classes implement that, e.g.:

public interface Copiable {
    public Copiable createDeepCopy ();
}

Still another option if you're desperate is to use reflection to invoke clone() on Cloneable objects. You may wish to think twice about what you are doing, though.

Community
  • 1
  • 1
Jason C
  • 38,729
  • 14
  • 126
  • 182