Avec Java 8 Sous-classes lambdas et en option

JCN:

Je ne comprends pas pourquoi le code suivant ne compile pas:

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));
}

Erreur de compilation:

OrElse (org.springframework.http.ResponseEntity <com.company.util.response.JSendFailResponse>) en option ne peut pas être appliquée à (org.springframework.http.ResponseEntity <com.company.util.response.JSendResponse>)

Bien que ce code (qui je pense est logiquement le même code) ne compile:

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);
    }
}

Le problème semble être que le RequestErrorHandler <> (). Retourne la méthode de validation d'une classe appelée JSendFailResponse si la validation échoue. JSendFailResponse est une sous-classe de JSendResponse, qui est ce qui est finalement retourné. Il semble que le code lambda ne peut pas comprendre que JSendFailResponse est un JSendResponse.

Je peux le compiler si je jetai validationErrors à un JSendResponse sur la carte lambda, mais je perds quelques-uns des champs du JSendFailResponse.

EDIT: Ce code échoue également à la compilation:

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: Voici un exemple simplifié, vous pouvez copier / coller dans votre IDE pour voir par vous-même.

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: Je pensais que je compris cette question en fonction de l'aide que je l'ai reçu à ce jour, mais le code suivant compile et travaux.

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

Donc, la question ne semble pas que la carte et le OrElse doivent retourner le même type, il semble être lié à paramterization. Ainsi, la carte peut émettre TypeA et OrElse peut émettre TypeB si sa une sous-classe de TypeA. Mais ils ne peuvent pas émettre différents types paramétrées de la liste. Liste <TypeA> et liste <TypeB> ne semblent pas être considérés comme des sous-types de l'autre et maintenant que je pense à ce sujet, ils ne sont pas.

ResponseEntity <JSendResponse> est un autre type que ResponseEntity <JSendFailResponse>. Si je rentrais JSendResponse plaine et JSendFailResponse des lambdas, qui fonctionnerait probablement. Mais je ne suis pas, j'émettre différentes versions de ResponseEntity, qui ne sont pas vraiment liés par la hiérarchie. Donc je suppose que cela revient à la façon dont les supports en option (ou ne prend pas en charge) génériques génériques. Je ne peux pas définir le type de l'option à ResponseEntity <? étend JSendResponse>, donc je suis limité à des hiérarchies de type strictes.

EDIT4:

L'exemple ci-dessus est incorrecte parce que les types sont passés du boîtier d'origine. Je pense que je reçois maintenant, tout le monde grâce.

Bohême:

Le type émis par map()est déduit que JSendFailResponse, mais vous offrez un type différent orElse()et les deux types doit être d' accord.

Déclarer explicitement le type d'appel à map()un type commun:

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

Je suppose que tu aimes

Origine http://43.154.161.224:23101/article/api/json?id=173131&siteId=1
conseillé
Classement