前面写了一篇文章专门用来说HashMap的,确实HashMap在平时是很是经常使用的,可是其中所涉及的内容还远远不止这些,举个例子:安全
HashMap<String,String> hashMap = new HashMap<>();
hashMap.put(1,"");//Error
复制代码
首先咱们知道,定义了一个键值对类型都是String类型的HashMap,若是你往里面丢入一个类型为非String类型的键值对,那么确定是会报错的。可是若是把尖括号及里面的内容去掉的话,程序是能够经过编译的。bash
HashMap hashMap = new HashMap<>();
hashMap.put(1,"");//Pass
复制代码
那么你会问,何苦要去掉括号呢?我明确的知道键值对的类型不是很方便嘛。确实,明确类型以后,编译器能够帮咱们检查出不少插入数据类型不正确的问题,可是要知道泛型是在JDK1.5才出现的,那么在那个没有泛型的年代,是怎么确保类型安全的呢?ide
要知道,大多数的语言在最开始的时候都是没有泛型的例如C#,Go(如今都不支持),Java。就拿前面例子中的hashMap来讲,在JDK1.5以前,能够在其中放入任何类型的数值。可是问题来了,若是咱们想构造一个只能传入<String,String>类型的HashMap要怎么作呢?能够用相似装饰器模式来实现,见代码:ui
public class MyStringHashMapDecorator {
HashMap hashMap = new HashMap();
public void put(String key , String value){
hashMap.put(key,value);
}
public HashMap get(String key){
return (HashMap) hashMap.get(key);
}
}
复制代码
可是问题来了,对于茫茫可能发生的状况,按照这样的话,我岂不是须要每一种都列出对应的状态。因此在JDK1.5中推出了泛型,简化了这些麻烦的操做,可是Java为了向后兼容性,因此这种泛型只是在编译期间存在的,运行期间仍是会经过类型擦除(Type Erasure),去掉泛型的。这一点能够经过看字节码能够看出: spa
public static void main(String[] args) {
foo(new ArrayList<String>());//Error
}
public static void foo(ArrayList<Object> objects){
//do something
}
复制代码
下面经过几个例子来引出泛型的使用:
code
好比如今要比较两个参数的大小,可是参数的类型不肯定,那么就能够用到泛型的绑定了。
举例说明:cdn
public static void main(String[] args) {
System.out.println(max(1,2));//int
System.out.println(max(1.0,2.0));//double
System.out.println(max(1.0f,2.0f));//float
System.out.println(max(1L,2L));//long
System.out.println(max("abc","abd"));//long
}
private static <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
复制代码
结果以下:blog
2
2.0
2.0
2
abd
Process finished with exit code 0
复制代码
可是在这就有疑问了:
1.为何Comparable明明是个接口,却要用extends关键字?
2.若是对两种都实现了Comparable接口,可是对两者类型不一样的参数进行比较,会有什么结果呢?
回答:
1.在泛型中,关键字extends后面既能够跟类,也能够跟接口。可是在实际意义上更接近因而绑定类型的自身或者子类型,因此用extends关键字更加接近。
2.见代码: 继承
public static void main(String[] args) {
//在ArrayList中指定了T的类型,第二个参数传入的是T类型的父类型
sort(new ArrayList<Cat>(),new AnimalComparator());
}
private static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
}
class AnimalComparator implements Comparator<Animal> {
@Override
public int compare(Animal o1, Animal o2) {
return 0;
}
}
复制代码