未知类型的数组

时间:2014-09-12 14:30:45

标签: java arrays generics

为什么表达式?[]非法?我不明白为什么它比T[]更令人怀疑。我知道通用数组创建存在问题,所以我明白为什么不允许使用new T[]new ?[3]之类的内容,但我不知道{{1}有什么问题。 }。例如,能够拥有像?[]这样的方法签名会很好。这有什么不对?

另外,编写一个采用未知类型数组的方法的首选方法是什么?你应该使用

吗?
void method(?[] arr)

优先于

public void method(Object[] arr)

或者这是常规规则的一个例外,如果类型参数只出现一次,你应该避免在方法签名中输入参数吗?

2 个答案:

答案 0 :(得分:3)

是的,您应该使用

public void method(Object[] arr)

优先于

public <T> void method(T[] arr)

因为它们都接受相同的潜在参数集,第一个更简单且类型参数更少。

  

为什么表达式?[]非法?

从语法上讲,因为[]的左侧必须是实际类型。从语言上讲,这是因为没有必要,你可以改用Object[]

一般情况下,只要你想做(? extends X)[]这样的事情,在你的脑海中,只需将其转换为X[]即可。同样,只要您想将? extends X这样的内容用作独立类型,请考虑使用X

对于泛型类型参数,需要? extends X,因为泛型类型不是协变的(List<A>不是List<B>的子类型,即使AB的子类型1}})。但是,数组类型是协变的(如果A[]B[]的子类型,AB的子类型,因此不需要(? extends X)[]

答案 1 :(得分:1)

您正在混合类型参数和类型参数!

考虑以下泛型类型List的示例:

interface List<T> {
    void add(T element);
    int size();
    T get(int index);
}

此处,T类型参数。它是“真实”类型的占位符,在实例化泛型类型时“填充”。您可以在泛型类型的实现中使用此占位符,例如声明一个变量,或作为另一个泛型类型的类型参数:

class LinkedList<T> implements List<T> {
    private Node<T> head; // here, T is the type argument of E in Node<E>
    ...
}

class Node<E> {
    private E element; // here, E is a placeholder for the 'real' type
    ...
}

类型参数是形式参数,如element是上例中方法add的形式参数。它只是运行时指定的值的占位符!

现在让我们使用泛型类型:

List<String> list = new LinkedList<String>();

此处,String类型参数,它取代了泛型类型的类型参数T

通配符('?')也是某种类型的参数,表示具体类型未知(且不相关)。因此,您可以在实例化泛型类型时使用它:

List<?> list = new LinkedList<String>();

同样,?类型参数,因此您无法像类型参数那样使用它!