泛型通配符extends与super的区别
<? extends T>限定参数类型的上界:参数类型必须是T或T的子类型
<? super T> 限定参数类型的下界:参数类型必须是T或T的超类型
总结为:
- <? extends T> 只能用于方法返回,告诉编译器此返参的类型的最小继承边界为T,T和T的父类都能接收,但是入参类型无法确定,只能接受null的传入
- <? super T>只能用于限定方法入参,告诉编译器入参只能是T或其子类型,而返参只能用Object类接收
- ? 既不能用于入参也不能用于返参
示例:
1 class Super{ 2 } 3 class Self extends Super{ 4 } 5 class Son extends Self{ 6 } 7 8 void test() { 9 List<? extends Self> a = new ArrayList<>();//参数类型上界是Self 10 a.add(new Son());//error 不能放入任何类型,因为编译器只知道a中应该放入Self的某个子类,但具体放哪种子类它并不知道,因此,除了null以外,不能放入任何类型 11 a.add(new Self());//error 12 a.add(new Super());//error 13 a.add(null);//error 14 Self s1 = a.get(0); //返回类型是确定的Self类,因为<? extends T> 只能用于方法返回,告诉编译器此返参的类型的最小继承边界为T,T和T的父类都能接收,但是入参类型无法确定,只能接受null的传入 15 Super s2 = a.get(0); //Self类型可以用Super接收 16 Son s3 = a.get(0); //error:子类不能接收父类型参数 17 18 //-------------------------------------- 19 20 List<? super Self> b = new ArrayList<>();//参数类型下界是Self 21 b.add(new Son());//ok 只能放入T类型,且满足T类型的超类至少是Self,换句话说,就是只能放入Self的子类型 22 b.add(new Self());//ok 本身类型也可以 23 b.add(new Super());//ok 超类不可以 24 b.add(null);//ok 25 Object o1 = b.get(0);//返回类型是未知的, 因为<? super T>只能用于限定方法入参,告诉编译器入参只能是T或其子类型,而返参只能用Object类接收 26 Son o2 = b.get(0);//error 27 Self o3 = b.get(0);//error 28 Super o4 = b.get(0);//error 29 30 List<?> c = new ArrayList<>(); 31 //总结: 32 // 1. <? extends T> 只能用于方法返回,告诉编译器此返参的类型的最小继承边界为T,T和T的父类都能接收,但是入参类型无法确定,只能接受null的传入 33 // 2. <? super T>只能用于限定方法入参,告诉编译器入参只能是T或其子类型,而返参只能用Object类接收 34 // 3. ? 既不能用于入参也不能用于返参 35 }