2012-10-06 42 views
6

我前几天正在审查别人的代码,并且我遇到了一条提出了一些问题的线。为了简化,说我有一个泛型类A和一个抽象类B.是否允许以下​​实例化,如果是这样,为什么?泛型通配符实例化

Object obj = new A<? extends B>(); 

我个人从来没有见过像上面的实例,虽然声明如

A<? extends B> obj = null; 

肯定会举行。我一直使用泛型中的通配符来声明方法参数,所以我可能只是没有经验。

+0

你用什么版本的java? –

+0

相关如果不重复:http://stackoverflow.com/questions/9147129/creating-new-generic-object-with-wildcard和http://stackoverflow.com/questions/12200136/cannot-instantiate-type-in​​-泛型?lq = 1 –

回答

3

实际上new A<? extends B>()不能编译。自从Java 5以来一直非法。

但我想你的原始示例是类似于new A<X<? extends B>>()。后者在最近版本的Java中是合法的。

想法是,在实例化对象时,类型参数的值可以是任何非通配符类型。 ? extends B是通配符类型,因此它是不允许的。但是X<? extends B>不是通配符类型,尽管它具有通配符类型作为组件。所以你可以合法地称new A<X<? extends B>>()

如果你这样想,规则就有意义。最终,它是更基本规则的副产品,通配符类型如? extends B不能是声明的类型的字段或变量。如果A被定义为

class A<T> { 
    T value; 
} 

,则假设new A<? extends B>().value将宣布? extends B类型的字段。既然这是非法的,那么实例化也是非法的。但是new A<X<? extends B>>()没有这个问题。

+0

相当不错的答案,但我不认为下半部分的推理很有意义。如果一个变量'a'输入为'A ',并不意味着'a.value'被声明为'?将B' - 'value'扩展为'T',其中'A'声明'T'。 'a.value'确实*评估*为'?延伸B'。看到我对类似问题的回答[这里](http://stackoverflow.com/a/9147768/697449)。 –

+0

@PaulBellora承认,第二部分我不太清楚。我想说的是,_expression_“a.value”的推定类型和_variable_“a.value”的声明类型之间存在差异。请注意,变量既是r值又是l值,所以如果你允许创建一个带有通配符类型的变量/字段'?扩展T'(或'?super T'),这将是一个固有的残疾变量。您将无法将其用作r值(分别为l值)。现在,对于普通的参考文献'a',这是可以容忍的,但从来不会对'this'。 – Saintali