您的位置:首页 > 编程语言 > Java开发

Java中的泛型(Generic)

2017-04-22 22:25 344 查看
一、泛型作用

* 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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 泛型