一、概念
1、定义:
在定义类或接口通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。
2、引入:
从JDK1.5后,Java引入“参数化类型”概念,即在创建集合时指定可以再指定元素类型。
3、优点:
a、解决元素存储的安全性问题;
b、解决获取元素时,需要类型强制转化的问题;
二、自定义泛型
1、自定义泛型类、泛型接口
class DAO<T>{
private Map<String,T> map=new HashMap<>();
public void save(String id,T entity){
map.put(id,entity);
}
public T get(String id){
return map.get(id);
}
public void update(String id,T entity){
if(map.containsKey(id)){
map.put(id,entity);
}
}
public List<T> list(){
ArrayList<T> arrayList=new ArrayList<>();
Collection<T> values = map.values();
for(T t:values){
arrayList.add(t);
}
return arrayList;
}
注:
a、如interface List<T>,class FanTest<K,V>中T、K、V仅表示类型,其中使用任意字母都可以;
b、泛型实例化时,一定要在类名指定类型参数的值;(如:List<String> strList=new ArrayList<String>(); ps:其中从JDK1.7后new后面的泛型可省略)
c、接收类型可为多个,按需求设置;(如:class FanTest<K,V>中K、V均是)
d、泛型只能是类,不能用基本数据类型填充,但可以用包装类填充;
e、泛型不同的引用不能相互赋值;(编译时便报错)
f、如果编译时有ArrayList<String>和ArrayList<Integer>两种类型,但在运行时只会有一个ArrayList被加载到JVM中;
g、泛型如果不指定,将会被擦除,泛型对应的类型都会按Object处理;(但是不等价于Object)
l、最好一开始便决定是否使用泛型,要么不用要么一路用下去;
y、在类或接口声明泛型时,即在本类本接口中代表某种类型可以作为非静态属性的类型、非静态方法的参数类型,返回值类型;(静态方法不能使用类的泛型)
j、异常类不能使用泛型;
k、不能使用new E[ ];的形式,但是可以使用E[ ] elements = (E[ ])new Object[capacity]; 的形式;
2、自定义泛型方法
class DAO1{
public <E>E get(E e){
E o=e;
return o ;
}
}
public class GenericityTest2 {
public static void main(String[] args) {
DAO1 dao1 = new DAO1();
System.out.println(dao1.get("sisi"));
}
}
注:
a、方法也可以被泛型话,无论该类是否为泛型类,在泛型方法中可以定义泛型参数,此时传入的的参数类型就是参数类型;
b、泛型方法格式是:[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常;
c、泛型方法是否为静态都可以正常通过编译运行;
三、泛型在继承上的体现
1、情况
a、如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G<B>并不是G<A>的子类型,二者是平等关系;(如:String是Object的子类,但是List<String >并不是List<Object> 的子类。)
b、如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或者接口,这时B<G>就是A<G>的子类型;(如:LinkedHashSet是HashSet的子类,同时LinkedHashSet<String>也是HashSet<String>的子类。)
四、通配符
1、通配符的使用
a、使用类型通配符:?;
b、读取如List<?>对象的list元素时,永远是安全的;(因为无论list的真实类型是什么,它包含的都是Object类型)
c、写入list中的元素时除null都不行;(因为不确定写入的具体类型)
d、通配符仅在创建集合对象中使用,无法使用于泛型类泛型方法泛型对象的创建对象上;
2、有限制的通配符
a、<?>允许所有泛型的引用调用;
b、通配符指定上线,extends->使用时指定的类型必须是继承某个类,或者实现某个接口;(如:<? extends Number>,只允许Number及其子类引用调用。)
c、通配符指定下线,super->使用时指定的类型不能小于操作的类;(如:<? extends Number>,只允许Number及其父类引用调用。)