通配符实参可以像类型形参那样被约束.在创建的方法只用于特定超类的子类的对象时约束通配符特别重要.为了进一步说明原因,下面提供一个简单的示例.考虑下面的一组类:
class A{} class B extends A{} class C extends A{} class D{} class Gen<T> { T ob; Gen(T o) { ob = o; } }
其中类A由类B和类C扩展,但是没有被类D扩展.
接下来,考虑下面这个非常简单的泛型类:
class Gen<T> { T ob; Gen(T o) { ob = o; } }
Gen有一个类型形参,他指定保存在ob中的对象的类型.由于T被解除约束,因此T类型是非严格限定的.也就是说,T可以是任意类类型.
现在假定需要创建一个方法,以任何Gen对象的类型做为实参,只要其类型形参是A或A的子类即可.也就是说,你需要创建一个只在Gen<Type>对象上操作的方法,其中type是A或A的子类.为此,必须使用约束通配符.下面的方法test()有一个实参,实参类型是Gen对象且其类型形参是A或A的子类.
static void test(Gen<? extends A> o){}
下面的类演示了可以传递给test()的Gen对象的类型:
public class test2 { // @param args public static void main(String args[]) { A a = new A(); B b = new B(); C c = new C(); D d = new D(); Gen<A> w1 = new Gen<A>(a); Gen<B> w2 = new Gen<B>(b); Gen<C> w3 = new Gen<C>(c); Gen<D> w4 = new Gen<D>(d); UseBounded.test(w1); UseBounded.test(w2); UseBounded.test(w3); } } class A {} class B extends A{} class C extends A{} class D{} class Gen<T> { T ob; Gen(T o) { ob = o; } } class UseBounded { static void test(Gen<? extends A> o) { System.out.println("success"); } }
在main()中创建了类型为A,B,C,D的对象,然后使用他们来分别创建4个Gen对象,最后分别调用test(),把最后一次调用的代码注释掉.前3个调用是有效的,因为W1,W2,W3是Gen对象且其类型是A或A的子类.但是,最后一个对test()的调用是非法的,因为W4是D类型的对象,而D没有继承A.因此,test()中的约束通配符不接受w4作为实参.
总之,要为通配符建立上层约束,可以使用如下所示的通配符表达式:
<? extends superclass>
其中,superclass是用作上层约束的类名.注意这里有一条包含性子句,因为构成上层约束(由superclass指定)的类也在约束中.
还可以指定通配符的下层约束,方法是在通配符声明中添加一条super子句,一般形式如下所示:
<? super subclass>
在本例中,只有subclass的超类是可接受的实参,这是一条包含性子句.
问:可以把一个泛型类的一个实例强制转换为另一个实例吗?
答:可以,但是二者必须兼容,并且其类型实参也要相同.例如,假定泛型类Gen的声明如下所示:
class Gen<T>
接下来假定x的声明如下所示:则下面的转换是合法的:
Gen<Integer> x = new Gen<Integer>(); (Gen <Long>)x
因为x是Gen<Integer>的实例,但是下面的转换不合法:
(Gen<Long>)x
因为x不是Gen<Long>的实例