泛型上限、下限所操作的运行时对象类型,永远是所给类型的子类型;
(1)上限保证返回值类型、对象能够调用的方法一定正确,但是编译器不会知道现在拿到的元素具体是哪一个子类型,既然不知道具体子类型,那也就无法将拿到的对象传入任何一个需要具体子类型的方法里面!为什么不行?因为编译器他不知道你传入的这个对象是不是你要调用的方法需要的子类型对象,万一你拿到的对象是方法需要的子类型的父类型对象或者同一个继承级别的不同子类型的对象,父类型对象不可能自动转型为子类型、不同子类型的对象自动转型该方法的子类型对象更不可能,这么一来,你不就会在运行时出现类型转换的异常了吗?所以就凭这一点,编译器就可以在编译期间报错。
(2)下限保证你拿到的对象的类型一定是你要调用的方法所需对象类型的子类型,相对而言:你拿到的对象就是子类型,你要调用方法的对象类型就是父类型;子类型向上自动转型为父类型,说的过去吧,那就没问题!但是,下限没法保证你拿到的对象到底是什么类型,只能知道你拿到的对象的类型是你所给类型的父类型,具体是什么?可能是Object、也可能是任意一个父类型,不清楚,那你既然偏要调用这种返回类型的方法的话,编译器都告诉你臣妾做不到了,不就只能编译期间报错了吗?
泛型上限:
1.表示: ? extedns T,T表示具体类型;比如? extends String;
2.(1)的示例:
public class Test{
public static T test01(final List extends T> list){
if(list != null && list.size() > 0){
// 编译器肯定这句代码绝对没问题
return list.get(0);
}
return null;
}
public Number test02(final List extends Number> list){
if(list != null && list.size() > 0){
// 编译器打包票,下面两句代码绝对没问题
System.out.println(list.get(0).doublevalue());
return list.get(0);
}
return null;
}
public static void main(String[] args){
List numberList = List.of(1, 2, 3, 2.2);
// 编译器认为:返回的一定是Number类型,是不是Integer类型不清楚;
// 编译器只知道List extends Number>里面装的一定是Number类型
System.out.println(Test.test01(numberList).getClass());
Test t = new Test();
t.test02(numberList);
// 也可以这么调用
// 此时test02方法中的?类型就是Integer类型,即:
// ? extends Number == Integer extends Number
// 承认上面等式成立,那就对了
List intList = List.of(1, 2, 3);
t.test02(intList);
}
}
2.泛型下限:
1.表示: ? super T,T表示具体类型,比如? super String;
2.(2)的示例:
public class Test{
public static void test01(final List super T> list, final T t){
if(list != null){
// 编译器敢保证,这句代码绝对没问题
list.add(t);
}
}
public void test02(final List super Integer> list, final Integer t ){
if(list != null){
// 编译器以它的人格担保,下面代码绝对没问题
list.add(t);
}
}
public static void main(String[] args){
List numberList = new ArrayList<>;
Test.test01(numberList, 2.2);
Test.test01(numberList, 1);
Test t = new Test();
List intList = new ArrayList<>();
t.test02(intList, 1);
}
}
Java不支持泛型数组!!!!!



