简体   繁体   中英

If you don't clone in Java then what do you do and what do you call it?

Does anyone have any suggested or established best practices and naming conventions for copy constructors / factory methods etc in Java? In particular, say I have a class Thing and I want a method somewhere that returns a new Thing with the same value as a Thing passed in (or as the instance if it's an instance method). Would you have this as constructor or a static factory method or instance method? What would you call it?

As per the title, I want to avoid clone() and Cloneable .

Effective Java recommends either of the following:

  1. A copy constructor (as noted by others):

    public Item(Item item)

  2. A copy factory method:

    public static Item newInstance(Item item)

(Also, no copying for immutables)

The primary difference is that with #1 you choose the actual class of the result, and with #2 the implementer can return a subclass. The semantics of the class may guide you into which one is best.

I would call it a copy method or a copy constructor (as the case may be). If it was a static method, then I would call it a factory.

In terms of what to do, the most flexible and long living option is a copy constructor. This gives subclasses the ability to copy themselves just like the parent.

I'd do a constructor

...
public Thing(Thing copyFrom)
{
    attr1 = copyFrom.attr1;
    attr2 = copyFrom.attr2;
    //etc...
}

then when you want to clone it

Thing copy = new Thing(copy from me);

You can overwrite the clone() -method, if you want. Another used practice is a constructor, that takes an object of this type, ie new ArrayList(anotherList) .

您有一些选择,实现Cloneable ,添加一个复制构造函数,但是我的首选方式是使用一个名称(描述静态操作)的方法(静态或实例)-是深层还是浅层复制等

Use immutable data structures . The only reason you feel that you need clone() is that you're mutating your objects in place. Stop doing that. Think about how you can:

  • Make your classes final.
  • Make fields in your classes final and private.

For example, here's a "setter" for an immutable 3D vector object:

public Vector3D setX(double x) {
  return new Vector3D(x, this.y, this.z);
}

So I guess what I'm saying is... I use copy constructors instead of mutation, and I just name them according to the attribute that I want to modify.

Another option is to implement the copying method in the source object, eg:

interface Has3DCoords {
    void setLocation(double x, double y, double z);

    void copyCoordsTo(Has3DCoords dest);
}

You would then implement copying with a piece of code like:

class Thing implements Has3DCoords {
    private Point3D loc;
    // ...

    void setLocation(double x, double y, double z) {
        loc.setLocation(x, y, z);
        // or: loc = new Point3D(x, y, z);
    }

    void copyCoordsTo(Has3DCoords dest) {
        loc.copyCoordsTo(dest);
        // or: dest.setLocation(loc.getX(), loc.getY(), loc.getZ());
    }

    OtherThing createOtherThing() {
        OtherThing result = new OtherThing();
        this.copyCoordsTo(result);
        return result;
    }
}

This can be useful if:

  • It does not make sense to clone the whole object
  • There is a group of related properties that are often copied as one unit
  • You do not want to expose loc as a property of Thing
  • The number of properties is large (or there are many such groups) so a constructor that required all of them as parameters would be unwieldy.

This is not the nicest approach to copying objects but the following is sometimes useful if you wish to perform a deep copy of a Serializable object. This avoids having to write copy constuctors, implement Cloneable or writing factory classes.

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);

//Serializes the input object
oos.writeObject(input);

ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);

//Copy of the input object
Object output = ois.readObject();

Don't forget to handle the exceptions and to close the streams nicely.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM