前几天我正在审查别人的代码,我遇到了引起一些担忧的一行。为了简化,假设我有一个通用类 A 和一个抽象类 B。是否允许以下实例化,如果允许,为什么?
Object obj = new A<? extends B>();
我个人从未见过像上面这样的实例化,尽管有这样的声明
A<? extends B> obj = null;
肯定会举行。我一直在泛型中使用通配符来声明方法参数,所以我可能没有经验。
前几天我正在审查别人的代码,我遇到了引起一些担忧的一行。为了简化,假设我有一个通用类 A 和一个抽象类 B。是否允许以下实例化,如果允许,为什么?
Object obj = new A<? extends B>();
我个人从未见过像上面这样的实例化,尽管有这样的声明
A<? extends B> obj = null;
肯定会举行。我一直在泛型中使用通配符来声明方法参数,所以我可能没有经验。
实际上new A<? extends B>()
不会编译。自 Java 5 以来,它一直是非法的。
但我猜你原来的例子是这样的new A<X<? extends B>>()
。后者在 Java 的最新版本中是合法的。
这个想法是,当实例化一个对象时,类型参数的值可以是任何非通配符类型。? extends B
是通配符类型,所以它是不允许的。butX<? extends B>
不是通配符类型,尽管它具有通配符类型作为组件。所以你可以说合法地打电话new A<X<? extends B>>()
。
如果你这样想,这些规则是有道理的。? extends B
最终,通配符类型不能是字段或变量的声明类型,这是更基本规则的副产品。如果A
定义为
class A<T> {
T value;
}
那么假设new A<? extends B>().value
将是一个声明为 type ? extends B
的字段。既然这是非法的,那么实例化也是如此。但是new A<X<? extends B>>()
没有那个问题。