一、定义泛型类
类名<T>,其中T是泛型的名称,代表某一种类型,在创建该类对象时需要指定T所代表哪种具体的类型。如果不指定具体类型,T则采用Object类型。
public class Main<T> {
T book;
public Main(T book) {
this.book = book;
}
public T getBook(){
return book;
}
public static void main(String[] args) {
Main<String> bookName = new Main<String>("这是一本书的名字");
Main<Integer> bookPrice = new Main<Integer>(20);
System.out.println(bookName.getBook());
System.out.println(bookPrice.getBook());
}
}
创建该类对象时,<T>,T必须指定具体类类型,可以是Integer,不能是基本数据类型int。
二、泛型用法
1.定义泛型类时,可以声明多个类型,也可以声明数组类型。
public class ArrayClass<T,T2>{
private T[] array; //可以在使用泛型机制声明一个数组,但是不可以使用泛型来建立数组的实例
private T2 num; //声明一个泛型变量
public void setNum(T2 num ){ //给泛型变量赋值
this.num =num;
}
public T2 getNum(){ // 获取泛型变量
return num;
}
public T[] getArray(){ //获取泛型数组
return array;
}
public void setArray(T[] array){ // 给泛型数组赋值
this.array = array;
}
public static void main(String[] args){
//第一个对象demo的泛型<String,Integer>,String对应泛型T,Integer对应泛型T2
ArrayClass<String,Integer> demo=new ArrayClass<String,Integer>();
String value[]={"成员1","成员2","成员3","成员4","成员5","成员6"}; //定义数组
demo.setArray(value); // 将数组value[]赋值给demo对象
String array[] = demo.getArray(); //获取demo数组对象赋值给新数组array[]
for (int i=0;i<array.length;i++){
System.out.println(array[i]); //遍历输出
}
demo.setNum(2); //demo对象可以利用第二个泛型Integer赋值
System.out.println(demo.getNum());
//第二个对象demo2的泛型<Integer,String>,Integer对应泛型T,String对应泛型T2
ArrayClass<Integer,String> demo2=new ArrayClass<Integer,String>();//类似于第一个对象使用方法
Integer a[]={1,3,2,2,2};
demo2.setArray(a);
for (int i=0;i<demo2.getArray().length;i++){
System.out.println(demo2.getArray()[i]);
}
}
}
2.使用泛型约束集合的元素类型
ArrayList<Integer> a = new ArrayList<Integer>();
Map<Integer,String> m = new Map(Integer,String>();
3.在类声明时使用extends关键字限制泛型可用类型。
public class LimitClass<T extends List> { // 限制泛型的类型。向下限制
// 关键字extends后面可以接口或者类
public static void main(String[] args){
//创建类对象时,泛型必须是已经实现List接口的类
LimitClass<ArrayList> l1=new LimitClass<ArrayList>();
LimitClass<LinkedList> l2=new LimitClass<LinkedList>();
// LimitClass<HashMap> l3=new LimitClass<HashMap>();
// 这句错误,因为HashMap类没有实现List()接口。
}
}
4.通配符?,只能在创建对象的时候使用,或者用作方法参数的时候使用,而不能在声明类的泛型的时候使用
// 泛型类名称<? extends List> a = null,边界是List接口 实现对象时只能使用实现了List接口的类
// A<? extends List> a = null;
// a = new A<ArrayList>();
// a = new A<LinkedList>();
// 可以作为参数放置在一个方法中
public void doSomething(A<? extends List> a){}
使用通配符实例化泛型类对象,
List<String> l1 = new ArrayList<String>();
l1.add("成员");
List<?> l2 = l1;
List<?> l3 = new LinkedList<Integer>();
// 注意:使用通配符实例化的对象,比如l2,l3不能对其加入新的信息,只能获取l2.get()或删除l3.remove()。
// 如:l2.set(),l3.add()等,报错,不能被调用。
5.上边界限制,下边界限制
// A<? extends List> extends关键字限制了,实例化对象时只能使用实现了List接口的类,
// 也就是List类及其子类,如ArrayList,LinkedList
// A<? super List> super关键字限制了,实例化对象时只能使用List类及其父类,如Objec
6.继承泛型类,实现泛型接口
// 继承泛型类
class ExtendClass<T1>{}
class SubClass<T1,T2,T3> extends ExtendsClass<T1>{}
// 实现泛型接口
interface SomeInterface<T1>{}
class SubClass<T1,T2,T3> implements SomeInterface<T1>{}
如果在SubClass类继承ExtendClass类时保留父类的泛型类型,需要在继承时指明,如果没有指明,直接使用"extends ExtendsClass"语句进行继承操作,则SubClass类中的T1、T2和T3都会自动变为Object类型,所以在一般情况下都将父类的泛型类型保留。