概念
就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称为类型实参)。
泛型在集合中的使用
List<Integer> list = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();
map.put("tom1",1);
map.put("tom2",2);
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entrySet.iterator();
while (iterator.hasNext()){
Map.Entry<String, Integer> entry = iterator.next();
System.out.println(entry.getKey() + "--->>" + entry.getValue());
}
自定义泛型结构
自定义泛型类、泛型接口
- 泛型类的构造器:public GenericClass(){}。而不是public GenericClass< T > (){}。
- 泛型的指定中不能使用基本数据类型,可以使用包装类替换。
- 在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型。
- 异常类不能是泛型的。
- 不能使用new T[]。但是可以:T[] elements = (T[])new Object[capacity]。
- 父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型。若子类不保留父类的泛型,则按需实现,包括没有类型擦除和指定具体类型;若子类保留父类的泛型,则包括全部保留和部分保留。
class Father<T1, T2> {}
/**
* 子类不保留父类的泛型
* 没有类型擦除,等价于class Son extends Father<Object,Object>
*/
class Son1 extends Father {}
/**
* 子类不保留父类的泛型
* 指定具体类型
*/
class Son2 extends Father<Integer, String> {}
/**
* 子类保留父类的泛型:全部保留
* @param <T1>
* @param <T2>
*/
class Son3<T1, T2> extends Father<T1, T2> {}
/**
* 子类保留父类的泛型:部分保留
* @param <T2>
*/
class Son4<T2> extends Father<Integer, T2> {}
/**
* 子类除了指定或保留父类的泛型,还可以增加自己的泛型
* @param <A>
* @param <B>
*/
class Son5<A, B> extends Father{}
class Son6<A, B> extends Father<Integer, String> {}
class Son7<T1, T2, A, B> extends Father<T1, T2> {}
class Son8<T2, A, B> extends Father<Integer, T2> {}
class Student<T>{
//使用T类型定义变量
private T name;
//使用T类型定义构造器
public Student(){}
public Student(T name) {
this.name = name;
}
//使用T类型定义一般方法
public T getName() {
return name;
}
public void setName(T name) {
this.name = name;
}
}
自定义泛型方法
格式:[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
public class DAO {
public <T> T get(int id, T t){
T result = null;
return result;
}
}
【注意】:如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G< B >并不是G< A >的子类型。
通配符的使用
- 使用类型通配符:?,比如List<?>是List< String >、List< Object >等各种泛型List的父类。
- 读取List<?>的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。
- 不能向list中写入元素。因为我们不知道list的元素类型,我们不能向其中添加对象。但唯一的例外是null,它是所有类型的成员。
【注意点】:
- 不能用在泛型方法声明上,返回值类型前面<>不能使用?。
- 不能用在泛型类的声明上。
- 不能用在创建对象上。
有限制的通配符
- <?>允许所有泛型的引用调用。
- 通配符指定上限,上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<=。比如<? extends Number> ,只允许泛型为Number及Number子类的引用调用; <? extends Comparable>,只允许泛型为实现Comparable接口的实现类的引用调用。
- 通配符指定下限,下限super:使用时指定的类型不能小于操作的类,即>=。比如<? super Number> ,只允许泛型为Number及Number父类的引用调用。