使用 Lombok SuperBuilder 对类进行流映射

问题描述 投票:0回答:1

Class

MyEntity
扩展了基类。两者都有 lombok(版本 1.18.34)
@SuperBuilder
注释。

@Getter
@Setter
@SuperBuilder
@ToString(onlyExplicitlyIncluded = true)
@EqualsAndHashCode
public abstract class BaseEntity {

    public abstract SomeType getSomeType();
}
@Value
@SuperBuilder
@ToString(onlyExplicitlyIncluded = true)
@EqualsAndHashCode(callSuper = true)
public class MyEntity extends BaseEntity {

    @Override
    public SomeType getSomeType() {
        return SomeType.SOMETHING;
    }
}

如果我尝试像这样将某些内容映射到 MyEntity

someItems.stream()
    .map(item -> MyEntity.builder().build())
    .toList();

其返回类型是

List<?>
。为什么编译器无法推断出这里的类型?如果我查看
build()
方法,我确实会看到一个通用的
public abstract C build()

作为解决方法,我可以将构建移至单独的方法。

private MyEntity getBuild(SomeItem item) {
    return MyEntity.builder().build();
}


List<MyEntity> myEntities = someItems.stream() // works
    .map(item -> getBuild(item))
    .toList();
java intellij-idea stream lombok builder
1个回答
0
投票

toList
调用的返回类型不是
List<?>
,而是
List<T>
,其中
T
是上限为
MyEntity
的新类型变量。这意味着您可以将其分配给类型为
List<? extends MyEntity>
的变量。

// this compiles
List<? extends MyEntity> result = someItems.stream()
    .map(item -> MyEntity.builder().build())
    .toList();

发生这种情况的原因是因为

builder()
返回
MyEntityBuilder<?, ?>
。重要的是,它的第一个类型参数(类型
C
,也是
build
的返回类型)是一个通配符,所以我们对
C
一无所知,除了它继承自
MyEntity
之外。然后,这个
?
经过捕获转换,成为一个具有上限
MyEntity
的新类型变量。我们将新鲜类型变量称为
T

这意味着

build
将返回
T
。所以
map
返回
Stream<T>
toList
返回
List<T>

由于

T
的上限为
MyEntity
,因此可以将
T
转换为
MyEntity
。但在
T
放入列表之前,您的代码永远不会执行此操作,此时不再可能隐式执行此操作(
List<? extends MyEntity>
不是
List<MyEntity>
的子类型)。

您可以在

T
lambda 中提前进行
MyEntity
->
map
转换:

List<MyEntity> result = Stream.of(1)
        .map(item -> (MyEntity)MyEntity.builder().build())
        .toList();
© www.soinside.com 2019 - 2024. All rights reserved.