回顾泛型类
泛型类:具有一个或多个泛型变量的类被称之为泛型类
1、class A<T>{
}
2、在创建泛型实例时,需要为其类型变量赋值
A<String> a=new A<String>();
*如果创建实例时,不给类型变量赋值,那么会有一个警告!
3、泛型方法:具有一个或多个类型变量的方法,称之为泛型方法!
class A<T>{
public T fun(T t1){}
}
fun()方法不是泛型方法!它是泛型类中的一个方法!
public <T> T fun(T t1){} -->它是泛型方法
*泛型方法和泛型类没有什么关系,泛型方法不一定非要在泛型类中!
4、泛型在类中或者方法中的使用
*泛型类中使用泛型:
>成员类型
>返回值类型和参数类型
>局部变量的引用上
class A<T>{
private T bean;//泛型可在成员变量上使用
public T fun(T t){}//泛型可以在类中的方法上(返回值和参数类型)使用!
public void fun2(){//泛型还可以在局部变量的引用类型上使用
T b=...
new T();//不行的
}
}
=====================================
5、泛型的继承和实现
class A<T>{}
class AA extends A<String>{} //不是泛型类,只是它爸爸是泛型类!
5.1 继承泛型类
*子类不是泛型类:需要给父类传递类型常量
>当给父类性传递的类型常量为String时,那么在父类中所有T都会被String替换
*子类是泛型类:可以给父类传递类型常量,也可以传递泛型变量
class AA1 extends A<Integer>{}
class AA3<E1> extends A<E1>(){}
============================================
泛型的通配符
1、通配符的使用场景
方法的形参!
2、通配符的优点
使方法更加通用!
3、通配符分类
无界通配 ?
子类限定:? extends Object
父类限定:? super Integer
4、通配符缺点
使变量使用上不再方便
无界:参数和返回值为泛型的方法不能使用
子类:参数为泛型的方法不能使用
父类:返回值为泛型的方法不能使用
5、比较通配符
boolean addAll(Collection<E> c)
List<Number> numList=new ArrayList<Number>();
List<Integer> intList=new ArrayList<Integer>();
numList.add(intList);//编译失败
boolean addAll(Collection<? extends E> c)
List<Number> numList=new ArrayList<Number>();
List<Integer> intList=new ArrayList<Integer>();
numList.add(intList);
package cn.itcast;import org.junit.Test;public class Demo1 {@Testpublic void fun1(){AA3<Long> aa3=new AA3<Long>();} } class A<T>{private T t;public T fun1(){return t;}public void fun2(T t){this.t=t;}}class AA1 extends A<Integer>{} class AA2 extends A<String>{}class AA3<E> extends A<E>(){ }package cn.itcast;import java.util.ArrayList; import java.util.List;import org.junit.Test;public class Demo2 {@Testpublic void fun1(){Object[] objs=new Object[10];List list=new ArrayList();String[] strs=new String[10];List<String> strList=new ArrayList<String>();Object[] objArray=new String[10];objArray[0]=new Integer(100);//java.lang.ArrayStoreException: java.lang.Integer// List<Object> objList=new ArrayList<String>();/** 泛型引用和创建两端,给出的泛型变量必须相同!*/}public void fun2(){List<Integer> integerList=new ArrayList<Integer>();print(integerList);//List<Object> list=new ArrayList<Integer>(); List<String> strList=new ArrayList<String>();print(strList);}/** 这个?就是通配符* 通配符只能出现在左边!,即不能再new时使用通配符!!!* List<? extends Object> list=new ArrayList<String>();*//** ?它表示一个不确定的类型,它的值会在调用时调用下来*/public void print(List<?> list){/** 当使用通配符,对泛型类中参数为泛型的方法起到了副作用*///list.add("hello");/** 当使用通配符时,泛型类中返回值为泛型的方法也作废了*/Object s=list.get(0);/** 通配符的好处:可以使泛型类型更加通用!尤其是在方法调用时形参使用通配符*/}public void fun3(){List<Integer> intList=new ArrayList<Integer>();print1(intList);List<Long> lonList=new ArrayList<Long>();print1(lonList);// List<String> strList=new ArrayList<String>(); // print1(strList); }/** 给通配符添加了限定* 只能传递Number或其子类* 子类统配对通用性产生了影响,但使用形参更加灵活*/public void print1(List<? extends Number> list){/** 参数为泛型的方法还是不能使用*/ // list.add(new Integer(100));/** 返回值为泛型的方法可用*/Number number=list.get(0);}public void fun4(){List<Integer> intList=new ArrayList<Integer>();print2(intList);// List<Long> lonList=new ArrayList<Long>(); // print2(lonList); List<Object> objList=new ArrayList<Object>();print2(objList);}/** 给通配符添加了限定* 只能传递Integer类型,或其父类型*/public void print2(List<? super Integer> list){/** 参数为泛型的方法可以使用了*/list.add(new Integer(100)); // Integer int1=list.get(0);/** 返回值为泛型的方法,还是不能使用*/Object obj=list.get(0);}}
反射获取类上面的泛型信息:
package cn.itcast.demo1;import java.lang.reflect.ParameterizedType;import org.junit.Test;public class Demo1 {@Testpublic void fun1(){new C();}}class A<T>{public A(){/** 在这里获取子类传递的泛型信息*/ // Type type=this.getClass().getGenericSuperclass();//获取父类的参数化类型 格式为A<String>或。。。 // ParameterizedType pType=(ParameterizedType) type; // Class c=(Class) pType.getActualTypeArguments()[0];//参数的Class数组Class c=(Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];System.out.println(c.getName());} } class B extends A<Integer>{} class C extends A<String>{}