Respuestas:
El hecho de que el clon esté protegido es extremadamente dudoso, al igual que el hecho de que el clone
método no esté declarado en la Cloneable
interfaz.
Hace que el método sea bastante inútil para tomar copias de datos porque no puede decir :
if(a instanceof Cloneable) {
copy = ((Cloneable) a).clone();
}
Creo que el diseño de Cloneable
ahora se considera en gran medida un error (cita a continuación). Normalmente me gustaría poder hacer implementaciones de una interfaz Cloneable
pero no necesariamente hacer la interfazCloneable
(similar al uso de Serializable
). Esto no se puede hacer sin reflexión:
ISomething i = ...
if (i instanceof Cloneable) {
//DAMN! I Need to know about ISomethingImpl! Unless...
copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}
Cita de Effective Java de Josh Bloch :
"La interfaz Cloneable fue pensada como una interfaz mixin para que los objetos anunciaran que permiten la clonación. Desafortunadamente, no cumple con este propósito ... Este es un uso altamente atípico de interfaces y no uno para ser emulado ... Para que la implementación de la interfaz tenga algún efecto en una clase, esta y todas sus superclases deben obedecer un protocolo bastante complejo, inaplicable y en gran parte indocumentado "
Serializable
; depende de las implementaciones decidir si se implementa Serializable
. Estaba extendiendo esto a Cloneable
, no es algo que una interfaz deba extender, pero la implementación de una interfaz es gratuita Cloneable
. El problema es que, si tiene un parámetro del tipo de interfaz, le pregunta si se puede clonar; ¡pero entonces no puedes clonarlo!
La interfaz Clonable es solo un marcador que dice que la clase puede admitir la clonación. El método está protegido porque no debe llamarlo en el objeto, puede (y debe) anularlo como público.
Desde el sol:
En la clase Object, el método clone () se declara protegido. Si todo lo que hace es implementar Cloneable, solo las subclases y los miembros del mismo paquete podrán invocar clone () en el objeto. Para permitir que cualquier clase en cualquier paquete acceda al método clone (), deberá anularlo y declararlo público, como se hace a continuación. (Cuando anula un método, puede hacerlo menos privado, pero no más privado. Aquí, el método clone () protegido en Object se anula como método público).
Set
clone
está protegido porque es algo que debe anularse para que sea específico de la clase actual. Si bien sería posible crear un clone
método público que clonara cualquier objeto, esto no sería tan bueno como un método escrito específicamente para la clase que lo necesita.
El método Clone no se puede usar directamente en ningún objeto, por lo que está destinado a ser anulado por la subclase.
Por supuesto, podría ser público y lanzar una excepción apropiada cuando la clonación no sea posible, pero creo que sería engañoso.
La forma en que se implementa la clonación en este momento le hace pensar en por qué desea usar la clonación y cómo desea que se clone su objeto.
Está protegido porque la implementación predeterminada hace una copia superficial de todos los campos (incluido el privado), evitando el constructor . Esto no es algo para lo que un objeto pueda estar diseñado para manejar en primer lugar (por ejemplo, podría realizar un seguimiento de las instancias de objetos creados en una lista compartida, o algo similar).
Por la misma razón, la implementación predeterminada de clone()
arrojará si el objeto al que se llama no se implementa Cloneable
. Es una operación potencialmente insegura con consecuencias de gran alcance y, por lo tanto, el autor de la clase debe participar explícitamente.
Desde el javadoc de cloneable.
* By convention, classes that implement this interface (cloneable) should override
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.
* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface. Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.
Por lo tanto, podría llamar a clonar en cada objeto, pero esto le daría la mayoría de las veces, no los resultados que desea o una excepción. Pero solo se recomienda si implementa cloneable.
En mi humilde opinión, es tan simple como esto:
#clone
no debe invocarse en objetos no clonables, por lo tanto, no se hace público#clone
tiene que ser llamado por las subclases ob Object
que implementan Cloneable para obtener la copia superficial de la clase correcta¿Cuál es el alcance correcto para los métodos que serán invocables por subclases, pero no por otras clases?
Es protected
.
Las clases implementadas, Cloneable
por supuesto, harán público este método para que pueda ser llamado desde otras clases.
El método Clone () tiene una verificación interna 'instancia de Cloneable o no'. Así es como el equipo de Java podría pensar que restringirá el uso indebido del método clone (). El método clone () está protegido, es decir, se accede solo por subclases. Dado que el objeto es la clase principal de todas las subclases, todas las clases pueden usar el método Clone () de hecho si no tenemos la verificación anterior de 'instancia de Cloneable'. Esta es la razón por la que el equipo de Java podría haber pensado en restringir el uso indebido de clone () haciendo que el método clone () marque 'es una instancia de Cloneable'.
Por lo tanto, cualquier clase que implemente clonable puede usar el método clone () de la clase Object.
Además, dado que se hizo protegido, solo está disponible para aquellas subclases que implementan una interfaz clonable. Si queremos hacerlo público, este método debe ser anulado por la subclase con su propia implementación.
Sí, el mismo problema que conocí. Pero lo resuelvo implementando este código
public class Side implements Cloneable {
public Side clone() {
Side side = null;
try {
side = (Side) super.clone();
} catch (CloneNotSupportedException e) {
System.err.println(e);
}
return side;
}
}
Tal como dijo alguien antes.
Bueno, también los desarrolladores de Sun son solo humanos, y de hecho cometieron un gran error al implementar el método de clonación como protegido, ¡el mismo error que implementaron un método de clonación que no funciona en ArrayList! Entonces, en general, existe un malentendido mucho más profundo, incluso de los programadores Java experimentados sobre el método de clonación.
Sin embargo, recientemente encontré una solución rápida y fácil para copiar cualquier objeto con todo su contenido, sin importar cómo esté construido y qué contiene, vea mi respuesta aquí: Error al usar Object.clone ()
Una vez más, el marco Java JDK muestra un pensamiento brillante:
La interfaz clonable no contiene un "clon T público ();" método porque actúa más como un atributo (por ejemplo, serializable) que permite clonar una instancia.
No hay nada de malo en este diseño porque:
Object.clone () no hará lo que quieras con tu clase personalizada definida.
Si tiene Myclass implements Cloneable => sobrescribe clone () con "public MyClass clone ()"
Si tiene MyInterface amplía Cloneable y algunas MyClasses implementando MyInterface: simplemente defina "public MyInterface clone ();" en la interfaz y cada método que use objetos MyInterface podrá clonarlos, sin importar su clase MyClass.