Pregunta

Este es un ejemplo de copia defensiva en Java efectivo.Supongamos que el escenario en mis preguntas subyacentes necesita una copia defensiva y no puede funcionar con un comentario que le pide al cliente que evite mutar los objetos pasados.

public Period(Date start, Date end) {
    this.start = new Date(start.getTime());
    this.end = new Date(end.getTime());
}

Preguntas:

  1. ¿Qué hacer si Date ¿No tenía un constructor para asimilarlo, para hacerme más general, se pasa un objeto sin ningún mecanismo para replicarse y dicho objeto no nos pertenece, es decir, no podemos cambiarlo de ninguna manera?

  2. ¿Qué pasa si el constructor toma el parámetro de tipo como argumento, por ejemplo? Period(T object) y T podría ser mutable, por lo que necesita una copia defensiva.No tenemos idea de qué es T.¿Cómo hacer una copia defensiva en este caso?

  3. ¿Qué es una interfaz? Se pasa donde algunas de sus subclases tienen un constructor como Date ¿Crear un objeto por sí mismo y algunas de sus subclases no tienen ningún mecanismo para hacerlo?

  4. ¿A qué profundidad debemos copiar defensivamente?Digamos que copiamos una matriz, pero ¿los elementos de la matriz eran mutables?

¿Fue útil?

Solución

  1. Si todo su estado está disponible, puede extraerlo y construir un nuevo objeto usted mismo.De lo contrario, no podrá hacer nada al respecto excepto utilizar trucos desagradables de reflexión o serialización.
  2. Si T no es una instancia de una clase que permite copiarse a sí misma, no puedes hacer nada.
  3. No puedes hacer nada al respecto.
  4. Eso depende.

Al leer su pregunta, parece que le gustaría aplicar el consejo de "copia defensiva" en todas partes.No deberías.La mayoría de las veces, el código que utiliza objetos mutables quiere una referencia al objeto original y no una copia.Especialmente si lo que obtienes como argumento es una instancia de una clase o interfaz abstracta.

Está obligado a hacer una copia defensiva de Date porque es un tipo de valor mutable que no debería serlo y no lo sería si se hubiera diseñado correctamente.Si promueves la inmutabilidad de los tipos de valor, las copias defensivas se vuelven innecesarias.Para los tipos sin valor, generalmente no desea una copia, sino una referencia al objeto.

Otros consejos

  1. Si no puedes cambiar el estado del objeto de todos modos, no necesitas una copia defensiva.
  2. Lo único que puede hacer es asumir una implementación probable de T y verificarla con en vez de.
  3. Igual que 2.
  4. A su discreción.Si supone que la modificación de los elementos de la matriz podría dañar su programa en otros lugares, también debería copiarlos todos.

La programación defensiva es importante cuando los objetos que se pasan a un método son mutables.Una buena práctica (también descrita en el libro Java efectivo) es hacerlos inmutables.

  1. Si la clase Date no es definitiva, puede escribir una clase contenedora para ella, es decir, una subclase de Date.
  2. Eso depende.Probablemente no será necesario clonarlo.
  3. No debería molestarte.El implementador de una interfaz debe encargarse de los problemas de sincronización.Generalmente, es una buena práctica pasar interfaces en lugar de sus implementaciones.
  4. Para las colecciones estándar de Java, existen muchos métodos de utilidad en la clase java.util.Collections, como unmodifiableList y unmodifiableMap, destinados a la programación defensiva.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top