在Java中,为什么我只能使用泛型来限制集合参数?

时间:2017-11-03 02:58:59

标签: java generics methods

下面我有两种通用方法。两者都有两个参数化类型T和V扩展T.第一个方法foo接受类型为T和V的参数。奇怪的是,我可以调用foo(“hello”,new Integer(10))并编译并运行即使整数显然不会扩展String。第二种方法bar采用List<类型的参数。 T>和列表< V>。在这里,我不能调用bar,传递一个字符串列表和一个整数列表。为什么后者限制类型,前者不限制。

public class GenMeth {

    public static void main(String[] args) {

        List<String> s_list = new ArrayList<>();
        s_list.add("hello");

        List<Integer> i_list = new ArrayList<>();
        i_list.add(10);

        foo("hello", new Integer(10));  // will compile - why?

        bar(s_list, i_list);  // won't compile - understandable

    }

    public static <T,V extends T> void foo(T obj1, V obj2) {
            // do something
    }

    public static <T,V extends T> void bar(List<T> list1, List<V> list2) {
            // do something
    }
}

1 个答案:

答案 0 :(得分:1)

foo将始终能够获取任何引用类型的两个参数,因为TV可以选择为Object,并且任何引用类型都是Object的子类型。因此,foo也可以声明为public static void foo(Object obj1, Object obj2);它没有任何区别。声明它的方式,foo除了可以使用Object完成的事情外,没有任何Object可以对其参数做任何事情,因为类型变量没有限制,所以没有理由任何超出限制的限制都是bar

List<String>不同,因为type变量在type参数中。泛型是不变的 - List<Object>不是String的子类型(反之亦然),即使ObjectList<T>的子类型。因此,通过使第一个参数为T类型,它会强制List<String>与传递的参数的类型参数完全匹配;即通过传递T作为第一个参数,它强制StringObject;它不能是List<V>或其他任何东西 - 它不会兼容。由于第二个参数的类型为VT扩展String,因此第二个参数的类型参数必须为String或子类型为{{1 }}。 (p.s. bar也可以宣称为public static <T> void bar(List<T> list1, List<? extends T> list2)

更简单