new icon example borderfactory java java-8 deprecated cloneable

java - icon - ¿Por qué Cloneable no está en desuso?



my icon java (3)

¿Por qué todavía no está en desuso?

Porque el JCP no ha creído conveniente hacerlo, y puede que nunca lo haga. Pregúntales. Estás preguntando en el lugar equivocado.

¿Cuáles son las razones para mantener esto en la API de Java?

Nadie eliminará nada de la API de Java, debido al requisito de compatibilidad con versiones anteriores. La última vez que sucedió fue el cambio en el modelo de evento AWT entre 1.0 y 1.1 en 1996/7.

Se entiende comúnmente que la interfaz Cloneable en Java está rota. Hay muchas razones para esto, que no mencionaré; others ya lo hicieron. También es la posición de los propios arquitectos de Java .

Mi pregunta es por lo tanto: ¿por qué todavía no ha quedado en desuso? Si el equipo central de Java ha decidido que está roto, entonces también deben haber considerado la depreciación. ¿Cuáles son sus razones para no hacerlo (en Java 8 todavía no está en desuso )?


Hay un bug enviado en 1997 a bug sobre agregar el método clone() a Cloneable , por lo que ya no sería inútil. Se cerró con la resolución "no se solucionará" y la justificación fue la siguiente:

El Comité de Revisión Técnica (TRC) de Sun consideró este problema detenidamente y recomendó no realizar ninguna acción que no sea mejorar la documentación de la interfaz Cloneable actual . Aquí está el texto completo de la recomendación:

Las API de clonación de objetos Java existentes son problemáticas. Hay un método de "clonación" protegido en java.lang.Object y hay una interfaz java.lang.Cloneable. La intención es que si una clase quiere permitir que otras personas la clonen, entonces debe admitir la interfaz Cloneable y anular el método de clonación protegido predeterminado con un método de clonación pública. Desafortunadamente, por razones convenientemente perdidas en las brumas del tiempo, la interfaz clonable no define un método de clonación.

Esta combinación resulta en una buena cantidad de confusión. Algunas clases afirman ser compatibles con Cloneable, pero accidentalmente se olvidan de admitir el método de clonación. Los desarrolladores están confundidos acerca de cómo se supone que debe funcionar Cloneable y qué se supone que debe hacer el clon.

Desafortunadamente, agregar un método de "clonación" a Cloneable sería un cambio incompatible. No romperá la compatibilidad binaria, pero romperá la compatibilidad de origen. La evidencia anecdótica sugiere que en la práctica hay una serie de casos en los que las clases admiten la interfaz clonable pero no proporcionan un método de clonación público. Después de la discusión, TRC recomendó por unanimidad que NO deberíamos modificar la interfaz Cloneable existente, debido al impacto de compatibilidad.

Una propuesta alternativa era agregar una nueva interfaz java.lang.PubliclyCloneable para reflejar el propósito original de Cloneable. Por una mayoría de 5 a 2, TRC recomendó no hacerlo. La principal preocupación era que esto agregaría aún más confusión (¡incluida la confusión ortográfica!) A una imagen ya confusa.

TRC recomendó por unanimidad que agreguemos documentación adicional a la interfaz Cloneable existente para describir mejor cómo se debe utilizar y para describir las "mejores prácticas" para los implementadores.

Entonces, aunque esto no se trata directamente de obsoleto , la razón para no hacer que Cloneable sea "obsoleto" es que el Comité de Revisión Técnica decidió que modificar la documentación existente será suficiente para que esta interfaz sea útil. Y así lo hicieron. Hasta Java 1.4, Cloneable estaba documentado de la siguiente manera:

Una clase implementa la interfaz Cloneable para indicar al método Object.clone () que es legal que ese método haga una copia de campo por campo de instancias de esa clase.

Los intentos de clonar instancias que no implementan la interfaz Cloneable dan como resultado la excepción CloneNotSupportedException.

La interfaz Cloneable no declara métodos.

Desde Java 1.4 (que se lanzó en febrero de 2002) hasta la edición actual (Java 8) se ve así:

Una clase implementa la interfaz Cloneable para indicar al método Object.clone () que es legal que ese método haga una copia de campo por campo de instancias de esa clase. Al invocar el método de clonación de Object en una instancia que no implementa la interfaz Cloneable, se genera la excepción CloneNotSupportedException.

Por convención, las clases que implementan esta interfaz deben anular Object.clone (que está protegido) con un método público. Consulte Object.clone () para obtener detalles sobre cómo anular este método.

