约束通配符

通配符实参可以像类型形参那样被约束.在创建的方法只用于特定超类的子类的对象时约束通配符特别重要.为了进一步说明原因,下面提供一个简单的示例.考虑下面的一组类:
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>的实例