Для создания хорошо документированного кода требуется меньше времени, чем для плохо документированного кода
Когда я говорю хорошо документирован , я имею в виду комментарии, которые сообщают о вашем намерении. четко на каждом шагу. Да, ввод комментариев занимает некоторое время. И да, ваши коллеги должны быть достаточно умны, чтобы понять, что вы хотели, просто прочитав вашу описательную функцию и имена переменных и тщательно продумав все свои исполняемые операторы. Но на это уходит больше времени, чем если бы вы только что объяснили свои намерения, и ясная документация особенно полезна, когда логика кода оказывается неверной. Не то чтобы ваш код был бы неверным ...
Я твердо верю, что если вы рассчитываете время от начала проекта до поставки бездефектного продукта, написание хорошо документированного кода займет меньше времени. Во-первых, необходимость четко объяснять, что вы делаете, заставляет вас четко обдумать это, и если вы не можете написать ясное, краткое объяснение того, что выполняет ваш код, то, вероятно, он не разработан должным образом. И по другой, исключительно эгоистичной причине, хорошо документированный и хорошо структурированный код гораздо проще перенести на кого-то другого, чтобы поддерживать - таким образом, освобождая первоначального автора для создания следующей важной вещи. Я редко, если когда-либо, вынужден останавливать то, что я делаю, чтобы объяснить, как мой код должен был работать, потому что он очевиден для любого, кто умеет читать по-английски (даже если он не умеет читать C / C ++ / C # и т. Д.). И еще одна причина, честно говоря, моя память просто не так хороша! Я не могу вспомнить, что у меня было на завтрак вчера, тем более, о чем я думал, когда писал код месяц или год назад. Возможно, ваша память намного лучше моей, но, поскольку я документирую свои намерения, я могу быстро подобрать, где бы я ни остановился, и внести изменения без необходимости сначала выяснить, о чем я думал, когда писал это.
Вот почему я хорошо документирую - не потому, что я чувствую какой-то благородный призыв к созданию красивого кода, пригодного для отображения, и не потому, что я пурист, а просто потому, что он позволяет мне поставлять качественное программное обеспечение за меньшее время .
Реализовали ли вы интерфейс Cloneable для своего объекта?
Однако есть очень мало случаев, когда я бы использовал clone для копирования объекта. Один из таких безопасных примеров - array.clone (). Я бы предпочел использовать идиому копирующего конструктора или вручную копировать / присваивать значения.
В Эффективная Java (2-е издание) есть пункт № 11 о фоновой проблеме. Клонируемый интерфейс - это особый вид интерфейса, поскольку он изменяет поведение класса Object
в отношении клонирования. По сути, это функция, включающая интерфейс class в Java.
Изменить: На основе вашего примера вам может потребоваться заключить вызов clone () в try-catch CloneNotSupportedException в общем случае .
Edit2: Перефразировал мой ответ
Edit3: Вы переопределили clone () в общедоступном
контексте? В приведенном вами примере вы пытаетесь клонировать объект, который находится в пакете java.lang - вряд ли это пакет, в котором находится ваш код.
Edit4: Я думаю, что ответ уже есть в других сообщениях, просто хотел чтобы поразмышлять над основной проблемой.
Edit5: Попробуйте следующее:
public Object clone1() throws CloneNotSupportedException {
return super.clone();
}
Edit6 Затем назовите свой метод public abstract Object copy ()
, например, и в реализации используйте super.clone () - во избежание путаницы.
Edit7 Я сделал несколько затмений и пришел со следующим решением:
public class Cloner {
public static abstract class Person {
protected abstract Object clone1() throws CloneNotSupportedException;
public Object copy() throws CloneNotSupportedException {
return clone1();
}
}
public static class Employee extends Person implements Cloneable {
@Override
protected Object clone1() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) throws Exception {
new Employee().copy();
}
}
Но в основном это та же концепция, что и переименование вашего абстрактного метода во что-то другое, кроме clone ( ).
Edit8: Исправил мой пример, теперь работает без исключения.
Стандартный шаблон для создания клонируемого класса:
Клонируемый
clone ()
и сделать его общедоступным clone ()
вызовите super.clone ()
, а затем скопируйте состояние любого изменяемого объекта Вы должны не создавать новый объект, используя new
. Правильный способ - вызвать super.clone ()
для нового экземпляра.
clone ()
объекта является особенным и создает новую копию объекта и копирует его примитивные поля и ссылки.
Например:
public class Person implements Cloneable {
protected String name;
// Note that overridden clone is public
public Object clone() {
Person clone = (Person)super.clone();
// No need to copy name as the reference will be
// copied by Object's clone and String is immutable
return clone;
}
}
public class Employee extends Person {
protected int id;
protected java.awt.Point location;
public Object clone() {
Employee clone = (Employee )super.clone();
// No need to copy id as Object's clone has already copied it
// Need to clone location as Point is mutable and could change
clone.location = location.clone();
return clone;
}
}
Java ' механизм клонирования несколько неудобен. Чтобы иметь возможность клонировать себя, класс должен делать две вещи. Сначала он должен реализовать Clonable. Во-вторых, он должен переопределить clone () и сделать его общедоступным.
В вашем примере вы переопределяете clone (), но вызываете clone () не в классе Employee, а в Object.class (), где clone () - только охраняется.
Мистер Блох из Effective Java может сказать несколько интересных слов об использовании клона
.
http://www.artima.com/intv/bloch13. html
Обычно в настоящее время принято избегать использования клона, поскольку он подвержен ошибкам и неправильно понимается, реализация конструктора копирования является альтернативной стратегией или использование подхода грубой силы для глубокого копирования объекта с использованием сериализации.
Вам следует просто написать
return super.clone();
в вашем методе клонирования и реализовать интерфейс Clonable.
Реализовали ли вы соответствующий интерфейс? Это может быть так просто, хотя вы, возможно, уже это учли.
См. Здесь для получения дополнительной информации: http://java.sun.com/javase/6/docs/api/java/lang /Object.html#clone()[121pting
Я не очень знаком с Java, но это может помочь: http://en.wikipedia.org/wiki/Clone_ (Java_method)
Выдержка из сообщения:
Еще одним недостатком является то, что часто не может получить доступ к методу clone () на абстрактный тип. Большинство интерфейсов и абстрактные классы в Java не укажите общедоступный метод clone (). Как результат, часто единственный способ использовать clone (), если вы знаете актуальный класс объекта; который вопреки принципу абстракции использования наиболее общего типа возможно. Например, если у кого-то есть Ссылка на список в Java, нельзя вызвать clone () по этой ссылке потому что в списке нет общедоступных clone () метод. Актуальные реализации списка, такого как ArrayList и LinkedList у всех обычно есть методы clone () себя, но это неудобно и плохая абстракция носить с собой фактический тип класса объекта.
В основном, чтобы иметь правильно клонируемый объект, достаточно иметь в этом классе реализованный общедоступный метод clone ().
Интерфейс Cloneable является интерфейсом маркера
используется, чтобы сообщить виртуальной машине, что можно безопасно реализовать защищенный по умолчанию метод clone () в виде поля за копией поля.
Чтобы правильно реализовать метод клонирования для класса, вы должны объявить клон общедоступного метода, как это ().
public Object clone() {
return super.clone();
}
Хорошая работающая реализацияk создаст новый объект и правильно назначит поля, как того требует бизнес-логика:
public Object clone() {
CurrentClass newObject = new CurrentClass();
newObject.field1 = this.field1; // for simple types: int, long, etc
newObject.referenceField = this.referenceField.clone(); // for agregate objects or references.
return newObject;
}
Заключение: объявить общедоступный метод клонирования. Если вы хотите иметь реализацию по умолчанию в виде поля с помощью функции копирования поля, вызовите super и отметьте класс как Cloneable Если вы хотите только индивидуальное клонирование, игнорируйте метку «Клонируемый».
Я думаю, что текущий зеленый ответ плохой , почему вы можете спросить?
Да, кстати, сериализация - тоже плохо, возможно, вам придется добавлять Serializable повсюду (это тоже заставляет меня плакать).
Итак, каково решение:
Библиотека глубокого клонирования Java Библиотека клонирования - это небольшая java-библиотека с открытым исходным кодом (лицензия apache), которая глубоко клонирует объекты. Объекты не обязательно должны реализовывать интерфейс Cloneable. Фактически, эта библиотека может клонировать ЛЮБЫЕ объекты Java. Его можно использовать, например, в реализациях кеширования, если вы не хотите, чтобы кэшированный объект изменялся или всякий раз, когда вы хотите создать глубокую копию объектов.
Cloner cloner=new Cloner();
XX clone = cloner.deepClone(someObjectOfTypeXX);
Посмотрите на http://code.google.com/p/cloning/