传递给方法的无界通配符

时间:2011-10-17 00:33:31

标签: java generics wildcard

public class ColTest {
static<T> T wildSub(ArrayList<? extends T> holder, T arg){
        T t=holder.get(0);
        return t;
    }

    public static void main(String[] args) {
        ArrayList<?> list=new ArrayList<Long>(Arrays.asList(2L,3L,7L));
        Long lng=1L;
        ColTest.wildSub(list, lng);
    }
}

真的很有兴趣为什么这个代码段是合法的,因为wildSub的签名只需ArrayListT或来自T,而arg属于T。但<?>意味着 - 某些特定类型,未知,以及它如何满足编译器?所有类型<?>并不意味着<? extends Long> ...

4 个答案:

答案 0 :(得分:3)

编译器可以自由地推断出与参数类型和返回类型兼容的任何内容。在您的情况下,它始终可以将T推断为Object。这将签名转换为

static Object wildSub(ArrayList<?> holder, Object arg)

这意味着它可以将任何ArrayList作为第一个参数,将任何东西作为第二个参数。由于您没有对返回值执行任何操作,Object将没问题。

答案 1 :(得分:2)

如果你把它当作编译器使用Object在哪里?使用它,它编译的原因是有道理的。这就是它的全部内容。

如果您正在进行任何依赖的操作?作为某个类,如果传入了错误的类,您将在运行时获得强制转换异常。

答案 2 :(得分:1)

作为现有(正确)答案的补充,使其更加清晰:

    ...
        Object result1 = ColTest.wildSub(list, lng); //compiles fine with Sun's javac
//      Long result2 = ColTest.wildSub(list, lng);   //does not compile without explicit casting
        Long result2 = (Long) ColTest.wildSub(list, lng);   //compiles fine 
    ...

答案 3 :(得分:1)

这是由于捕获转换。在内部,编译器将表达式Foo<?>的类型转换为Foo<X>,其中X是特定的未知类型。