泛型的本质是什么
什么是泛型,泛型是一种模板技术,就好比排序,所有的排序策略,核心问题是比较和交换,如果一种算法对double有效,则只要提供比较大小的规则,该算法也对String甚至任意数据类型有效,而泛型可以使得这样的排序算法一个实现就应用到多中情形。
结合这种概念,就有了泛型集合,好比ArrayList集合的实现,无论对于什么数据类型,其算法结构都是一样的,于是从JDK5后有了泛型集合。
泛型有什么好处
当然,有了泛型集合和泛型技术后,泛型带来的好处就不只是代码重用了,还包括类型安全,以及更好的可读性。要知道下面的代码,在编写代码的时候是不会报错的,要命的是在运行的时候就会:
1 List list1 = new ArrayList();// 非泛型集合 2 list1.add("testString"); 3 list1.add(Integer.valueOf(10)); 4 for (Object s : list1) { 5 Integer num = (Integer) s; 6 // 类型不安全,会抛出异常 7 }
但是如果是泛型集合,你在编写代码的时候JDK就直接告诉你这里不可以这么使用了:
Listlist2 = new ArrayList (); //list2.add(1);//类型检查,不是允许的类型无法放入集合
这就是所谓的类型安全了。这是泛型的第二个好处。
当然泛型的另外一个好处就是增强可读性,取出数据的时候不再有完全没有意义的强制类型转换,因为程序员应该知道这个类型是什么。
泛型的非协变性
Java中的泛型集合不是协变的,下面的代码你觉得可以编译通过吗:
Listlist3 = new ArrayList (); List
看起来没什么问题对吧,一个是Object集合,一个是String集合,完全兼容啊,事实上是不行的,如果行的话,泛型集合ArrayList的实例就可以装入任何对象了不是吗?
这里还有个小知识:Java的泛型支持是编译期技术,所谓的类型擦除就是这个意思,我们后面再详细聊。
那么这个问题怎么解决呢?需求是肯定存在的呀,比如我们有个方法定义:
public static void printElements(List
这个方法希望接受任何List集合,显然通过上面的内容,我们知道传参数是传不进去的。
解决的办法很简单,讲List
//方法声明 public static void printElements(List> objs) //方法调用 Listlist5 = new ArrayList (); printElements(list5);
当然,?是没有任何约束,我们也可以对接受的类型进一步约束,比如下面的方法定义:
public static void printElements(List<? extends Parent> objs)
这样我们的方法要求集合的元素必须是Parent类的子类,比如Number可以限制为数字,别问我怎么知道Number的 (#^.^#)
当然,很多同学还见过这种的:
public static void printElements(List<? super Parent> objs)
反之,这样限制了参数必须是List集合且集合的元素必须是Parent类的父类。(这是super在Java中的第三种用法,你知道还有哪两种吗?)
下次我给大家分享泛型类,静态泛型方法,有兴趣的关注我的博客喲。