Are there any alternatives to implementing Clone in Java?

前端 未结 5 1164
醉酒成梦
醉酒成梦 2021-01-12 15:10

In my Java project, I have a vector of various types of Traders. These different types of traders are subclasses of the Trader class. Right now, I have a method that takes a

相关标签:
5条回答
  • 2021-01-12 15:35

    Just add an abstract copy method. You can use covariant return types so that the derived type is specified to return a derived instance, which may or may not be important.

    public interface Trader {
        Trader copyTrader();
        ...
    }
    
    
    public final class MyTrader implements Trader {
        MyTrader copyTrader() {
            return new MyTrader(this);
        }
        ...
    }
    

    Sometimes you might want to generically deal with a collection of derived type of Trader that needs to clone and then return the a properly typed collection. For that you can use generics in an idiomatic way:

    public interface Trader<THIS extends Trader> {
        THIS copyTrader();
        ...
    }
    
    
    public final class MyTrader implements Trader<MyTrader> {
        public MyTrader copyTrader() {
            return new MyTrader(this);
        }
        ...
    }
    
    0 讨论(0)
  • 2021-01-12 15:39

    One option: If you can make the objects serializable, you can serialize then deserialize it to make a copy, similar to what happens when passing an object over RMI.

    Quick copy method:

    public MyObject copy() {
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;
        try {
            ByteArrayOutputStream bos =  new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            oos.flush();
            ByteArrayInputStream bin =
                new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bin);
            return (MyObject)ois.readObject();
        } catch(Exception e) {
            return null;
        } finally {
            try {
                oos.close();
                ois.close();
            } catch (Exception e) {
                return null;
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-12 15:48

    One way is to make it a final class like Java's own String, which will make any change to an object of class Trader to create a new copy in memory, but it will make it impossible to subclass it.

    Another (better) way is to use a factory method to create and copy Trader objexts, which implies that you must not allow for the default constructor to be used i.e. make it a private. This way you can control the number of instances the class has. See http://en.wikipedia.org/wiki/Factory_method

    public class Trader {
    
        /* prevent constructor so new cant be used outside the factory method */
        private Trader() {
        }
    
        /* the factory method */
        public static Trader createTrader(int whatKindOfTrader) {
    
            switch (whatKindOfTrader) {
            case 0:
                return new Trader1(); // extends Trader
            case 1:
            default:
                return new Trader2(); // extends Trader
            }
            return new Trader3(); // or throw exception
        }
    }
    

    You might even specify another overloaded method, or a second argument that takes one Trader and copies it into a new one, thus replacing clone. Btw, you might want to override the clone() method and throw CloneNotSupportedException, to prevent default Object cloning.

    0 讨论(0)
  • 2021-01-12 15:54

    Uri's right, polymorphism with state opens up a big can of worms.

    I think subclassing Cloneable and overrideing clone() is probably the simplest way to go. You can, I believe, make the return type covariant.

    0 讨论(0)
  • 2021-01-12 15:56

    I am a little unclear as to why you would want to store 50 or so clones of the same object unless they the original trader serves as a prototype (see pattern) for later traders.

    If you want to make an exact copy of an object, you have to take into account the issue of polymorphism. If people subclassing your given class are allowed to add state members, then you already have enough of a headache with functions like equals and compareTo, that clone is jut one more case where you need to require special handling.

    I disagree that clone is always evil, it is sometimes necessary. However, in situations of subclassing, a lot of things become tricky.

    I would recommend you read (when you get a chance) Bloch's "Effective Java", which covers a lot of his topics. Bracha's view is that it is not a good idea to let others extend your classes, and that if you do, you need to document very well what they would have to do and hope that they follow your instructions. There really isn't a way to bypass that. You may also want to make your Traders immutable.

    Go ahead an implement Clone normally, and indicate very clearly in the class header that anybody inheriting from your Trader and adding state members must implement X methods (specify which).

    Finding tricks to bypass an actual Cloneable and still Clone isn't going to overcome the problem of inheritance. There is no silver bullet here.

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