#泛型是JDK 1.5引入的新特性 泛型是jdk1.5后 引入的新特性,泛型在源码中使用的非常广泛,平常开发中也经常使用
那既然使用的这么广泛,你是否真正理解了,并能运用自如呢?
先抛出一个问题,既然泛型是在jdk 1.5后才引入,那之前源码是怎么写的呢?是为什么要引入呢?
搞清楚了这个,我想才能真正理解泛型设计的精髓!
#对比不同版本的JDK api
JDK1.6的ArrayList
JDK1.4的ArrayList
不同之处在于 get(int index), remove(int index)
1.4版本返回的是object类型
1.6版本返回的是泛型的类型
#为什么是object 我们都知道object是所有类的超类,那么在早期没有泛型概念的时候
其实就是用object来接收所有对象,代表任意类型
public class ObjectDemo{
private Object obj;
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
ObjectDemo od=new ObjectDemo();
od.setObj(new String("qingguguo"));
String s = (String) ot.getObj();
System.out.println("姓名是:" + s);
od.setObj(new Integer(20));
String ss = (String) ot.getObj();//强转会报类型转换异常
System.out.println("姓名是:" + ss);
复制代码
按照现在泛型的写法如下:
public class ObjectDemo2<T>{
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
ObjectDemo2<String> od=new ObjectDemo2<String>();
od.setObj(new String("qingguguo"));
String s = ot.getObj();//这里都不用强转了
System.out.println("姓名是:" + s);
od.setObj(new Integer(20));//编译期就会报错
复制代码
在向上转型为object的时候没有任何问题,但是向下转型的时候就可能会类型转换异常
这样的程序不安全,不健壮,所以java在JDK1.5后引入了泛型,以提高程序的安全性
#泛型应用
*泛型类 Arraylist
*泛型方法
*泛型接口 List Map
*泛型高级通配符
##泛型类 泛型类:把泛型定义在类上
/*
* 如果创建对象不写<T>,那么默认就是object
*/
public class ObjectDemo<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
复制代码
##泛型方法 泛型接口:把泛型定义在接口上,会根据传的类型返回传入的类型,对比下,这个用法有点意思,好好体会
public class ObjectTool<T> {
public void show(String s) {
System.out.println(s);
}
public void show(Integer i) {
System.out.println(i);
}
public void show(Boolean b) {
System.out.println(b);
}
public void show(T t) {
System.out.println(t);
}
}
复制代码
/*
*把泛型定义在方法上,方法上的泛型可以和类上的定义的泛型不一致,
*类上不定义泛型,方法上也可以定义泛型,互不干涉
*/
public class ObjectTool {
public <T> void show(T t) {
System.out.println(t);
}
}
复制代码
##泛型接口
/*
* 泛型接口:把泛型定义在接口上
*/
public interface Inter<T> {
public abstract void show(T t);
}
复制代码
那么实现类就会有两种情况要考虑: 实现类在实现接口的时候
//第一种情况:明确了类型
public class InterImpl implements Inter<String> {
@Override
public void show(String t) {
System.out.println(t);
}
}
//第二种情况:还是不明确类型,比较多是这种情况
//必须在实现类上也加上泛型
public class InterImpl<T> implements Inter<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
复制代码
##泛型高级通配符
- 泛型高级(通配符)
- ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了
- ? extends E:向下限定,E及其子类
- ? super E:向上限定,E极其父类
##泛型擦除 有这样的一个问题:ArrayList的一个对象,能在这个集合中添加一个字符串数据吗?如果能,怎么做?
// 集合对象
ArrayList array = new ArrayList();
array.add(10);
array.add("hello");//这样写肯定会报错
这些都是给编译器看的!
泛型只是在编译阶段才有,运行时是没有的,通过反编译class文件就可以看到
运行时泛型已经擦除了,所以
可以通过反射的方式拿到add方法,默认就是object方法,再调用array.add("hello")
#总结 基础决定了上层建筑,源码以及很多设计模式都用到了泛型,用的如此之广泛,
高级点的多个泛型,接口实现.如果没搞清楚,可能看的一脸懵逼.
1.泛型把明确类型的工作推迟到创建对象或者调用方法的时候才去明确
2.<数据类型>数据类型只能是引用类型
3.如果有泛型,不传的话默认就是object,但是建议有泛型最好就传入数据类型
3.泛型把运行时期的类型转换问题提前到编译期,避免了强制类型转换
4.优化程序设计,程序更健壮