深入了解泛型
泛型是为编译器用的
可以用反射跳过编译
例如ArrayList<Integer>collection = new ArrayList<Integer>();
collection.add("abb");//编译器会报错
//通过反射
collection.getClass().getMethod("add",Object.class).invoke(collection,"sd");
因为编译器编译后会去掉泛型,所以在内存中不存在泛型
几种错误
Collection<String>c = new Vector();警告
Collectionc= new Vector<String>();警告
Collection<String>c = new Vector<Object>();错误
Collection<Object>c = new Vector<String>();错误
通配符?
表示任意类型
publicstatic void printCollection(Collection<?> cols){
cols.add(1);//错误?可以代表任意类型
cols.size();//正确,此方法和类型参数无关
cols= new HashSet<Date>()//正确,如果作为参数传递过来,是可以的。因为cols可以表示任意类型
}
publicstatic void printCollection(Collection<Object> cols){
cols.add(1);//正确
cols= new HashSet<Date>()//错误,相当于赋值,传参,类型错误
cols.size();//正确,此方法和类型参数无关
}
使用?通配符可以引用其他各种参数化的类型,?通配符的作用主要用作引用
,可以调用与参数化无关的方法,不能调用与参数化有关的方法
限定
上限
Vector<?extendsNumber> x = new Vector<Integer>();//正确,必须是Number的子类或者本身
Vector<?extendsNumber> x = new Vector< String >();//错误
下限
Vector<?superInteger> x = new Vector<Number>();//正确,必须是Integer的父类或者本身
Vector<?superInteger> x = new Vector<Byte>();//错误
a<?>= new a<Integer>();可以,反过来不可以
编译器不允许创建类型变量的数组
Vector<Integer>[]list = new Vector<Integer>[10];//错误
HashMap 的迭代
HashMap<String,Integer>map = new HashMap<string,Integer>)();
map.add("sd",1);
map.add("s",3);
map.add("sdd",4);
Set<Map.Entry<String,Integer>>entrySet = map.entrySet();
for(Map.Entry<String,Integer>entry:entrySet){
entry,getKey();entry.getValue();
}
泛型的应用
泛型先定义后使用
publicstatic <T> void swap(T[] a ,int i,int j){
Ttemp = a[i];
a[i] = a[j];
a[j]= temp;
}
swap(newString[]("s","s"),0,1);//正确
swap(newint[]{1,2,3,4,4},2,3);//错误,因为基本数据类型不能作为T实际类型
privatestatic <T> TconvertObj(Object obj){
return(T)obj
}
privatestatic <T> void arr(T[] a,T v){
for(inti = 0;i<a.length;i++){
a[i]= v
}
}
privatestatic <T> void printCollection(Collection<T> cols,T t){
cols.add(t);//正确,因为类型就是T,确定类型就可以增加了
}
privatestatic <T> void copyData(T[] arr,Collection<T> cols){
inti = 0;
for(Tc:cols){
arr[i]= c
i++;
}
}
在类上用泛型
publicclss Dao<T>{
publicvoid add(T t){
}
publicvoid delete(T t){}
publicvoid update(T t){}
publicSet<T> findByConditions(String where){return null}
publicstatic void update(T t){}//出错,静态不能用类泛型,除非单独定义泛型因为静态方法单独存在
}
可以保证T是同一种类型,因为是在类上定义的
如果是 public<T> void delete(T t){}
public<T> void udpate(T t){}
则就不能保证是同一个类型
Dao<RefkectPoint>da = new Dao<RefkectPoint>();
如何确定一个集合中元素的类型
Vector<Date>v ;无法通过v本身来得到
可以把v放在一个方法里
publicstaic void applyVector(Vector<Date> v){}
publicstatic void main(){
//得到该类的字节码对象,通过字节码对象来得到该方法
Methodmethod = GenericTest.class.getMethod("applyVector",Vector.class);
//得到该方法的泛化类型列表
Type[]types = method.getGenericParameterTypes();
//转为变量类型
ParameterizedTypeptype = (ParameterizedType) types[0];
//得到原始类型
ptype.getRawType();//Vector
得到真实类型
ptype.getActualTypeArguments()[0];//Date
}