首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有Java 8 lambdas和可选组件的子类

具有Java 8 lambdas和可选组件的子类
EN

Stack Overflow用户
提问于 2018-12-11 05:34:39
回答 2查看 609关注 0票数 6

我不明白为什么下面的代码不能编译:

代码语言:javascript
复制
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));
}

编译错误:

不能将Optional (org.springframework.http.ResponseEntity)中的

orElse应用于(org.springframework.http.ResponseEntity)

虽然这段代码(我认为它在逻辑上是相同的代码)确实可以编译:

代码语言:javascript
复制
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);
    }
}

问题似乎在于,如果验证失败,RequestErrorHandler<>().validate方法将返回一个名为JSendFailResponse的类。JSendFailResponse是最终返回的JSendResponse的子类。似乎lambda代码不能理解JSendFailResponse是一个JSendResponse。

如果我在map lambda中将validationErrors强制转换为JSendResponse,我可以编译它,但这样我就会丢失JSendFailResponse上的一些字段。

编辑:此代码也无法编译:

代码语言:javascript
复制
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:这是一个简化的示例,您可以将其复制/粘贴到您的集成开发环境中,以便自己查看。

代码语言:javascript
复制
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:我想我是根据到目前为止收到的帮助来理解这个问题的,但是下面的代码可以编译并工作。

代码语言:javascript
复制
Optional.ofNullable(val1)
                .map(a -> new TypeA())
                .orElse(new TypeB());

所以问题似乎不是映射和orElse必须返回相同的类型,它似乎与参数化有关。因此,map可以发出TypeA,如果orElse是TypeA的子类,那么它也可以发出TypeB。但是它们不能发出列表的不同参数化类型。List和List似乎不被认为是彼此的子类型,现在我想起来,它们不是。

ResponseEntity是与ResponseEntity不同的类型。如果我从lambda返回普通的JSendResponse和JSendFailResponse,这可能会起作用。但我没有,我发出了不同版本的ResponseEntity,它们实际上并不是按层次结构相关的。所以我猜这归结于Optional如何支持(或不支持)通配符泛型。我不能将可选的类型设置为ResponseEntity<?扩展了JSendResponse>,所以我仅限于严格的类型层次结构。

EDIT4:

上面的例子是错误的,因为类型是从原来的情况切换过来的。我想我现在明白了,谢谢大家。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-12-11 06:41:00

map()发出的类型被推断为JSendFailResponse,但是您在orElse()中提供了一个不同的类型,并且两种类型必须一致。

显式类型以使用通用类型调用map()

代码语言:javascript
复制
.<JSendResponse>map(validationErrors -> new ResponseEntity<>(validationErrors, HttpStatus.BAD_REQUEST))
票数 6
EN

Stack Overflow用户

发布于 2018-12-11 06:38:24

如果检查oracle文档:https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html

.ofNullable()方法的签名是:public static <T> Optional<T> ofNullable(T value)

orElse()public T orElse(T other)

所以两个方法类型上的参数都是T,而orElse()没有<? extends T>作为参数,它们都应该有T作为类型,所以我猜你的方法不能工作,

您应该尝试这样做(使用简化的示例):

代码语言:javascript
复制
public List<TypeA> getList(TypeA ta) {

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

    public class TypeA {

    }

    public class TypeB extends TypeA {

    }

希望这能有所帮助

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53713991

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档