我不明白为什么下面的代码不能编译:
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)
虽然这段代码(我认为它在逻辑上是相同的代码)确实可以编译:
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上的一些字段。
编辑:此代码也无法编译:
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:这是一个简化的示例,您可以将其复制/粘贴到您的集成开发环境中,以便自己查看。
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:我想我是根据到目前为止收到的帮助来理解这个问题的,但是下面的代码可以编译并工作。
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:
上面的例子是错误的,因为类型是从原来的情况切换过来的。我想我现在明白了,谢谢大家。
发布于 2018-12-11 06:41:00
从map()发出的类型被推断为JSendFailResponse,但是您在orElse()中提供了一个不同的类型,并且两种类型必须一致。
显式类型以使用通用类型调用map():
.<JSendResponse>map(validationErrors -> new ResponseEntity<>(validationErrors, HttpStatus.BAD_REQUEST))发布于 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作为类型,所以我猜你的方法不能工作,
您应该尝试这样做(使用简化的示例):
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 {
}希望这能有所帮助
https://stackoverflow.com/questions/53713991
复制相似问题