----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ----------------------
泛型
(一)概述:
1,对于集合来讲,它里面可以装的是Object类型,但是,在jdk1.5之后,出现了泛型,所谓的泛型就是在创建一个集合的时候,首先要明确该集合需要存储对象的类型,这样就提高了安全。如:当你使用ArrayList集合时,直接这样创建ArrayList<String> al=new ArrayList<String>();明确集合存储的元素都是字符串类型的数据,这样当你往该集合中存储5的时候(此时,类型就自动装箱),就会报错。
所谓的泛型:jdk1.5出现了安全机制(也称之为新特性)
2,新特性出现的几个作用:
(1) 简化书写
(2) 提高安全性
(3) 提高效率
3,泛型出现的意义:
(1)将运行时期的问题ClassCastException转到了编译时期。
(2)避免了强制转换的麻烦(集合中添加的数据为Object,当你没有进行声明该集合中存储的数据类型是什么的时候,你取出该集合中的元素就需要强制转换成你需要取出的类型数据)
4,需要注意的是:
泛型技术是给编译器使用的技术,用于编译时期,确保了类型的安全。
运行时,会将泛型去掉,生成class文件中不带泛型的,这个称为泛型的擦除(为了兼容运行的类加载器)。
泛型的补偿:在运行时,通过获取元素的类型进行转换动作。不用使用者再强制转换了
(二)自定义泛型类
1,含义:使用泛型来接收类型中要操作的引用数据类型,就叫做泛型类(注意:jdk1.5之后才开始出现的)
2,什么时候使用呢?
当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。
如当我们需要在Tool类明确该类需要存储的对象类型时,我们可以这样来表示:
public class Tool<QQ> {//明确操作对象的工具类是QQ
}
3,将泛型定义在方法上:
public <W> void show(W str){//将泛型定义在方法上 System.out.println("str:"+str.toString());
}
其中的<W>表示定义参数类型,而括号中的W表示使用参数
4,将泛型定义在静态方法上:
public static <Y> void method(Y obj){
System.out.println("method:"+obj);
}
当方法静态时,不能访问类上定义的泛型(自定义的泛型类型是需要对象的),如果静态方法使用泛型,只能将泛型定义在方法上(需要注意的是:在静态方法上定义的泛型需要放在没有返回值void之前,静态方法static修饰符之后)
5,将泛型定义在接口上:
//泛型接口,将泛型定义在接口上
interface Inter<T>{
publicvoid show(T t);
}
class InterImpl implementsInter<String>{
publicvoid show(String str){
System.out.println("show:"+str);
}
}
class InterImpl_2<Q> implementsInter<Q>{
publicvoid show(Q q){
System.out.println("show_2:"+q);
}
}
分析:
(1)Inter接口表示该接口中的数据都是T类型的数据,当我们使用接口的时候,需要全部实现接口中的方法并且明确该接口中的存储的数据时字符串,那么就需要在后面表示出String。
(2)注意接口的固定格式:
public static final 全局常量
public abstract 抽象方法
它们的权限都是public,因此在覆写的时候,需要注意的是子类中的权限必须是public
(3)因为我们在实现接口的时候,明确了子类中的存储数据都是String,但是,当我们想要往里面存储5(自动装箱)的时候,这个时候,我们就可以在实现该接口的后面也明确该接口存储的不确定的类型,如:InterImpl_2
(三)泛型的上限与下限及其应用:
1,泛型的通配符:?(未知类型)
当我们想要输出两种集合存储的不同类型的数据时,此时,我们使用到的就是泛型的通配符,将输出的方法封装起来,提供公共的访问方式:
public staticvoid printArrayList(Collection<?> al){
for(Iterator<?>it=al.iterator();it.hasNext();){
System.out.println(it.next());
}
其中,问号就表示不知道的类型。
2,泛型中的上限(父类被固定,子类随意改变):
在泛型中,当我们想要输出定义在该类中的所有对象时,如Person类,Student和Worker继承了Person类,此时,输出语句应该如何书写呢?
我们可以根据泛型的通配符来搞定,即在输出方法的参数中改变条件,如:
publicstatic void printArrayList(Collection<? extends Person> al){},明确需要输出的类型是继承Person类的,,后面参数的条件我们称之为:泛型的限定。
当泛型被限定以后,我们就可以直接使用Person类的对象去接收迭代器取出的元素:
public static voidprintArrayList(Collection<? extends Person> al){
for(Iterator<?extends Person> it=al.iterator();it.hasNext();){
//System.out.println(it.next().toString());
Personp=it.next();
System.out.println(p.getName()+"--"+p.getAge());
}
}
3,泛型的下限:
public static voidprintArrayList(Collection<? super Student> al){//此时,可以传入Person和Student
for(Iterator<?super Student> it=al.iterator();it.hasNext();){
System.out.println(it.next());
}
不过,对于下限的做法并不是很多,,应用不是很广泛。
总结:
(1) 一般在存储元素的时候,都使用上限,因为这样取出的都是按照上限类型来运算的,不会出现类型安全隐患。
(2) 通常对集合中的元素进行取出操作的时候使用的是下限
----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ----------------------