1、什么是泛型?
泛型是jdk1.5加入的特性,泛型及“参数化类型”,参数化类型就是参数的类型也是动态化的;那么泛型会给我们程序带来什么变化?我们原来方法里只有参数是动态的,加入泛型后参数的类型也变得可以动态化了,意思是定义方法或者类的时候不指定参数的类型,等到使用的时候才指定具体指定使用什么类型;
举个简单的例子:
先假设一个场景,我们看得最多的警匪片中有许多抓捕行动中警察都喜欢有代号来代替名字,我们现在要模拟警察对象,然后他们每个人都有自己的代号;
(1)未加泛型
/**
* 警察类,此类警察只能用String字符串作为代号;
*/
public class Police {
//代号
private String code;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public void sayCodeName(){
System.out.println(code);
}
public static void main(String[] args) {
Police police1=new Police();
police1.setCode("飞鹰");
police1.sayCodeName();
Police police2=new Police();
police2.setCode("飞虎");
police2.sayCodeName();
}
}
(2)加泛型
/**
* 警察类,此类警察能任何java类型作为代号;
*/
public class Police<T> {
//代号
private T code;
public T getCode() {
return code;
}
public void setCode(T code) {
this.code = code;
}
public void sayCodeName(){
System.out.println(code);
}
public static void main(String[] args) {
Police police1=new Police();
police1.setCode("飞鹰");
police1.sayCodeName();
Police police2=new Police();
police2.setCode(110);
police2.sayCodeName();
Police police3=new Police();
police3.setCode(false);
police3.sayCodeName();
Police police4=new Police();
police4.setCode(0.11);
police4.sayCodeName();
}
}
总结: 未加泛型的方法只能用String类型的字符串来作为代号,而加入了泛型的方法可以传多个类型的数据来作为代号,这样看到是不是程序得到了很大的扩展性,同业务方法只是参数类型不同的情况我们只需要写一个方法就行了;
2、为什么要使用泛型
一个新的技术的出现一般要不是为了满足某种新的需求,要不是为了完善原来的技术;
而泛型的出现其实是为了完善以前的技术,先看在没有泛型之前我们是怎么实现参数动态化的:
public static void main(String[] args) {
List list=new ArrayList();
list.add(110);
list.add("飞鹰");
list.add(false);
for(Object object:list){
String codeName=(String) object;
}
}
这个这个List 没有使用泛型,很显然这段代码运行时候会报错,类型转换错误,因为我向list里面添加了Int,boolean,String数据类型,而拿出来的时候是强转成String 类型的,其实从代码上看,我们都能看出其中的问题,而编译器是检测不出来的;
这个例子的工作原理是这样的:
存入数据时:00,"飞鹰",false 向上转型为object
而取出数据时:object会向下转型为String (而向下转型会有安全问题,这种隐患不能在编译的时候发现,而且类型强转本来就很消耗性能);
那么我们能不能提供一个不用强转,先指定好参数类型,数据直接拿出来就可以用的方式而这就是泛型要做的事;
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add(110);//编译器提示错误,因为泛型指定的类型为string
list.add("飞鹰");
list.add(false);//此处编译器提示错误,因为泛型指定的类型为string
for(String object:list){
String codeName=object; //直接用String类型接收
}
}
总结:泛型解决了使用Object实现动态参数后,向上向下的数据转型问题;
3、泛型规则和限制
(1)泛型的类型参数只能是类类型(包括自定义类),不能是简单类型;
(2)同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的;
(3)泛型的类型参数可以有多个;
(4)泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上称为“有界类型”;
(5)泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName("Java.lang.String");
4、泛型几种使用方式
(1)泛型类
public class Police<T> {
//代号
private T code;
public T getCode() {
return code;
}
public void setCode(T code) {
this.code = code;
}
}
(2)泛型接口
public interface IPolice<T> {
public T say();
public class PoliceImpl implements IPolice<String>{
public String say() {
return "hello";
}
}
}
(3)泛型方法
5、泛型中常用的几种格式:
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型