如何将List <? extends Foo> 转换为 List<Foo>?

17

Spring Batch的ItemWriter接口如下:

write(List<? extends T> items); 

我想让 ItemWriter 调用一个服务,但我的服务有以下代码:

process(List<T> items); 

据我所知,Java泛型在集合中严格限制类型转换。

为什么你的服务有 process(List<T> items) 而不是 process(List<? extends T> items) - ILMTitan
2
因为那是我想要的。我不必遵循Spring的规定。 - pri
为什么你想要那个?你是要插入元素到项中吗(这是唯一会因将其设置为通配符而失去的功能)? - ILMTitan
作为服务,签名使用List<T>比通配符更清晰和声明性强,而服务并不需要通配符。(虽然在其他情况下也很有用)。 - pri
6个回答

15

直接强制转换即可。在读取时,List<? extends Foo> 确实是一个 List<Foo>,转换是绝对安全的。如果你过于谨慎,可以使用 Collections.unmodifiableList() 进行包装。

List<? extends Foo> foos1 = ...;

@SuppressWarnings("unchecked")
List<Foo> foos2 = (List<Foo>)(List<?>)foos1;    

2
了不起。你是上帝。 PS:请注意Java泛型的糟糕之处。 - pri
5
为什么需要额外的(List<?>)转换? - David Bosschaert

7

确保你的方法接收一个从T继承的对象,然后执行转换操作。

或者更改你的方法签名以与写入方法相等。


为什么我要为Spring更改我的签名?不需要。 - pri
1
我说过我不会进行更改,只是提供了一个建议。他可以使用给定的转换选项。 - Tarcísio Júnior

5
List<? extends Foo> list1 = ...
List<Foo> list2 = Collections.unmodifiableList(list1);

为什么list2必须是list1的只读视图,这在泛型:List与List相同?的回答中有很好的解释。


2
如果您的服务允许 ? extends T,那么类型应该是这样的。目前,它表示传入的内容必须完全是 T

1
他明确表示该服务接收List<T>,而不是List<? extends T>。 - Yngvar Kristiansen

1
Java中的泛型只在编译时起作用。您可以强制转换任何内容,确保该值可以转换为新类型。

0

既然您知道如果有一个扩展了Foo的类型,它就是一个Foo,那么您为什么不可以进行强制转换呢?类似这样:

write(List<? extends Foo> items) {
    //noinspection unchecked
    process( (List<Foo>) items );
}

process(List<Foo> items) {
    // ...
}

如果您不能确定项目是否为“List<Foo>”类型,请务必捕获潜在异常。 - Jesse Webb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接