泛型(Generics)
泛型的定义:
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数类型,再用的时候再指定具体的类型。
泛型可以用在类,接口,方法的创建中,
泛型的类型将来传入只有引用类型(类类型,接口,数组),不能是基本数据类型
1.泛型类
一个泛型类就是具有一个或者多个类型变量(把类型参数化)的类
例如1:
//这里的T是根据将来用户使用Point类的时候所传的类型来定的
//Point<Double> p = new Point<Double>();
public class Point<T> {
private T x;
private T y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}
例2
//这里的T和S是根据将来用户使用Point类的时候所传的类型来定
//Point<String,Integer> p = new Point<String,Integer>();
public class Point<T,S> {
private T x;
private S y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public S getY() {
return y;
}
public void setY(S y) {
this.y = y;
}
}
2.泛型接口
一个泛型接口就是具有一个或者多个类型变量的接口
例如
public interface Action<T,U>{
void doSomeThing(T t,U u);
}
class ActionTest implements Action<String,Date>{
public void doSomeThing(String str,Date date) {
System.out.println(str);
System.out.println(date);
}
}
3.泛型方法
在方法上直接声明泛型,该方法就是泛型方法
例如
public class Test{
public <T> void run1(T t){
}
public <T> T run2(T t){
return t;
}
public <T,S> void run3(T t,S s){
}
}
注意:
(调用方法时传什么类型的参数,就是什么类型。)
Test t = new Test();
t.run1(1); //==>Integer类型
t.run2("Hello");//-->String类型
t.run3(2D);//-->Double类型
4.通配符( ?)
泛型中?是通配符,它可以表示所有泛型的父类型:
List<?> list = new ArrayList <任意>();
例如
//这时list可以指向任何泛型的List类型集合对象
public void test(List<?> list){
list.add(1); //编译报错,因为我们并不知道?到底代表什么类型
list.add(null); //编译通过
//编译通过
for(Object o:list){
System.out.println(o);
}
}
5.泛型中的extends和super关键字
在泛型中可以使用entends和super关键字来表示将来用户所传的泛型参数的 上限和下限。
例如
public class Point<T extends Number> {
private T x;
private T y;
}
public class Point<T extends Number,S> {
private T x;
private S y;
}
public interface Action<T extends Person> {
public void doSomeThing(T t);
}
例如: 在声明泛型方法是使用extends
public <T extends Action> void run(T t){
}
**例如:**在声明泛型类型变量时使用extends
List<? extends Number> list = new ArrayList<Integer>();
List<? extends Number> list = new ArrayList<Long>();
List<? extends Number> list = new ArrayList<Double>();
6.泛型中的&
使用&可以给泛型加多个限定
//不管该限定是类还是接口,统一都使用关键字extends
//可以使用&符号给出多个限定
//如果限定既有接口也有类,那么类必须只有一个,并且放在首位置
public class A{
}
inerface B{
}
class Point<T extends A&B> {
}
泛型举例:从1演变到4
public class Test<T,U>{
public void go1(Map<String,String> map){} //1
public void go2(Map<?,?> map){} //2
public void go3(Map<? super Number,? extends Number> map){} //3
public void go3(Map<? super T,? extends U> map){} //4
}