Lambda inside orElseGet in bounded wildcard generics
Lambda inside orElseGet in bounded wildcard generics
我的部分代码如下所示:
EntityTypeEnum entityType = EntityTypeEnum.fromName(entityTypeName).orElseThrow(...);
EntityService<? extends AbstractEntityDto> entityService = entityServiceFactory.getEntityService(importType);
return getFooArgs(bar)
.map(entityService::getListWithFooArgs)
.orElseGet(()->entityService.getListNoArgs());
有一个 enum,通过它我使用来自 entityServiceFactory 的静态方法获得服务 class。然后我调用方法 getFooArgs(...),即 returns Optional 。然后我想使用 EntityService 方法映射它或使用不带参数的方法来获取 "default" 值,当 getFooArgs return空可选。
public interface EntityService<T extends AbstractEntityDto> {
List<T> getListNoArgs();
List<T> getListWithFooArgs(FooArg fooArgs);
}
遗憾的是我从 IDE 得到了 Bad return type in lambda expression: List<capture of ? extends AbstractEntityDto> cannot be converted to List<capture of ? extends AbstractEntityDto>
。我要做的是:
Optional<List<? extends AbstractEntityDto>> listOptional = getFooArgs(bar)
.map(entityService::getListWithFooArgs);
if(listOptional.isPresent())
return listOptional.get();
else
return entityService.getListNoArgs();
你能解释一下为什么会这样吗?我认为它与 ?
和泛型有关,但我认为通过使用 ?
很多类型的限制都会消失。
如果代码太少无法解决,请告诉我。
我什至没有试图找出为什么编译器不接受这个结构。当谈到类型推断和通配符时,很多看起来应该有效的东西却没有。
最简单的解决方法是为 map
:
的泛型调用提供显式类型
return getFooArgs(bar)
.<List<? extends AbstractEntityDto>>map(entityService::getListWithFooArgs)
.orElseGet(entityService::getListNoArgs);
一般来说,你应该avoid wildcards in return types。随身携带通配符没有任何价值。相比之下,当您真正拥有处理 List<ConcreteEntityDto>
的代码并且需要将其传递给应该能够处理更多情况的方法时,使用通配符声明 参数类型 , 像 List<? extends AbstractEntityDto>
, 接受 List<ConcreteEntityDto>
和 List<SomeOtherEntityDto>
, 是非常有用的。
注意给定一个
List<? extends AbstractEntityDto> list = …
你可以做到
List<AbstractEntityDto> view = Collections.unmodifiableList(list);
用于不尝试修改列表的后续处理。由 unmodifiableList
编写的包装器 return 可防止任何尝试将元素插入到 AbstractEntityDto
的未知子类型列表中,但可以保证所有 AbstractEntityDto
的 return 个实例查询方法。这就是此类型更改有效的原因。
我的部分代码如下所示:
EntityTypeEnum entityType = EntityTypeEnum.fromName(entityTypeName).orElseThrow(...);
EntityService<? extends AbstractEntityDto> entityService = entityServiceFactory.getEntityService(importType);
return getFooArgs(bar)
.map(entityService::getListWithFooArgs)
.orElseGet(()->entityService.getListNoArgs());
有一个 enum,通过它我使用来自 entityServiceFactory 的静态方法获得服务 class。然后我调用方法 getFooArgs(...),即 returns Optional
public interface EntityService<T extends AbstractEntityDto> {
List<T> getListNoArgs();
List<T> getListWithFooArgs(FooArg fooArgs);
}
遗憾的是我从 IDE 得到了 Bad return type in lambda expression: List<capture of ? extends AbstractEntityDto> cannot be converted to List<capture of ? extends AbstractEntityDto>
。我要做的是:
Optional<List<? extends AbstractEntityDto>> listOptional = getFooArgs(bar)
.map(entityService::getListWithFooArgs);
if(listOptional.isPresent())
return listOptional.get();
else
return entityService.getListNoArgs();
你能解释一下为什么会这样吗?我认为它与 ?
和泛型有关,但我认为通过使用 ?
很多类型的限制都会消失。
如果代码太少无法解决,请告诉我。
我什至没有试图找出为什么编译器不接受这个结构。当谈到类型推断和通配符时,很多看起来应该有效的东西却没有。
最简单的解决方法是为 map
:
return getFooArgs(bar)
.<List<? extends AbstractEntityDto>>map(entityService::getListWithFooArgs)
.orElseGet(entityService::getListNoArgs);
一般来说,你应该avoid wildcards in return types。随身携带通配符没有任何价值。相比之下,当您真正拥有处理 List<ConcreteEntityDto>
的代码并且需要将其传递给应该能够处理更多情况的方法时,使用通配符声明 参数类型 , 像 List<? extends AbstractEntityDto>
, 接受 List<ConcreteEntityDto>
和 List<SomeOtherEntityDto>
, 是非常有用的。
注意给定一个
List<? extends AbstractEntityDto> list = …
你可以做到
List<AbstractEntityDto> view = Collections.unmodifiableList(list);
用于不尝试修改列表的后续处理。由 unmodifiableList
编写的包装器 return 可防止任何尝试将元素插入到 AbstractEntityDto
的未知子类型列表中,但可以保证所有 AbstractEntityDto
的 return 个实例查询方法。这就是此类型更改有效的原因。