Subclases @Builder anotación lombok la postura correcta

I. Antecedentes

En el desarrollo real, a veces es necesario utilizar @Builder anotación subclases Lombok usar el esquema constructor construye el objeto subclase.

Clase de Padres:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Parent {
    private Long id;

    private String name;
}

subclase

import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@Builder
public class Child extends Parent{


}

En este momento, aunque la anotación añadido en subclases @Builder, pero puesto que no hay subclase atributo, como se muestra a continuación, no puede utilizar el patrón de constructor.

 

 

Segundo, el análisis

Lombok.Builder mediante la lectura de la fuente, no sólo entiende anotación @Builder se puede utilizar en la clase, también se puede utilizar en el constructor.

Así que trate la siguiente redacción:

@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@Builder
public class Child extends Parent {

    @Builder
    private Child(Long id, String name) {
        super(id, name);
    }
}

pruebas unitarias volver a ejecutar anteriores, hallazgos apoyan el modo de constructor, pero lo extraño es, no a través de una sola medida.

java.lang.AssertionError: 
Esperado: 1024
Actual: null

Así que nos fijamos en el código Child.class decompilados:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.chujianyun.libs.lombok;

public class Child extends Parent {
    private Child(Long id, String name) {
        super(id, name);
    }

    public static Child.ChildBuilder builder() {
        return new Child.ChildBuilder();
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Child)) {
            return false;
        } else {
            Child other = (Child)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                return super.equals(o);
            }
        }
    }

    protected boolean canEqual(final Object other) {
        return other instanceof Child;
    }

    public int hashCode() {
        int result = super.hashCode();
        return result;
    }

    public String toString() {
        return "Child()";
    }

    public Child() {
    }

    public static class ChildBuilder {
        private Long id;
        private String name;

        ChildBuilder() {
        }

        public Child build() {
            return new Child();
        }

        public String toString() {
            return "Child.ChildBuilder()";
        }

        public Child.ChildBuilder id(final Long id) {
            this.id = id;
            return this;
        }

        public Child.ChildBuilder name(final String name) {
            this.name = name;
            return this;
        }
    }
}

Encontrado la razón, durante el uso de notas @Builder en la sub-clase constructor y los parámetros completos, habrá ERROR, es decir, la versión final () la función simplemente devuelve un constructor parámetro nulo crea un objeto secundario, por lo que la propiedad "adoptada constructor de modo Identificación y ajuste el nombre de "final" perdida ".

 

Entonces, ¿cómo resolver este problema?

Una vez más, volvemos a la fuente del comentario @Builder:

If a member is annotated, it must be either a constructor or a method. If a class is annotated,
* then a private constructor is generated with all fields as arguments
* (as if {@code @AllArgsConstructor(access = AccessLevel.PRIVATE)} is present
* on the class), and it is as if this constructor has been annotated with {@code @Builder} instead.

Encontrado, que se agrega a la clase correspondiente al constructor privado contiene todos los atributos, y la adición de anotaciones en @Builder constructor.

Así que escribir el código puede tener un conflicto, se modifica como sigue:

import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
public class Child extends Parent {

    @Builder
    private Child(Long id, String name) {
        super(id, name);
    }
}

La única final medida por

Nos fijamos en el código compilado en este momento:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.chujianyun.libs.lombok;

public class Child extends Parent {
    private Child(Long id, String name) {
        super(id, name);
    }

    public static Child.ChildBuilder builder() {
        return new Child.ChildBuilder();
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Child)) {
            return false;
        } else {
            Child other = (Child)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                return super.equals(o);
            }
        }
    }

    protected boolean canEqual(final Object other) {
        return other instanceof Child;
    }

    public int hashCode() {
        int result = super.hashCode();
        return result;
    }

    public String toString() {
        return "Child()";
    }

    public Child() {
    }

    public static class ChildBuilder {
        private Long id;
        private String name;

        ChildBuilder() {
        }

        public Child.ChildBuilder id(final Long id) {
            this.id = id;
            return this;
        }

        public Child.ChildBuilder name(final String name) {
            this.name = name;
            return this;
        }

        public Child build() {
            return new Child(this.id, this.name);
        }

        public String toString() {
            return "Child.ChildBuilder(id=" + this.id + ", name=" + this.name + ")";
        }
    }
}

En este punto la función build () es el estado que necesitamos.

A partir del código compilado podemos ver claramente a través del patrón básico Lombok lógica constructor @Builder logra.

Es decir, la estructura interna de la clase, las propiedades de asignación dentro de la clase, llama al constructor contiene todos los atributos de un objeto cuando se crea la acumulación.

 

Más detalles se pueden revisar cuidadosamente @Builder código y los comentarios de la fuente anotada, ver el manual oficial  https://projectlombok.org/features/Builder

En tercer lugar, el resumen

Encontrar problemas extraños no debe dejar ir fácilmente.

Analizar los problemas tienen pasos, como si se puede echar un vistazo a las instrucciones de código fuente, también se puede mirar el código compilado, también se puede desmontar y así sucesivamente, lo que hizo un comentario para observar el impacto de los archivos de clase. También puede ver el manual oficial.

 

 

-------------------------------------------------- ---

Veo programadores CSDN 1024 evento (24 de octubre de 2019 fecha límite)

Si tengo un blog para ayudar a usted, y no hay tiempo para dar la bienvenida al navegador qué código de exploración de micro-canales a ayudarme a apoyar mi punto de elogio:

 

 
Publicados 379 artículos originales · ganado elogios 862 · Vistas 1,32 millones +

Supongo que te gusta

Origin blog.csdn.net/w605283073/article/details/102470537
Recomendado
Clasificación