Tenga en cuenta que esta interfaz no contiene el método de clonación. Por lo tanto, no es posible clonar un objeto simplemente por el hecho de que implementa esta interfaz. Incluso si el método de clonación se invoca reflexivamente, no hay garantía de que tenga éxito.


La respuesta corta a "¿por qué no se puede Cloneable desuso?" (o, de hecho, por qué X no está en desuso, para cualquier X ) es que no se ha prestado mucha atención a despreciarlos.

La mayoría de las cosas que han quedado en desuso recientemente quedaron en desuso porque existe un plan específico para eliminarlas. Por ejemplo, los métodos addPropertyChangeListener y removePropertyChangeListener de LogManager fueron desaprobados en Java SE 8 con la intención de eliminarlos en Java SE 9. (La razón es que complicaron innecesariamente las interdependencias de los módulos). De hecho, estas API ya se han eliminado de JDK temprano 9 construcciones de desarrollo. (Tenga en cuenta que las llamadas de escucha de cambio de propiedad similares también se eliminaron de Pack200 ; consulte JDK-8029806 ).

No existe un plan similar para Cloneable y Object.clone() .

Una respuesta más larga implicaría discutir más preguntas, como qué podría esperarse que suceda con estas API, qué costos o beneficios acumularían la plataforma si fueran desaprobadas, y qué se comunica a los desarrolladores cuando una API está en desuso. Exploré este tema en mi reciente charla de JavaOne, Deuda y desaprobación . (Diapositivas disponibles en ese enlace; video aquí .) Resulta que el JDK en sí mismo no ha sido muy consistente en su uso de la degradación. Se ha utilizado para significar varias cosas diferentes, que incluyen, por ejemplo,

  • Esto es peligroso y debe tener en cuenta los riesgos de usarlo (por ejemplo: Thread.stop() , Thread.resume() y Thread.suspend() ).

  • Esto se eliminará en una versión futura

  • Esto es obsoleto y es una buena idea que use algo diferente (ejemplo: muchos de los métodos en java.util.Date )

Todos estos son significados distintos, y diferentes subconjuntos de ellos se aplican a diferentes cosas que están en desuso. Y algunos de ellos se aplican a cosas que no están en desuso (pero que tal vez deberían estar en desuso).

Cloneable y Object.clone() están "rotos" en el sentido de que tienen fallas de diseño y son difíciles de usar correctamente. Sin embargo, clone() sigue siendo la mejor manera de copiar matrices, y la clonación tiene una utilidad limitada para hacer copias de instancias de clases que se implementan cuidadosamente. Eliminar la clonación sería un cambio incompatible que rompería muchas cosas. Una operación de clonación podría implementarse de una manera diferente, pero probablemente sería más lenta que Object.clone() .

Sin embargo, para la mayoría de las cosas, un constructor de copia es preferible a la clonación. Entonces, quizás sea Cloneable marcar Cloneable como "obsoleto" o "reemplazado" o algo similar. Esto les diría a los desarrolladores que probablemente quieran buscar en otro lado, pero no indicaría que el mecanismo de clonación podría eliminarse en una versión futura. Desafortunadamente, no existe tal marcador.

Tal como están las cosas, la "desaprobación" parece implicar la eliminación eventual, a pesar del hecho de que una cantidad cada vez menor de características desaprobadas se han eliminado alguna vez, por lo que la desaprobación no parece justificada por el mecanismo de clonación. Quizás en el futuro se pueda aplicar una marca alternativa que dirija a los desarrolladores a utilizar mecanismos alternativos.

ACTUALIZAR

Agregué un historial adicional al informe de error . Frank Yellin, uno de los primeros implementadores de JVM y coautor de la especificación de JVM, hizo algunos comentarios en respuesta al comentario de "perdido en las brumas del tiempo" en la recomendación de TRC citada en la otra respuesta . He citado las porciones relevantes aquí; El mensaje completo está en el informe de error.

Cloneable no tiene métodos por la misma razón que Serializable no. Cloneable indica una propiedad de la clase, en lugar de decir específicamente algo sobre los métodos que admite la clase.

Antes de la reflexión, necesitábamos un método nativo para hacer una copia superficial de un Objeto. De ahí nació Object.clone (). También estaba claro que muchas clases querrían anular este método, y que no todas las clases querrían ser clonadas. Por lo tanto, Cloneable nació para indicar la intención del programador.

Entonces, en resumen. El propósito de Cloneable no era indicar que tenía un método público clone (). Fue para indicar que estaba dispuesto a ser clonado usando Object.clone (), y fue la implementación decidir si hacer público clone () o no.