1、什么是泛型
泛型就是标签。容器要用标签标记一下,就是容器存储什么类型的数据。
ArrayList();
定义:把元素的类型设计出一个参数,这个类型参数叫泛型。Collection,List
这个就是类型参数,即泛型。
2、为什么要用泛型?
容器的默认类型是Object,那么标签的出现,是限制容器的类型。
有了泛型,这样集合就可以向数组学习。使元素更规范化。
3、泛型类、泛型接口、泛型方法
3.1、泛型类:
类中的某个或某几个属性不确定类型的时候,可以采用泛型去约定该类型,这样通用型高。
public class Order<T> {T t;}
public class Emp<K,V> {}
3.2、泛型接口:
接口中的某个或某几个属性不确定类型的时候,可以采用泛型去约定该类型,
这样通用型高。
public interface IUser<T> {T t;}
public interface IDept<K,V> {}
3.3、泛型方法:
就是给当前方法定义泛型,和当前类没有关系。
public class User {
public <E> List<E> copyArrToList(E[] arr){
if (null == arr || arr.length == 0){
return Collections.EMPTY_LIST;
}
List<E> list = new ArrayList<>(arr.length);
for (E e : arr) {
list.add(e);
}
return list;
}
}
4、通配符的使用
类A是类B的父类, G 和 G 是没有关系的,两者的共同父类是 G<?>。
4.1、上届通配符
G<? extend Number>
只允许泛型为Number及Number的子类的引用调用。
public class Person<T> { T t;}
public class SubPerson<T> extends Person<T>{}
public class Test{
public static void main (String[] args){
List<? extends Person> list = null;
List<Person> list1 = null;
List<SubPerson> list2 = null;
List<Object> list3 = null;
list = list1;
list = list2;
//list = list3; #这个编译报错
}
}
G<? extend Comparable>
只允许泛型为实现Comparable接口的实现类的引用调用。
public interface IOrder<T> {T t ;}
public class IOrderImpl<T> implements IOrder<T> {}
public class Test{
public static void main (String[] args){
List<? extends IOrder> list = null;
List<IOrder> list1 = null;
List<IOrderImpl> list2 = null;
List<Object> list3 = null;
list = list1;
list = list2;
//list = list3; #这个编译报错
}
}
4.2、下届通配符
G<? super Number>
只允许泛型为Number及Number的父类的引用调用。
public class Person<T> { T t;}
public class SubPerson<T> extends Person<T>{}
public class Test{
public static void main (String[] args){
List<? super SubPerson> list = null;
List<Person> list1 = null;
List<SubPerson> list2 = null;
List<Object> list3 = null;
list = list1;
list = list2;
//list = list3; #这个编译报错
}
}
4.3、无界通配符
意味着可以使用任何对象,但它不能使用object类型。
5、泛型擦除
泛型信息只存在于编译前,编译后的字节码中是不包含泛型中的类型信息的。因此,编译器在编译时去掉类型参数,叫做类型擦除。
例如 List<Integer>
和 List<String>
等类型在编译之后都会变成 List
。JVM看到的只是 List
,而泛型信息对JVM来说是不可见的。
Class c1 = new ArrayList<String>().getClass();
Class c2 = new ArrayList<Integer>().getClass();
System.out.println(c1 == c2); // true