作为一个类赋值,我必须实现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()]);
}
所以,我的第一个问题是,是否有一个很好的理由为什么它以这种方式开始?其次,这会以任何方式影响我的实施吗?
答案 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
。