Если вы не клонируете на 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();
Не забывайте обрабатывать исключения и красиво закрывать потоки.