这两个通配符之间的区别

时间:2013-02-10 16:43:01

标签: java generics

是以下方法声明吗,

public void testMethod(ArrayList<T extends Animal> list)

public <T extends Animal> void testMethod(ArrayList<T> list)

同样的?

2 个答案:

答案 0 :(得分:4)

他们 不是 在一个重要的方面是相同的。对于第一种情况,泛型参数将绑定到类的范围,并且不会更改方法的多次调用。

在第二种情况下,泛型参数将取决于调用方法的参数,并且对于每个单独的调用可以是不同的。

所以,鉴于这个课程:

public class MyClass<T extends Animal> {
    public void handleList1(List<T> list) {
       // implementation
    }

    public <U extends Animal> void handleList2(List<U> list) {
        // implementation
    }
}

将其实例化为:

MyClass<Bear> test = new MyClass<Bear>();

您只能使用handleList1类型的列表来呼叫Bear。另一方面,您可以将handleList2称为:

test.handleList2(new ArrayList<Tiger>);
test.handleList2(new ArrayList<Lion>);
test.handleList2(new ArrayList<Puma>);

因为它的泛型参数是由提供的参数决定的。

答案 1 :(得分:3)

区别在于前者不编译,后者则编译。这是你在问什么?

如果你的意思是:

public void testMethod (ArrayList <? extends Animal> list)

public <T extends Animal> void testMethod (ArrayList <T> list)

然后不同的是,在第一种情况下,您不能引用ArrayList元素的实际类型,而在第二种情况下,您可以。

如果我们考虑以下两种情况,差异可能会更明显:

public void testMethod (
    ArrayList <? extends Animal> l1, 
    ArrayList <? extends Animal> l2)

public <T extends Animal> void testMethod (
    ArrayList <T> l1, ArrayList <T> l2)

在第一种情况下,第一个参数是扩展ArrayList的某种类型的Animal,第二个参数是扩展{{1}的Arraylist或某种(可能是其他)类型}}

在第二种情况下,两个参数都是{{1>} 相同的类型,扩展了Animal