Cloning with generics

后端 未结 6 484
栀梦
栀梦 2020-12-08 17:19

Once upon a time there was a class:

public class Scope> implements Comparable>, Clon         


        
相关标签:
6条回答
  • 2020-12-08 17:37

    As you see, if a class tries to implement Cloneable and you want a deep clone, then all of your constituent objects needs to be immutable, primitive, or need to also be Cloneable.

    Often, a better and easier approach is to create a copy constructor.

    public class Scope<C extends Comparable<C>> implements Comparable<Scope<C>>, Serializable {
        private C starts;
        private C ends;
        public Scope(final Scope original) {
           starts = new C(original.starts);
           ends = new C(original.ends);
           // initialize all my other fields from "original"
        }
    }
    

    and of course you need a copy constructor on C that is capable of handling polymorphism.

    If you have no access or ability to modify the source to C, then any method of copying, no matter what the method, will be very difficult and potentially impossible. For example, it is not possible to make a copy of an enum instance.

    0 讨论(0)
  • 2020-12-08 17:38

    As a general comment, avoid using Object.clone() whenever possible. If you have control over the code in question, implement a copy constructor instead. See here for information.

    0 讨论(0)
  • 2020-12-08 17:41

    Hopefully I've resolved the problem of generic cloning in Java:

    public class Generic<T> {
      private T data;
    
      public Generic() {
        // ...
      }
    
      @SuppressWarnings("unchecked")
      @Override
      public Object clone() {
        Generic<T> cloned = new Generic<T>();
        try {
          cloned.data = (T) data.getClass().getMethod("clone").invoke(data);
        } catch (Exception e) {
          // ...
        }
        return cloned;
      }
    }
    
    0 讨论(0)
  • 2020-12-08 17:47

    This is one reason why no one likes Cloneable. It's supposed to be a marker interface, but it's basically useless because you can't clone an arbitrary Cloneable object without reflection.

    Pretty much the only way to do this is to create your own interface with a public clone() method (it doesn't have to be called "clone()"). Here's an example from another StackOverflow question.

    0 讨论(0)
  • 2020-12-08 17:48

    Slightly OT, but you could save yourself a lot of future grief with this:

       catch (CloneNotSupportedException e) {
           throw new RuntimeException("Clone not supported", e);
       }
    

    So that when you get a stack trace you know which object caused the problem.

    To answer the core question, your own interface that implements a public clone() as mmyers wrote and require that C extend that as well.

    0 讨论(0)
  • 2020-12-08 17:53

    Solution

    Use the Java Deep-Cloning library.

    The cloning library is a small, open source (apache licence) java library which deep-clones objects. The objects don't have to implement the Cloneable interface. Effectivelly, this library can clone ANY java objects. It can be used i.e. in cache implementations if you don't want the cached object to be modified or whenever you want to create a deep copy of objects.

    Cloner cloner=new Cloner();
    XX clone = cloner.deepClone(someObjectOfTypeXX);
    

    Addendum

    A previous answer had the following drawbacks:

    • It adds a lot of code
    • It requires you to list all fields to be copied and do this
    • This will not work for Lists when using clone(); the clone() for HashMap notes: Returns a shallow copy of this HashMap instance: the keys and values themselves are not cloned, so you end up doing it manually.

    Serialization is also bad because it may require adding Serializable everywhere.

    0 讨论(0)
提交回复
热议问题