泛型(Generic)
引入:我想使用List集合装公司的员工,却装了一条狗进来;
使用TreeSet的时候,只能存放同一种数据类型,可惜存了不同的数据类型,依然没有报错,可是运行时出错.
泛型定义:
java5开始出现的一种对Java语言类型的一种拓展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数类型时指定的类型占位符,就好比方法的形式参数是实际参数的占位符一样.
泛型能保证大型应用程序的类型安全和良好的维护性;
使用泛型的优势:
类型安全,使编译器对泛型定义的类型做判断限制.如保证TreeSet里的元素类型必须一致;消除强制类型的转换,如,使用Comparable比较时每次都需要类型强转;
泛型类
在类声明时通过一个标识符表示类中某个字段的类型或者某个方法的返回值或参数的类型,这样在类声明或实例化的时候只要指定自己需要的类型就ok。
声明带泛型的类:
class类名<泛型类型1,泛型类型2……>{
泛型类型 变量名;
泛型类型 方法名(){}
返回值类型方法名(泛型类型变量名){}
}
使用带泛型的类:
类名<具体类>对象名 = new类名<具体类>();
类型参数规范:推荐使用规范-常见的泛型,泛型只保存在源文件中,class文件中不存在;也就是说在编译阶段就会丢失,基本数据类型不能作为泛型类型;
K 键,比如映射的键 key的类型
V 值,比如Map的值 value类型
E 元素,比如Set<E> Element表示元素,元素的类型
T 泛型,Type的意思
泛型使用
publicclass Point<Q>{ //声明任意符号的标识符
privateQ x; //变量类型由外部组成
privateQ y;
public Q getX() {
return x;
}
public void setX(Q x){ //类型由外部决定
this.x = x;
}
//..........................
}
.................main.........
{
Point<Double> p = new Point<Double>(); //定义具体类型
p.setX(1.1);
p.setY(2.2);
}
声明多个泛型类型和通配符
若一个类中多个字段需要不同的泛型声明,则在声明类的时候指定多个泛型类型即可;
格式:
public interface IDAO<PK, T> {
PKadd(T t);
voidremove(PK id);
voidupdate(PK id, T t);
Tget(PK id);
}
在进行引用传递的时候泛型类型必须匹配才可以传递,否则编译不通过;
使用? ,表示未知类型的泛型对象:
List<?> 表示未知元素的List集合;
这种带通配符的List仅表示各种泛型List的父类,并不能把元素添加入集合中;
List<?> list = newArrayList<>(); list.add(1);//ERROR
public void show(List<?> list){}
//表示可接受任意类型的List集合
泛型的上限与下限
设置泛型对象的上限使用extends,表示参数类型只能是该类型或该类型的子类:
声明对象:类名<?extends 类> 对象名
定义类:类名<泛型标签 extends 类>{}
设置泛型对象的下限使用super,表示参数类型只能是该类型或该类型的父类:
声明对象:类名<?super 类> 对象名称
定义类:类名<泛型标签 extends类>{}
public static void show(List<? extends Number> l){
}
public static void show(List<? super String> l){
}
public static voidshow(List<? extends Number> l){}
public static void show(List<?super String> l){}
泛型的上限
public static voidmain(String[] args) {
Person<Integer> p1 = new Person<>();
p1.setVal(99);
Person<Double> p2 = new Person<>();
p2.setVal(3.14);
Person<String> p3 = new Person<>();
p3.setVal("007");
show(p1);//√
show(p2);//√
show(p3);//×
}
public static void show(Person<? extends Number> p){//此处限定了Person的参数类型只能是Number或者是其子类,而String并不属于Number。
System.out.println(p.getVal());
}
泛型的下限
public static void main(String[] args) {
Person<Integer> p1 = new Person<>();
p1.setVal(99);//Integer
Person<Double> p2 = new Person<>();
p2.setVal(3.14);//Double
Person<String> p3 = new Person<>();
p3.setVal("007");//String
Person<Object> p4 = new Person<>();
p4.setVal(new Object());//Object
show(p1);//×
show(p2);//×
show(p3);//√
show(p4);//√
}
public static void show(Person<? super String> p){
System.out.println(p.getVal());
}
泛型接口和方法
java5后,可以声明泛型接口,声明方式和声明泛型类是一样的。
public interface IDAO<T>{}
泛型接口子类有两种方式:
直接在子类后申明泛型;
在子类实现的接口中给出具体的泛型类型
public class DaoImpl<T>implements IDAO<T>{}
public class DaoImpl implementsIDAO<String>{}
泛型方法
方法中可定义泛型参数,形参的参数类型就是实参的类型。
格式:
<泛型标签>返回值类型 方法名([泛型标签参数]...)
publicstatic <T extends Number> List<T> show(T……t){
return null;
}
.....main.....{
//Show(new Object[]{});不可以,因为方法参数类型的限定
Show(new Number[]{});
Show(new Integer[]{});
}