Java:将Collection<T>向上转型为Collection<U super T>

3

我有一个Collection<T>。我有一个实现接口UManager的类TManager,该接口具有方法getCollection(),需要返回一个Collection<U>,其中U是一个接口,而T是实现U的类。

除了强制转换之外,例如return (Collection<U>)Tcoll;,是否有更正确的处理方式?

我在这里控制所有4个类/接口。在声明UManager.getCollection时,我错了吗?

public Collection<U> getCollection();

应该这样做:

public Collection<? extends U> getCollection()

?


你的代码示例有点令人困惑,你是想返回 U 还是 Collection<U>?至少,类/方法必须被指示 T 是 U 的实现。 - BalusC
Collection<U> -- 我打错了,我没有输入我想要的内容。 - Jason S
另一个困惑是,这里的 UT 实际上是接口和实现类的名称,还是只是通用类型? - BalusC
你最初是如何得到一个 Collection<T> 的?你能否创建一个 Collection<U> 来代替它呢? - Kevin Bourrillion
@BalusC:抱歉,T和U是实际类型,我应该使用类似于MyClass和MyInterface的东西。 - Jason S
@Kevin B:我有一个 Map<String, T> map;,所以我只想返回 map.values() - Jason S
4个回答

3

这取决于您需要使用集合做什么。如果您不需要将任何内容放入返回的集合中,则可以使用“extends”参数。

  public interface UInterface {

         Collection<? extends UInterface> getCollection();

  }

解决它。如果将来需要添加到集合中,只需将其包装在新的集合中并添加所有内容即可完成该任务,忽略性能问题(编译时问题会增加额外的运行时间性能损失)。

然而,如果目的是返回一个可变集合,则可以在接口中添加类型参数:

 public interface UInterface<T extends UInterface> {

        Collection<T> getCollection();

 }

那么您的实现将是这样的:
 public class TClass implements UInterface<TClass> {

        pubic Collection<TClass> getCollection();

 }

这种方法的问题在于,你必须在运行时拥有一个类型参数,才能使用接口获取可变集合,或者引用具体的类。

是的,这是一个不可变集合。对于可变集合,我通常更喜欢将集合作为输入参数传递,例如 public void getCollection(Collection<? super U> collection) - Jason S
啊哈,因为Java 5支持协变返回类型,所以你可以返回一个Collection<TClass>而不是Collection<? extends UInterface> - Jason S
@Jason S,虽然Java 5支持协变返回类型,并且这允许根据泛型参数具有不同的返回类型,这仅因为协变返回类型是可能的,但这不是这种情况。Collection<? extends U>和Collection<T>不是协变的,泛型参数只是在运行时被擦除。在这种情况下,正是类型参数让你完成了它。 - Yishai

2

我相信你想要:

public Collection<? extends U> getCollection();

你可以在这里找到一些关于这个的官方文档 @Jason,你是对的。虽然文档没有明确指出返回类型,但它确实有效。以下是一个示例方法,演示了语法:
public Collection<? extends Throwable> getErrors() {
    return new ArrayList<Exception>();
}

@saleem:你发布的链接没有详细说明通配符如何扩展返回类型。 - Jason S

2
它应该是这样的:

public Collection<U> getCollection();

尽量避免在返回类型中使用有界通配符。子类只需将返回的引用类型声明为“Collection”,而不是“Collection”。这样可以消除强制转换。但是,如果确实需要在返回类型中使用有界通配符,那么我想你将不得不返回“Collection”,并且不需要强制转换。

@notnoop: 我有一个Collection<U>,编译器不允许我返回一个没有强制转换的Collection<T>。 - Jason S

1
你的主题开头有点令人困惑,因为单字符标识符通常由泛型类型使用,但你明确提到了一个接口和一个类。所以你是在寻找像这样的东西吗?
interface UManager<T extends UInterface> {
    Collection<T> getCollection();
}

class TManager implements UManager<TClass> {
    public Collection<TClass> getCollection() {
        return Arrays.asList(new TClass(), new TClass());
    }
}

interface UInterface {

}

class TClass implements UInterface {

}

其实不是...我想我可以使用类型参数,但我宁愿不这样做。不过,你说得对!(+1) - Jason S

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