黑马程序员—泛型

------- android培训java培训、期待与您交流! ---------- 

 1,泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。
2,ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:
(1)整个称为ArrayList<E>泛型类型
(2)ArrayList<E>中的E称为类型变量或类型参数
(3)整个ArrayList<Integer>称为参数化的类型
(4)ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数
(5)ArrayList<Integer>中的<>念着typeof
(6)ArrayList称为原始类型
3,参数化类型与原始类型的兼容性:
(1)参数化类型可以引用一个原始类型的对象,编译报告警告,例如:
Collection<String> c = new Vector();
(2)原始类型可以引用一个参数化类型的对象,编译报告警告,例如:
Collection c = new Vector<String>();
4,参数化类型不考虑类型参数的继承关系:
(1)Vector<String> v = new Vector<Object>();//错误!
(2)Vector<Object> v = new Vector<String>();//也错误!!!!!!!!!!!
5,在创建数组实例时,数组的元素不能使 用码数化的类型,例如,下面的语句有错误:
Vector<Integer> vectorList[]= new Vector<Integer>[10];
6,思考题:下面的代码会报错吗?
Vector v1 = new Vector<String>();
Vector<Object> v = v1;
刚开始一看到这题我觉得他会报错,为了验证下自己的观点是否正确就在开发环境里试了下,结果居然没有报错,我写成这样就报错Vector<Object> v1 = new Vector<String>();后来听张老师一解说,我就明白了,原来编译器没有那么聪明,它只是按照语法来编译的,语法上能编译通过就行,第一句就是原始类型引用一个参数化类型的对象,第二句就是参数化类型引用一个原始类型的对象,所以编译器不会报错
7,Java中的泛型类型(或者泛型)类似于C++中的模板。但是这种相似性仅限于表面,Java语言中的泛型基本上完全是在编译器中实现,用于编译器执行类型检查和类型推断,然后生成普通的非泛型的字节码,这种实现技术称为擦除(erasure)(编译器使用泛型类型信息保证类型安全,然后在生成字节码之前将其清除)。这是因为扩展虚拟机指令集来支持泛型被认为是无法接受的,这会为Java厂商升级其JVM造成难以逾越的障碍。所以,Java的泛型采用了可以完全在编译器中实现的擦除方法。
8,定义泛型方法:
(1)Java的泛型方法没有C++模板函数功能强大,Java中的如下代码无法通过编译:
<T> T add(T x, T y){
return (T)(x+y);
}
(2)交换数组中的两个元素的位置的泛型方法语法定义如下:
static <E> void swap(E[] a, int i, int j){
E t = a[i];
a[i] = a[j];
a[j] = t;
}
(3)用于放置泛型的类型参数的尖括号应出现在方法的其它所有修饰符之后和在方法的返回类型之前,也就是紧邻返回值之前,按照惯例,类型参数通常用单个大写字母表示。
(4)只有引用类型才能作为泛型方法的实际参数。swap(new int[3], 3, 5);语句会报告编译错误。
9,用下面的代码说明对异常如何采用泛型:
private static <T extends Exception> sayHello()throws T{
try{
}catch(Exception e){
throw (T)e;
}
}
注意:catch方法的形参类型不能改为T
10,定义泛型类型
(1)如果类的实例对象中的多处都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,这时候就要采用泛型类型的方式进行定义,也就是类级别的泛型,语法格式如下:
public class GenericDao<T>{
private T field1;
public void save(T obj){}
public T getByID(int ID){}
}
(2)类级别的泛型是根据引用该类名时指定的类型信息来参数化类型变量的,例如,如下两种方式都可以:
GenericDao<String> dao = null;
new GenericDao<String>();
注意:
(1)在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。
(2)当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能被静态变量和静态方法调用。因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数。
11,可以通过反射获得泛型的参数化类型,以个是核心代码部分:
//Vector<Date> v1 = new Vector<Date>();
Method applyMethod = 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]);
public static void applyVector(Vector<Date> v1){
}

------- android培训java培训、期待与您交流! ---------- 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值