Java:泛型和通配符的区别

发布时间 2023-11-21 19:28:26作者: 爱编程DE文兄

一开始我学习通配符的时候,我觉得这个和泛型T不都一样吗?都是表示未确定的类型,有何区别

举一个下面的例子:

@Test
    public void demo1(){
        List<Object> list = null;
        
        List<String> listString = new ArrayList<>();
        List<Double> listDouble = new ArrayList<>();

        list = listString; //编译报错
        list = listDouble; //编译报错
    }

虽然String,Double是Object的子类,但是List< String> 和 List< Double> 可不是 List< Object>的子类,因此编译失败;如果你改成下面这样也是编译失败:

@Test
    public void demo1(){
        List<T> list = null;
        
        List<String> listString = new ArrayList<>();
        List<Double> listDouble = new ArrayList<>();

        list = listString; //编译报错
        list = listDouble; //编译报错
    }

编译器会认为是有个类名字就叫T,所以也报错。但改成通配符就不会了,如下:

@Test
    public void demo1(){
        List<?> list = null;

        List<String> listString = new ArrayList<>();
        List<Double> listDouble = new ArrayList<>();

        list = listString; //编译正常
        list = listDouble; //编译正常
    }

举例二:

public class Demo01<T> {

    @Test
    public void demo1(){
        List<String> listString = new ArrayList<>();
        List<Double> listDouble = new ArrayList<>();

        demo2(listString); //编译报错
        demo2(listDouble); //编译报错
    }


    public void demo2(List<T> list){

    }
}

泛型的确定是由类最先确定,接着才能定下方法的。如果你这样通过方法来确定是会报错的;但改成通配符就没事了:

public void demo2(List<?> list){

}

举例三:
这个是通配符比泛型突出不同的一点,泛型可以是任何类型不加限制,而通配符可限制类型,如下:

public static void getElement1(Collection<? extends Number> coll){}