泛型是jdk1.5的一种新特性:
安全方面:
例:当我们用List等集合存放数据对象时,由于list的add()方法可以传递的参数是任意的Object类型,甚至你传入的是基本数据类型也会被装箱成对应的包装类,所以不管任何类型的对象我们都已以加入到list集合中,这在编译期可以通过,但是从集合中取元素时我们却不能确定每次取出来的是什么类型的元素,所以常常会发生类型转换错误(ClassCastException),所以在运行期就会报错。专业点叫做由于参数任意化导致的类型转化错误。
在jdk1.5引入泛型之后可以通过在定义集合时就指定存放的数据类型,这样一来当集合中添加的元素类型不对时在编译期就能检测出来,甚至一些开发软件会在代码中会自动提示你错误。
泛型的定义:
泛型可以定义在接口,类和方法中:
在类上定义泛型后在类中的公有非静态方法中就不需要指明泛型,而对于非静态方法,即使在类上已经声明过了泛型在静态方法前也要加上泛型声明例如:
<span style="font-family:Microsoft YaHei;font-size:12px;">public class <T> Demo{ //这里指明了泛型
public T getXXX(T t){
return t;
}
public static <T> T getYYY(T t){ //这里要重新指明泛型
return t;
}
}</span><span style="font-size:18px;">
</span>
使用泛型要注意的地方:
1:泛型中定义变量的前后类型没有父子级关系,比如:
List<Object> list = new ArrayList<Person>(); //这种定义就是错的
List<Person> list = new ArrayList<Object>(); //这种定义也是错误的
2.使用?的泛型
public void demo2()
List<?> list = new ArrayList<Person>(); //这是可以的,因为?为通配符表明参数可以是任意类型
list.add(new Person()); //错误,即便转型了,带有通配符‘?’的泛型不能调用任何与元素类型有关的方法
list.size();//正确,该方法未涉及元素类型
List< ? extends T> list;//限定通配符的上边界:表示传入的类型必须是T或T的子类
Vector<? extends Number> v = new Vector<Number>();//正确
Vector<? extends Number> v1 = new Vector<Integer>();//正确
List<? supper T> list; //限定通配符的下边界:表示传入的参数只能是T或者T的父类
Vector<? super Integer> v2 = new Vector<Number>();//正确
Vector<? extends Integer> v3 = new Vector<Integer>();//正确
泛型与反射:
我们通常把泛型定义在父类中,从子类传递过去具体的参数类型,然后在父类的方法中获取到子类传递过来的参数的
类型即泛型变量的确定类型,然后对其操作。例如:
public acstract class baseQuery <T>{
public baseQuery(){
//构造子类时会先执行父类的构造方法,因此这里的代码会在子类中执行,这里的getGenericSuperclass()是获取父类
//上的泛型,最终获取的就是本类上的泛型,将其强转为ParameterizedType
ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
Class<T> t = (Class<T>)type.getActualTypeArguments()[0];//有可能是多个泛型例如Map中的键值对,确定只有一个时就只取第一个
System.out.println(t);
}
}