泛型是jdk15出现的新特性泛型是jdk15出现的新特性
------------------------------------------入门-----------------------------------------------------------------
1.传统集合不使用泛型的后果?
(1)取数据时需要对类型进行转换
(2)难以确定取出数据的确切类型
2.使用泛型的好处?
(1)指定集合可以容纳的数据类型;
(2)如果放入的数据类型错误,编译时会报错;
(3)不需要类型转换,如果接收类型不对,编译时也会报错
总之,使用它会让关于类型的错误在编译时期就被发现。
3.泛型不但可以使用在集合中,也可以使用在其它地方,比如Constructor<String>;
4.去类型化:
泛型信息是提供给编译器的,编译完泛型消失,JVM无法知道,所以,如果是两个ArrayList对象,使用了不同泛型,那么在运行时,它们的字节码还是同一份;而且使用反射技术可以在程序运行期间给集合里添加任意类型;
5.泛型中的术语:
ArrayList称为原始类型
整个ArrayList<E>称为泛型类型
ArrayList<E>中的E称为类型变量或类型参数
整个ArrayList<Integer>称为参数化的类型
ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数
ArrayList<Integer>中的<>念typeof
6.注意事项:
(1)如果等号两边都使用泛型,那么泛型必须一致,如如果左边是<String>,那么右边必须是<String>
(2)下面的方式正确:
Collection<String>c=newVector();
Collectionc=newVector<String>();
(3)编译器不允许创建泛型变量的数组;
Vector<Integer>vectorList[]=newVector<Integer>[10];
--------------------------------------------------高级(?通配符)------------------------------------
1.?通配符可以接受任意类型:
如定义一个方法可以打印任何泛型的set集合元素的方法privatevoidprint(Set<?>set){
.......
}
那么此方法可以接受任何泛型类型的set集合及其子类集合;
但是代码中不允许出现诸如set.add();这类与类型有关的方法,因为在我们编写源文件时?类型是不确定的。
2.泛型上下限:
List<?superInteger>x表示右边可以接收的泛型类型是Integer的父类或Integer;
List<?extendsNumber>x表示右边可以接受的泛型是Number以及其子类;
如:List<?superInteger>x=newArrayList<Number>();
List<?extendsNumber>x=newArrayList<Integer>();
问题:下面的两种定义方式在使用泛型和定义泛型类或方法时都能使用吗?
?可以被换做T吗?
--------------------------------------------自定义泛型方法------------------------------------------------
1.泛型推断:
下面的代码T取得是x,y类型的最小父类(泛型推断),因为此方法可以这样的调用(2,”String”),那么T就是Object,但是以下的代码没有意义;
<T>Tadd(Tx,Ty){
returnnull;
}
2.T只可以是引用类型:
voidadd(Tx)-->add(1)-->1会被自动装箱
voidprint(T[]x)-->print(newint[]{1,2,3})-->此调用错误
3.泛型方法实例:
publicstatic<K,F>Fvoidprint(Kk){
System.out.println(k);
return(F)newObject();
}
说明:(1)泛型必须先使用<>声明再使用;
(2)泛型K的具体类型由方法调用时传入的参数类型决定
(3)泛型F的具体类型由方法调用时接收返回的变量的类型决定;
(4)可以使用多个泛型,多个泛型在一个<>里声明
---------------------------------------------------自定义泛型类-------------------------------------------
1.自定义泛型类就是就是在类名后面加了泛型声明的类。
2.如何定义:
ClassXxxDao{
publicvoid<T>add(Tt){...}
public<T>Tget(){...}
}
如果XxxDao的对象创建时,只希望对一种类型进行操作,那么就不能使用上面的定义,因为两个T是互不相干的,为了让它们有联系,必须把T的声明加在类的后面
ClassXxxDao<T>{
publicvoidadd(Tt){...}
publicTget(){...}
}
上面的类就是一个泛型类
如果存在一个静态方法也使用泛型,那么静态方法的泛型要单独声明;
ClassXxxDao<T>{
publicvoidadd(Tt){...}
publicTget(){...}
publicstatic<T>voiddoSome(Tt){...}//注意此行的T和类上的T没有任何关系,类上的T是给对象用的
}
如果一个方法里存在多个泛型,
ClassXxxDao<T,E>{
publicvoidadd(Tt){...}
publicEfindById(intid){...}
}
--------------------------------------反射泛型类型的实际参数-----------------------------------------------
1.如何获取实际类型参数?
想要的得到类型化的类型(如ArrayList<Integer>)的实际类型参数(如Integer),无法通过ArrayList的字节码获取,只能把ArrayList<Integer>作为一个方法的参数或者返回类型,使用Method提供的方法来获取。
小插曲:因为去类型化的缘故,下面的方法不是重载
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-44333-1.html
质检总局还说他们对真假不负责任
挺好的