Я должен реализовать глубокий клон в одном из моих объектов, который не имеет никакого суперкласса.
Что лучший способ состоит в том, чтобы обработать проверенное CloneNotSupportedException
брошенный суперклассом (который является Object
)?
Коллега советовал мне обрабатывать его следующий путь:
@Override
public MyObject clone()
{
MyObject foo;
try
{
foo = (MyObject) super.clone();
}
catch (CloneNotSupportedException e)
{
throw new Error();
}
// Deep clone member fields here
return foo;
}
Это походит на хорошее решение меня, но я хотел вывести его сообществу StackOverflow, чтобы видеть, существует ли какое-либо другое понимание, которое я могу включать.Спасибо!
В списке можно использовать\colorbox и символ escape:
Добавьте в преамбулу
\usepackage{color}
\definecolor{light-gray}{gray}{0.80}
, затем используйте его следующим образом:
\begin{lstlisting}[escapechar=!]
def mult(m: Matrix[Int], n: Matrix[Int]) {
val p = !\colorbox{light-gray}{new MatrixInt}!(m.rows, n.cols)
}
\end{lstlisting}
-121--1360192- Используйте setOnClickListener ()
для регистрации прослушивателя, который затем проверяет,
Обязательно ли использовать клон
? Большинство людей согласны с тем, что клон Java
сломан.
Джош Блох на дизайн - копировать конструктор против клонирования
Если вы прочитали пункт о клонировании в моей книге, особенно если вы читаете между строк, вы будете знать, что я думаю, что
клон
глубоко сломан. [...] Обидно, чтоКлонируемый
сломан, но так бывает.
Подробнее об этой теме можно прочитать в его книге Effective Java 2nd Edition, Пункт 11: Override clone
judicicially . Вместо этого он рекомендует использовать конструктор копий или завод по копированию.
Далее он написал страницы о том, как, если вы чувствуете, что должны, вы должны реализовать клон
. Но он закрылся этим:
Действительно ли все эти сложности необходимы? Редко. При расширении класса, реализующего
Cloneable
, у вас нет другого выбора, кроме как реализовать хорошо работающий методclone
. В противном случае лучше предоставить альтернативные средства копирования объектов или просто не предоставлять возможности .
Акцент был на нем, а не на моем.
Поскольку вы дали понять, что у вас мало выбора, кроме как реализовать клон
, вот что вы можете сделать в этом случае: убедитесь, что MyObject расширяет java.lang.Object реализует java.lang.Cloneable
. Если это так, вы можете гарантировать, что НИКОГДА не поймаете CloneNotSupportedException
. Ввод AssertureError
, как некоторые предлагали, представляется разумным, но можно также добавить комментарий, объясняющий, почему блок catch никогда не будет введен в данном конкретном случае .
Также, как и другие, можно реализовать клон
без вызова super.clone
.
Иногда проще реализовать конструктор копирования:
public MyObject (MyObject toClone) {
}
Это избавляет вас от необходимости обрабатывать CloneNotSupportedException
, работает с ] final
, и вам не нужно беспокоиться о возвращаемом типе.
Существует два случая, в которых будет создано CloneNotSupportedException
:
Клонируемый
(при условии, что фактическое клонирование в конечном итоге отложит метод клонирования объекта
). Если класс, записывающий этот метод в implements Cloneable
, этого никогда не произойдет (так как любые подклассы наследуют его соответствующим образом). Клонируемый
. Последний случай не может возникнуть в вашем классе (так как вы вызываете непосредственно метод superclass 'в блоке try
, даже если вызывается из подкласса, вызывающего super.clone ()
), и первый не должен, так как ваш класс явно должен реализовывать Cloneable
.
В основном, вы должны зарегистрировать ошибку наверняка, но в данном конкретном случае это произойдет только в том случае, если вы испортите определение вашего класса. Таким образом, рассматривайте его как проверенную версию StartPointerException
(или подобную) - он никогда не будет выброшен, если ваш код работает.
В других ситуациях необходимо быть готовым к этому - нет гарантии, что данный объект является клонируемым, поэтому при ловле исключения следует предпринять соответствующие действия в зависимости от этого условия (продолжить с существующим объектом, взять альтернативную стратегию клонирования, например сериализовать-десериализовать, вызвать IllegalParameterException
, если метод требует параметр клонируемой и т.д.).
Edit : Хотя в целом я должен отметить, что да, clone ()
действительно трудно реализовать правильно и трудно для вызывающих, чтобы знать, будет ли возвращаемое значение то, что они хотят, вдвойне, когда вы считаете глубокий против мелкого клонов. Часто лучше просто полностью избегать всего этого и использовать другой механизм.
Я бы просто использовал данные в «длинном» формате.
Например.
> d1 <- data.frame(id=1:3, num_words=c(2,1,4), phrase=c("hello world", "greetings", "take me to your leader"))
> d2 <- data.frame(id=c(rep(1,2), rep(2,1), rep(3,5)), token_length=c(5,5,9,4,2,2,4,6))
> d2$tokenid <- with(d2, ave(token_length, id, FUN=seq_along))
> d <- merge(d1,d2)
> subset(d, nchar(phrase) > 10)
id num_words phrase token_length tokenid
1 1 2 hello world 5 1
2 1 2 hello world 5 2
4 3 4 take me to your leader 4 1
5 3 4 take me to your leader 2 2
6 3 4 take me to your leader 2 3
7 3 4 take me to your leader 4 4
8 3 4 take me to your leader 6 5
> with(d, tapply(token_length, id, mean))
1 2 3
5.0 9.0 3.6
Как только данные находятся в длинном формате, можно использовать sqldf или plyr для извлечения из них желаемого.
-121--3338901- Ваш код работает довольно близко к «каноническому» способу его написания. Я бы выбросил AssertureError
в улов, хотя. Он сигнализирует, что эта линия никогда не должна быть достигнута.
catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
Вы можете реализовать конструкторы защищенного копирования следующим образом:
/* This is a protected copy constructor for exclusive use by .clone() */
protected MyObject(MyObject that) {
this.myFirstMember = that.getMyFirstMember(); //To clone primitive data
this.mySecondMember = that.getMySecondMember().clone(); //To clone complex objects
// etc
}
public MyObject clone() {
return new MyObject(this);
}
Есть два случая, в которых CloneNotSupportedException
будет сгенерировано:
Cloneable
(при условии, что фактическое клонирование в конечном итоге относится к Метод клонирования объекта
). Если класс, в котором вы пишете этот метод, реализует Cloneable
, этого никогда не произойдет (поскольку любые подклассы унаследуют его соответствующим образом). Cloneable
. Последний случай не может иметь место в вашем классе (поскольку вы напрямую вызываете метод суперкласса в блоке try
, даже если вызывается из подкласса, вызывающего super.clone ()
]), а в первом случае не следует, поскольку ваш класс явно должен реализовывать Cloneable
.
В принципе, вы должны обязательно зарегистрировать ошибку, но в данном конкретном случае это произойдет только в том случае, если вы испортите определение своего класса. Поэтому относитесь к нему как к проверенной версии NullPointerException
(или подобного) - оно никогда не будет сгенерировано, если ваш код работает.
В других ситуациях вам нужно быть готовым к такой возможности - нет гарантии, что данный объект является клонируемым, поэтому при перехвате исключения вы должны предпринять соответствующие действия в зависимости от этого условия (продолжить с существующий объект, возьмите альтернативную стратегию клонирования, напримерсериализовать-десериализовать, выбросить IllegalParameterException
, если вашему методу требуется параметр by cloneable и т. д. и т. д.).
Правка : Хотя в целом я должен отметить, что да, clone ()
действительно сложно реализовать правильно и вызывающим абонентам сложно узнать, будет ли возвращаемое значение таким, каким они хотят, вдвойне. когда вы рассматриваете глубокие и мелкие клоны. Часто лучше полностью избегать всего этого и использовать другой механизм.
Используйте сериализацию для создания глубоких копий. Это не самое быстрое решение, но оно не зависит от типа.