Java中的泛型(Generic)

来源:互联网 发布:进入国外网站软件 编辑:程序博客网 时间:2024/05/16 11:32

一、泛型作用

* JDK5中的泛形允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定性(尤其在大型程序中更为突出)。* 注意:泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。* 泛形的基本术语,以ArrayList<E>为例:<>念着typeof*     * ArrayList<E>中的E称为类型参数变量    * ArrayList<Integer>中的Integer称为实际类型参数 整个称为    * ArrayList<E>泛型类型    * 整个ArrayList<Integer>称为参数化的类型ParameterizedType

二、泛型的典型应用

* 使用迭代器迭代泛型集合中的元素。* 使用增强for循环迭代泛型集合中的元素。* 存储HashMap中的元素* SSH框架中抽取Service层代码* 使用泛型的几个常见问题:*     * 使用泛型时,泛型类型必须为引用类型,不能是基本数据类型。    * ArrayList<String> list = new ArrayList<Object>();    * ArrayList<Object> list = new ArrayList<String>();    * ArrayList<String> list = new ArrayList ();    * ArrayList list = new ArrayList<String>();

三、自定义泛型——泛型方法

* Java程序中的普通方法、构造方法和静态方法都可以使用泛型。方法使用泛型前,必须对泛型进行声明,语法:<T>,T可以是任意字幕,但通常必须要大写。<T>通常需放在方法的返回值声明之前。例如:public static <T> void doxx(T t);* 注意:*     * 只有对象类型才能作为泛型方法的实际参数。    * 在泛型中可以同时有多个类型,例如:public static <K,V> V getValue(K key) { return map.get(key);}* 泛型类和反射泛型*     * 如果一个类多处都要用到同一个泛型,这时可以把泛型定义在类上(即类级别的泛型),语法格式如下:
public class GenericDao<T> {            private T field1;     public void save(T obj){}     public T getId(int id){}   }
    * 注意,静态方法不能使用类定义的泛型。而应单独定义泛型。    * 泛型的典型应用:BaseDao和反射泛型
public BaseDao(){   Type type=this.getClass().getGenericsuperclass();    ParamterizedType pt=(ParamterizedType )type;    clazz=pt.getActualTypeArgyments()[0];}

四、泛型的高级应用——通配符
* 定义一个方法,接收一个集合,并打印出集合中的所有元素,如下所示:

  void print (Collection<String> c) {          for (String e : c) {                System.out.println(e);          } } 
* 问题:该方法只能打印保存了Object对象的集合,不能打印其它集合。通配符用于解决此类问题,方法的定义可改写为如下形式:
  void print (Collection<?> c)  {   //Collection<?>(发音为:"collection of unknown")for (Object e : c) {   System.out.println(e);}}
* 此种形式下需要注意的是:由于print方法c参数的类型为Collection<?>,即表示一种不确定的类型,因此在方法体内不能调用与类型相关的方法,例如add()方法。* 总结:使用?通配符主要用于引用对象,使用了?通配符,就只能调对象与类型无关的方法,不能调用对象与类型有关的方法。

五、泛型的高级应用——有限制的通配符
* 限定通配符的上边界:只可读取,不可以存取

正确:Vector<? extends Number> x = new Vector<Integer>();错误:Vector<? extends Number> x = new Vector<String>();
* 限定通配符的下边界:只能存取不能读取
正确:Vector<? super Integer> x = new Vector<Number>();错误:Vector<? super Integer> x = new Vector<Byte>();

注意:
1、对象实例化时不指定泛型,默认是object
2、泛型不同的引用不能互相赋值。
3、加入集合中的对象类型必须与指定的泛型类型一致。
4、静态方法中不能使用类的泛型
5、如果泛型类是一个接口或者抽象类,则不可创建泛型类的对象。
6、不能在catch中使用泛型
7、从泛型类派生子类,泛型类需要具体化。

泛型与继承的关系:
1、A类是B类的子类,G是带泛型声明的类或接口,那么G<A>不是G<B>的子类。

通配符:
A类是B类的子类,G是带泛型声明的类或接口,则G<?>是G<A>,G<B>的父类。
1、以List<?>为例,能读取其中的数据,因为不管存储的是什么类型的元素,其一定是Object类或者其子类。
2、以List<?>为例,不可以向其中写入数据,因为没有指明可以存放到其中的元素的类型!。唯一例外的是:null。

0 0
原创粉丝点击