泛型的作用就是保证集合内部的对象类型一致,并使集合一直保留这个类型的记忆,集合每次添加对象或取出对象都会给出恒定的类型,以下是泛型的基本表示方法,和泛型类的基本方法:
List<String> list=new ArrayList<>();//String 定义了List的参数类型即为泛型
class mytest<T>{
private T value;
//static T key; ① 不能在静态变量、静态方法中使用泛型
public mytest(T t){
this.value=t;
}
public void set(T t){
this.value=t;
}
public T set(){
return this.value;
}
}
值得注意的是在①处想把静态变量指定为泛型类这种情况是不允许的,同样也不能 在静态方法中使用泛型,另外其实并不存在泛型类,这里为了方便称呼统称为泛型类,一个类的泛型不同也属一个类比如ListString和ListDouble就是一个类。
在处理泛型的问题时需要注意以下几点:
1、泛型类的继承,继承泛型类时要指定泛型类的具体类型不能像其父类一样仅用形参代替:
class a extends mytest<String>{
public a(String t) {
super(t);
// TODO Auto-generated constructor stub
}}
//class a extends mytest<T>{}此处不能像定义mytest时一样使用形参变量,必须指定T的类型像上面一样
2、类型通配符,有时我们想把集合传入方法中而且希望该集合没有指定参数类型,这时候就需要使用类型通配符,类型通配符的具体使用方法如下:
public static void test(List<?> l){//设置通配符
for(int i=0;i<l.size();i++){
System.out.print(l.get(i));
}
在调用该方法的时候可以传入各种参数类型的list,这就是类型通配符的好处,此外如果想进一步明确?的类型可以使用类型通配符的上限和下限,通配符的上限是规定了集合内部的对象类型要继承?之后的类,通配符的下限是规定了集合内部的对象类型要是?之后的类的父类,具体情况如下:
public static void test2(List<? extends String> l){//设置通配符上限
for(int i=0;i<l.size();i++){
System.out.print(l.get(i));
}
}
public static void test3(List<? super String > l){//设置通配符下限
for(int i=0;i<l.size();i++){
System.out.print(l.get(i));
}
}
3、设定泛型的上下限,同类型通配符的上下限相似,泛型类也可是设定泛型的上下限,具体如下:
public class generic3 <T extends generic>{//设置泛型上限
public static void main(String arg[]){
generic test=new generic();
generic3<generic> test2=new generic3<>();//泛型为generic类或generic的子类可以创建对象
//generic3<String> test3=new generic3<>(); 泛型不是继承generic类无法创建对象
}
4、泛型方法,有一些情况下类和接口没有定义泛型但是我们还有用到它可以直接定义一个泛型方法,定义泛型方法是需要遵守很多规范如下:
//普通方法
static <T> void genericmo(T[] a,List<T> b){
for(T m:a){
b.add(m);
}
}
//构造方法
public <T> generic4(T t){
System.out.print("泛型构造方法 "+t);
}