泛型就是一个标签,表明里边放什么
用<>表示存放的是什么数据,例如
ArrayList<Integer> list = new ArrayList<Integer>();
//list中只能放int类型的数据
//jdk7新特性,自动推断:ArrayList<Integer> list = new ArrayList<>();
Map<String,Integer> map = new HashMap<String,Integer>();
总结:
① 集合接口或集合类在jdk5.0时都修改为带泛型的结构
② 在实例化集合类时,可以指明具体的泛型类型
③ 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。
比如:add(E e) --->实例化以后:add(Integer e)
④ 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换
⑤ 如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型
自定义泛型类泛型接口时,在类名后边加上<T>就行
Class Order<T>{int id;String name;T order;}
在子类继承中可以指定继承父类的泛型类类型,也可以不指定
class SubOrder extends Order<String>{}
class SubOrder<T> extends Order<T>{}
因为静态方法是在类加载的时候就加载到内存中,而泛型的指明确定是在调用构造器创对象的时候,加载静态方法时泛型T不确定
异常类不能使用泛型,try catch也不能用泛型
在方法中出现了泛型结构,方法的泛型参数与类的泛型参数不一样
如果类中定义了泛型<T>,类中带T的方法不叫泛型方法,带E或者别的方法才叫做泛型方法
public static <E> List<E> copyFromArrayToList(E[] arr){
ArrayList<E> list = new ArrayList<>();
for(E e : arr){
list.add(e);
}
return list;
}
泛型方法可以声明为静态的,因为泛型的声明是在该方法的调用时确定,不需要对象的参与
虽然类A是类B的父类,但是G<A> 和G<B>二者不具备子父类关系,二者是并列关系。
补充:类A是类B的父类,A<G> 是 B<G> 的父类
List<Object> list1 = null;
List<String> list2 = new ArrayList<String>();
//此时的list1和list2的类型不具有子父类关系
//编译不通过
//list1 = list2;
反证法:
假设list1 = list2;
list1.add(123);导致混入非String的数据,出错
通配符:?
类A是类B的父类,G<A>和G<B>是没有关系的,二者共同的父类是:G<?>
List<Object> list1 = null;
List<String> list2 = null;
List<?> list = null;
list = list1;
list = list2;
用通配符是因为list1与list2之间不能赋值,所以在调用方法时,形参若设为List<Object> list,List<String> list2就不能进来,需要重新再定义一个方法
这样会导致代码冗余,所以用List<?> list作为形参,list1与list2都能进来
写入:对于List<?> list调用方法不能添加数据即调用add()方法,只允许加null
读取:对于List<?> list调用方法允许读取数据即调用get()方法,但返回值类型是Object
? extends A:
G<? extends A> 可以作为G<A>和G<B>的父类,其中B是A的子类
? super A:
G<? super A> 可以作为G<A>和G<B>的父类,其中B是A的父类
原文:https://www.cnblogs.com/tianzhenaichirou/p/14587145.html