Demasiado repetitivo, ¿cómo puedo reducir mis constructores de POJO?

Tengo varios POJO diferentes que usan un patrón de constructor , pero después de agregar un constructor para cada uno y generar Object.toString , Object.hashCode y Object.equals , mis clases terminan siendo alrededor de 100 líneas de código. Tiene que haber una mejor manera de manejar esto. Creo que tener algún tipo de constructor reflexivo ayudaría mucho, pero no estoy seguro de que esto sería una buena práctica y tampoco estoy seguro de cómo lo haría exactamente. En otras palabras, ¿hay una manera de implementar un constructor como este?

Un simple POJO:

 public class Foo { public int id; public String title; public boolean change; ... } 

Entonces algún tipo de constructor reflexivo:

 Foo = ReflectiveBuilder.from(Foo.class).id(1).title("title").change(false).build(); 

Respuesta corta no . Lo que usted pide no es posible. Reflection examina el código en tiempo de ejecución e invoca métodos dinámicamente, no puede generar métodos reales.

Lo que podría hacer sería:

 Foo foo = ReflectiveBuilder.from(Foo.class). set("id", 1). set("title", "title"). build(); 

Esto tiene tres problemas masivos :

  1. Los campos son String s – un error tipográfico provoca un error en tiempo de ejecución en lugar de un tiempo de compilación,
  2. Los valores son Object s – el tipo incorrecto provoca un error de tiempo de ejecución en lugar de un tiempo de compilación, y
  3. Sería mucho más lento que la alternativa ya que la reflexión es muy lenta.

Así que una solución basada en la reflexión, aunque sea posible (véase Apache Commons BeanUtils BeanMap ) no es en absoluto práctica.

Respuesta larga, si usted está dispuesto a permitir que la magia de tiempo de compilación, puede utilizar el proyecto Lombok . La idea detrás de Lombok es generar código de calderas a partir de anotaciones usando el sistema de preprocesador de anotación de Java.

Lo realmente mágico es que todos los IDE, por lo menos los 3 grandes por lo menos, entienden el preprocesamiento de la anotación y la terminación del código todavía funcionará correctamente aunque el código no exista realmente .

En el caso de un POJO con un Builder puede utilizar @Data y @Builder

 @Data @Builder public class Foo { public int id; public String title; public boolean change; ... } 

La anotación @Data generará:

  • Un constructor de argumentos requeridos (que toma todos los campos final ),
  • hashCode y hashCode que utilizan todos los campos (se pueden configurar con la anotación @EqualsAndHashCode )
  • Un método toString en todos los campos (se puede configurar con la anotación @ToString y
  • Public getters y setters para todos los campos (se puede configurar usando las anotaciones @Getter / @Setter en campos).

La anotación @Builder generará una clase interna llamada Builder que se puede instanciar usando Foo.builder() .

Asegúrese de configurar los métodos equals , hashCode y toString como si tuviera dos clases con Lombok que tienen referencias entre sí, entonces terminará con un bucle infinito en el caso por defecto ya que ambas clases incluyen el otro en estos métodos.

También hay un nuevo sistema de configuración que te permite usar, por ejemplo, setters fluentes para que puedas eliminar más fácilmente el constructor si tu POJO es mutable:

 new Foo().setId(3).setTitle("title)... 

Para otro enfoque, puede ver la programación orientada a aspectos (AOP) y AspectJ . AOP le permite cortar sus clases en "aspectos" y luego pegarlos juntos utilizando ciertas reglas utilizando un pre-compilador. Por ejemplo, puede implementar exactamente lo que hace Lombok, utilizando anotaciones personalizadas y un aspecto. Este es un tema bastante avanzado sin embargo, y bien podría ser excesivo.

Tal vez el proyecto Lombok (sí el sitio web es feo) es una opción para usted. Lombok inyecta código en sus clases basado en anotaciones.

Con Lombok se utilizan las anotaciones @Data para generar getters, setters, toString() , hashCode() y equals() :

 @Data public class Foo { public int id; public String title; public boolean change; } 

Echa un vistazo al ejemplo en la sección de documentación @Data para ver el código generado.

Lombok también proporciona un @Builder que genera un constructor para su clase. Pero tenga en cuenta que esta es una característica experimental:

 @Builder public class Foo { public int id; public String title; public boolean change; } 

Ahora usted puede hacer:

 Foo foo = Foo.builder() .id(123) .title("some title") .change(true) .build(); 

Personalmente, uso este sitio web para crear todo el código para los POJOs para mí. Todo lo que necesitas hacer es pegar el JSON que quieres analizar, y generará todas las clases para ti. Entonces sólo uso Retrofit para hacer las solicitudes / caché / análisis de la información. He aquí un ejemplo de Retrofit y POJOs en mi cuenta de Github. ¡Espero que ayude!

Creé una pequeña biblioteca CakeMold para hacer la inicialización fluida de POJOs. Utiliza la reflexión, lo que ciertamente no es rápido. Pero puede ser muy útil cuando es necesario escribir pruebas.

 Person person = CakeMold.of(Person.class) .set("firstName", "Bob") .set("lastName", "SquarePants") .set("email", "[email protected]") .set("age", 22) .cook(); 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.