为什么AbstractCollection.toArray()隐藏通用值T?

时间:2016-02-16 17:40:20

标签: java generics

作为一个类赋值,我必须实现AbstractCollection的自定义实现,并使用泛型。我发现AbstractCollection.toArray()隐藏了其默认T类型,如下所示:

public <T> T[] toArray(T[] a) { ... }

我最初认为以下内容可行,但我的IDE告诉我它不会覆盖超级:

@Override
public T[] toArray(T[] a) { ... }

所以,然后我将<T>添加到方法签名中,现在(虽然它会编译)告诉我们:

Array of type 'T[]' expected

//Reports two types of suspicious calls to Collection.toArray().
//The first type is any calls where the type of the specified array argument
// is not of the same type as the array type to which the result is casted.
//Example:
void m(List list) {
  Number[] ns = (Number[])
      list.toArray(new String[list.size()]);
}
//The second type is any calls where the type of the specified array argument doesn't match
// the type parameter of the collection declaration.
//Example:
void m(List<Number> list) {
  Number[] ns =
      list.toArray(new String[list.size()]);
}

所以,我的第一个问题是,是否有一个很好的理由为什么它以这种方式开始?其次,这会以任何方式影响我的实施吗?

1 个答案:

答案 0 :(得分:1)

Collection接口将方法声明为:

<T> T[] toArray(T[] a)

所以你必须在实现类中做同样的事情,否则它不是覆盖给定方法,而是重载。

这样做是为了向后兼容,因为该方法在将泛型添加到语言之前就存在了。官方1.4文档已不再在线提供,但您可以在此处找到它(暂时):https://www.cs.duke.edu/csed/java/jdk1.4.2/docs/api/java/util/Collection.html#toArray%28java.lang.Object[]%29

请记住,List<Number>List<Integer>在运行时实际上只是List,因为类型擦除。区别在编译时完成。另一方面,Number[]Integer[]在运行时实际上是不同的,如果值的类型错误,将抛出异常。

这意味着,如果您愿意,可以从Number[]创建List<Integer>。如果您确定所有列表元素实际上都是Integer[]个对象,您甚至可以从List<Number>创建Integer