Subclases con Java 8 lambdas y opcional

JCN:

No entiendo por qué el siguiente código no se compila:

private ResponseEntity<JSendResponse> buildResponse(RequestModel requestModel,
                                                    RequestModelParamConverter paramConverter,
                                                    Supplier<String> xsdSupplier,
                                                    Supplier<String> xmlTemplateSupplier) {

    return Optional.ofNullable(new RequestErrorHandler<>().validate(validator, requestModel))
            .map(validationErrors -> new ResponseEntity<>(validationErrors, HttpStatus.BAD_REQUEST))
            .orElse(this.buildResponseForValidRequest(requestModel, paramConverter, xsdSupplier, xmlTemplateSupplier));
}

Error de compilación:

OrElse (org.springframework.http.ResponseEntity <com.company.util.response.JSendFailResponse>) en opcional no se puede aplicar a (org.springframework.http.ResponseEntity <com.company.util.response.JSendResponse>)

Si bien este código (que creo que es lógicamente el mismo código) hace de compilación:

private ResponseEntity<JSendResponse> buildResponse(RequestModel requestModel,
                                                    RequestModelParamConverter paramConverter,
                                                    Supplier<String> xsdSupplier,
                                                    Supplier<String> xmlTemplateSupplier) {

    JSendResponse validationErrors = new RequestErrorHandler<>().validate(validator, requestModel);

    if(validationErrors == null) {
        return this.buildResponseForValidRequest(requestModel, paramConverter, xsdSupplier, xmlTemplateSupplier);
    }
    else
    {
        return new ResponseEntity<>(validationErrors, HttpStatus.BAD_REQUEST);
    }
}

El problema parece ser que el RequestErrorHandler <> (). Devuelve el método para validar una clase llamada JSendFailResponse si falla la validación. JSendFailResponse es una subclase de JSendResponse, que es lo que se devuelve en última instancia. Parece que el código lambda no es capaz de entender que es un JSendFailResponse JSendResponse.

Puedo conseguir que se compila si yo echo validationErrors a un JSendResponse en el mapa lambda, pero luego perder algunos de los campos en la JSendFailResponse.

EDIT: Este código también falla al compilar:

private ResponseEntity<? extends JSendResponse> buildResponse(RequestModel requestModel,
                                                    RequestModelParamConverter paramConverter,
                                                    Supplier<String> xsdSupplier,
                                                    Supplier<String> xmlTemplateSupplier) {

    return Optional.ofNullable(new RequestErrorHandler<>().validate(validator, requestModel))
            .map(validationErrors -> new ResponseEntity<>(validationErrors, HttpStatus.BAD_REQUEST))
            .orElse(this.buildResponseForValidRequest(requestModel, paramConverter, xsdSupplier, xmlTemplateSupplier));
}

Edit2: He aquí un ejemplo simplificado puede copiar / pegar en su IDE para ver por sí mismo.

import java.util.*;

public class GemLamDemo {

    public static void main(String... args) {

        GemLamDemo gld = new GemLamDemo();

        gld.getList(null);

    }

    public List<? extends TypeA> getList(TypeA ta) {

        return Optional.ofNullable(ta)
                .map(a -> new ArrayList<TypeA>(Arrays.asList(a)))
                .orElse(new ArrayList<TypeB>(Arrays.asList(new TypeB())));
    }

    public class TypeA {

    }

    public class TypeB extends TypeA {

    }
}

Edit3: Estaba pensando que entendí este tema basado en la ayuda que he recibido hasta ahora, pero los siguientes compila el código y obras.

Optional.ofNullable(val1)
                .map(a -> new TypeA())
                .orElse(new TypeB());

Así que la cuestión no parece ser que el mapa y la OrElse deben devolver el mismo tipo, parece estar relacionado con paramterization. Así, el mapa puede emitir TypeA y OrElse puede emitir TypeB si es una subclase de TypeA. Pero no pueden emitir diferentes tipos parametrizados de la lista. no parecen lista <TypeA> y lista <Tipo B> para ser considerado subtipos de unos a otros y ahora que lo pienso, no lo son.

ResponseEntity <JSendResponse> es un tipo diferente de ResponseEntity <JSendFailResponse>. Si yo fuese a volver llanura JSendResponse y JSendFailResponse de las lambdas, que probablemente lo haría el trabajo. Pero no estoy, yo estoy emitiendo diferentes versiones de ResponseEntity, que no están muy relacionadas por jerarquía. Así que supongo que todo se reduce a la forma en soportes opcionales (o no admite) genéricos comodín. No puedo establecer el tipo del facultativo de ResponseEntity <? se extiende JSendResponse>, así que estoy limitado a estrictas jerarquías de tipos.

EDIT4:

El ejemplo anterior es incorrecta porque los tipos se conmutan desde el caso original. Creo que lo entiendo ahora, todo el mundo gracias.

Bohemia:

El tipo que emiten desde map()se infiere que JSendFailResponse, pero que está ofreciendo un tipo diferente orElse()y ambos tipos debe estar de acuerdo.

Explícitamente escribir para llamar a map()un tipo común:

.<JSendResponse>map(validationErrors -> new ResponseEntity<>(validationErrors, HttpStatus.BAD_REQUEST))

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=173133&siteId=1
Recomendado
Clasificación