1.入门泛型的基本应用
在java1.5 之前,我们在使用集合框架的时候,返回值都是Object 对象;当我们取出来的时候需要类型转换;效率不高;从java1.5之后,引出了泛型,就不需要类型装换了。
这时集合里只能存在同一个对象,这样存贮和使用更加的安全。
2.泛型的内部原理及更深应用
泛型:是用于告诉编译器,明确的表示集合只装哪一种变量。编译完成之后已经去掉了类型信息,意思就是说他们在内存中都是同一份字节码的;以下代码返回true 说明了这个问题。
Collection<Integer>collection1 =new ArrayList<Integer>();
Collection collection2 = newArrayList();
System.out.println(collection1.getClass() ==collection2.getClass());
在编译期间去掉类型,我们叫做去类型化;
在这个时候, 我们有一些哥们就想了,去类型化是在编译间进行的,他们在内存里是同一个字节码,我们可以通过反射穿透泛型,通俗一点就是通过反射向数据里面加入不同类型的值。
代码: 向Integer 泛型集合中添加了一个字符串
packageorg.nagi.annotation;
importjava.util.ArrayList;
importjava.util.List;
publicclass TestCollection {
publicstaticvoid main(String[] args)throws Exception {
List<Integer> list1 = new ArrayList<Integer>();
List list2 = newArrayList();
list1.getClass().getMethod("add", Object.class).invoke(list1,"abcd");
System.out.println(list1.get(0));
}
}
运行结果:abcd
结果说明了:泛型只是给编译器看的。
**3.泛型的通配符扩展应用
泛型的通配符<?> 数据类型,类不能够继承。
List<? Extens Number> = new ArrayList<Integer>();正确
限定通配符的下边界
List<? super Integer> = new ArrayList<Number>(); 正确
4.泛型集合的综合应用案例
例子:迭代遍历一个泛型Map
代码:
packageorg.nagi.annotation;
importjava.util.HashMap;
importjava.util.Map;
importjava.util.Map.Entry;
importjava.util.Set;
publicclass TestCollection {
publicstaticvoid main(String[] args)throws Exception {
Map<String,Integer> m = new HashMap<String, Integer>();
m.put("high", 175);
m.put("weight", 75);
m.put("age", 23);
//得到Map的entrySet集合
Set<Map.Entry<String,Integer>> entrySet = m.entrySet();
//循环迭代
for(Entry e : entrySet){
System.out.println(e.getKey() +":"+e.getValue());
}
}
}
运行的结果:
weight:75
age:23
high:175
5.自定义泛型方法及其应用
Java 的泛型是从C++泛型继承过来的,泛型的实现基本上是编译期。
通配符类型定义
privatestatic <T> Tadd(Tx,T y){
returnnull;
}
6.自定义泛型方法的练习与类型推断总结
1、泛型转换:Object自动转换为任意类型
private static <T> TautoConvert(Object obj){
return(T)obj;
}
2、定义一个泛型,可以将任意数组中填充为任意对象。
private static <T>voidfillArray(T[] a,T obj){
for(int i=0;i<a.length;i++){
a[i] = obj;
}
}
3、打印任意类型的集合,
public static <T> void printCollection2(Collection<T> collection){
System.out.println(collection.size());
for(Object obj : collection){
System.out.println(obj);
}
}
4、把任意类型的数组复制集合到数组
public static <T>void copy1(Collection<T> dest,T[] src){
}
7.自定义泛型类的应用
在Dao 泛型的使用,在Dao层常常使用到CUID 操作, 对于不同对象有不同的CUID,这时我们考虑使用泛型来降低Dao层的代码量。这时在Dao层使用的是类级别的泛型。
importjava.util.Set;
//daodata access object--->crud
publicclass GenericDao<E> {
//save
publicvoid add(E x){
}
//查询
public E findById(int id){
returnnull;
}
//删除
publicvoid delete(E obj){
}
//通过ID删除
publicvoid delete(int id){
}
//更新
publicvoid update(E obj){
}
//通过姓名查询
public E findByUserName(String name){
returnnull;
}
//集合查询
public Set<E> findByConditions(String where){
returnnull;
}
}
8.通过反射获得泛型的实际类型参数
前面我们都知道可以通过泛型向集合中存入指点的数据,但是我们如果从数据库里面取出数据的时候,什么让它直接返回之前定义的泛型类型呢???
Hibernate 底层是可以做到这一点的;
hibernate 在从数据库里面取出数据的时候,它不是直接的通过集合方法得到的的,而是通过定义一个方法来得到的。因为Method的反射方法里面有
getGenericParameterTypes()方法,可以得到参数泛型对象。
Type[]
getGenericExceptionTypes()
返回 Type 对象数组,这些对象描述了声明由此 Method 对象抛出的异常。
Type[]
getGenericParameterTypes()
按照声明顺序返回 Type 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型的。
Type
getGenericReturnType()
返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象。
例子代码:
//通过Method
publicstaticvoid applyVector(Vector<Date> v1){
//从数据库里Load出数据
}
MethodapplyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
Type[] types =applyMethod.getGenericParameterTypes();
ParameterizedType pType =(ParameterizedType)types[0];
System.out.println(pType.getRawType());//原始的类型
System.out.println(pType.getActualTypeArguments()[0]);//实际参数类型
}