Если вы не клонируете на Java, что вы делаете и как вы это называете?

Есть ли у кого-нибудь предлагаемые или установленные рекомендации и соглашения об именах для конструкторов копирования / factory методов и т.д. в Java? В частности, скажем, у меня есть класс Thing, и я хочу, чтобы метод где-то возвращал новый Thing с тем же значением, что и Thing, переданным (или в качестве экземпляра, если это метод экземпляра). У вас есть это как конструктор или статический метод factory или метод экземпляра? Как бы вы это назвали?

В соответствии с заголовком я хочу избежать clone() и Cloneable.

Ответ 1

Эффективная Java рекомендует одно из следующих действий:

  • Конструктор копирования (как отмечают другие):

    public Item (Item item)

  • Метод копирования factory:

    public static Item newInstance (элемент позиции)

(Кроме того, не копирование для неизменяемых)

Основное отличие состоит в том, что С# 1 вы выбираете фактический класс результата, а С# 2 разработчик может вернуть подкласс. Семантика этого класса может привести вас к лучшему.

Ответ 2

Я бы назвал его методом копирования или конструктором копирования (в зависимости от обстоятельств). Если бы это был статический метод, я бы назвал его factory.

С точки зрения того, что делать, наиболее гибким и долговечным вариантом является конструктор копирования. Это дает подклассам возможность копировать себя так же, как родительский.

Ответ 3

Я бы сделал конструктор

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

тогда, когда вы хотите клонировать его

Thing copy = new Thing(copy from me);

Ответ 4

Вы можете перезаписать clone() -метод, если хотите. Другая используемая практика - это конструктор, который принимает объект этого типа, т.е. новый ArrayList (другой список).

Ответ 5

У вас есть несколько вариантов, реализуйте Cloneable, добавьте конструктор копирования, но мой предпочтительный способ - использовать метод (статический или экземпляр), который имеет имя, которое описывает, что делает операция копирования, - это это глубокая или мелкая копия и т.д.

Ответ 6

Используйте неизменяемые структуры данных. Единственная причина, по которой вы чувствуете, что вам нужно clone(), - это то, что вы мутируете свои объекты на своем месте. Перестань. Подумайте, как вы можете:

  • Сделайте свои классы окончательными.
  • Сделать поля в своих классах окончательными и частными.

Например, здесь "сеттер" для неизменяемого трехмерного векторного объекта:

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

Итак, я думаю, что я говорю... Я использую конструкторы копирования вместо мутации, и я просто называю их в соответствии с атрибутом, который я хочу изменить.

Ответ 7

Другой вариант - реализовать метод копирования в исходном объекте, например:

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

    void copyCoordsTo(Has3DCoords dest);
}

Затем вы должны выполнить копирование с помощью фрагмента кода, например:

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;
    }
}

Это может быть полезно, если:

  • Не имеет смысла клонировать весь объект
  • Существует группа связанных свойств, которые часто копируются как одна единица
  • Вы не хотите раскрывать loc как свойство Thing
  • Количество свойств велико (или таких групп много), поэтому конструктор, который потребовал бы все из них в качестве параметров, был бы громоздким.

Ответ 8

Это не самый приятный подход к копированию объектов, но иногда полезно, если вы хотите выполнить глубокую копию объекта Serializable. Это позволяет избежать необходимости писать копии, выполнять клонирование или писать классы factory.

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();

Не забывайте обрабатывать исключения и красиво закрывать потоки.