1、泛型的概念
所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。
2、作用
- 添加对象:安全
- 读取对象:便捷(不需要强转)
3、自定义泛型结构
1.泛型的声明
interface List 和 class TestGen<K,V>
其中,T,K,V不代表值,而是表示类型。这里使
用任意字母都可以。常用T表示,是Type的缩写。
2.泛型的实例化
一定要在类名后面指定类型参数的值(类型)。如:
List strList = new ArrayList();
Iterator iterator = customers.iterator();
T只能是类,不能用基本数据类型填充。
3.1自定义泛型类、泛型接口
- 泛型类可能有多个参数,此时应将一起放在尖括号内 。比如: <E1,E2,E3> E1,E2,E3>
- 泛型类的构造器如下 :public GenericClass( e){}
而下面是 错误的 :public GenericClass(){} - 实例化后,操作原来泛型位置的结构必须 与指定的泛型类一致 。
- 泛型不同的引用能相互赋值。
- 泛型如果不指定,将被擦除泛对应的类均按照 Object处理,但不等价 于Object Object 。经验: 泛型要使用一路都用,要不用,一路都不用。
- 如果泛型结构 是一个接口或抽象 类,则不可创建泛型的对象。
- jdk1.7,泛型的简化 操作 :ArrayList flist = new ArrayList <>();
- 泛型的指定可以用包装类型。
- 在类/接口上声明的泛型,在本类或中即代表某种可以作为非静态 属性的类型、非静态方法参数返回值 类型 。但在静态方法中不能使用类的泛型。
- 异常类不能是泛型的
- 不能使用 new E[]。但是可以 :E[] elements = (E[])new Object[capacity [] ;
- 父类有泛型,子可以选择保留也可以指定:
Person<T>{
//使用T类型定义变量
private T info;
//使用T类型定义一般方法
public T getInfo(){
return info;
}
public void setInfo(T info){
this.info = info;
}
//使用T类型定义构造器
public Person(){}
public Person(T info){
this.info = info;
}
//static的方法中不能声明泛型
//public static void show(T t){
//}
//不能在try-catch中使用泛型定义
//try{}
//catch(T t){}
}
3.2自定义泛型方法
泛型方法的格式:
[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
示例代码如下:
public class DAO {
public <E> E get(int id, E e){
E result = null;
return result;
}}
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) {
c.add(o);
} }
4、泛型在继承上的体现
public void testGenericAndSubClass() {
Person[] persons = null;
Man[] mans = null;
// 而 Person[] 是 Man[] 的父类.
persons = mans;
Person p = mans[0];
// 在泛型的集合上
List<Person> personList = null;
List<Man> manList = null;
// personList = manList;(报错) }
5、通配符的使用
1.使用类型通配符:?
比如:List<?> ,Map<?,?>
List<?>是List、List等各种泛型List的父类。
2.读取List<?>的对象list中的元素时,安全,总是Object类型
3.写入list中的元素时,不确认元素类型,不能添加元素。null例外
类型通配符示例:
//类型通配符形式:
public interface Collection<E>{
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
}
//上面方法也可用泛型方法形式:
public interface Collection<E>{
<T> boolean containsAll(Collection<T> c);
<T extends E> boolean addAll(Collection<T> c);
}
5.1有限制的通配符
<?>:允许所有泛型的引用调用举例:
- <? extends Number> (无穷小 , Number] 只允许泛型为Number及Number子类的引用调用
- <? super Number> [Number , 无穷大) 只允许泛型为Number及Number父类的引用调用
- <? extends Comparable> 只允许泛型为实现Comparable接口的实现类的引用调用
5.2通配符使用的注意点
//注意点1:编译错误:不能用在泛型方法声明上,返回值类型前面<>不能使用?
public static <?> void test(ArrayList<?> list){
}
//注意点2:编译错误:不能用在泛型类的声明上
class GenericTypeClass<?>{
}
//注意点3:编译错误:不能用在创建对象上,右边属于创建集合对象
ArrayList<?> list2 = new ArrayList<?>();