List的四张面孔(泛型)

编程的时候,能在编译时发现并修改错误最好,等上线运行时报错才解决,则属于生产事故,且找到bug的位置需要花费更多的时间和精力。泛型是java1.5以后出的内容,运用泛型,指定集合中的对象类型,你可以在编译时发现类型不匹配的错误,并且取数据时不需要手动强转类型。

我们最常用的集合类之一便是List,假如我们想让这个List只放Integer类型的元素,可以这样创建集合类:

List<Integer> list = new ArrayList<Integer>;

List.add(new Integer(88));

一般的编程工作中对泛型的运用也就仅此而已,但你若想让你的程序更加安全,更加清爽,必须深入理解知识点,挖掘泛型的潜能。在此我们就循序渐进,来了解下List在运行泛型后需要注意的四张面孔

List<Object>

List

List<?>

List<E>

以下是示例代码,相关解释都在注释里面,大家可以把代码粘贴到eclipse上对照查看,效果更好

import java.util.ArrayList;
import java.util.List;
public class KnowGeneric {
 private static void normAdd(List<Object> list, Object o) {
 list.add(o);
 }
 private static void rawAdd(List list, Object o) {
 list.add(o);
 }
 private static <E> void wildCardQueryAdd(List<?> list, Object o) {
 if (list.contains(o)) {
   System.out.println("contain");
  } else {
   System.out.println("not contain");
  }
 /*
   * list集合不能添加除null以外的任何元素。 
compile error The method add(capture#1-of ?) in the
   * type List<capture#1-of ?> is not applicable for the arguments (Object)
   */
 list.add(o);
 list.add(null);
 }
 private static <E> void geneAdd(List<E> list, E e) {
 list.add(e);
 }
 public static void main(String[] args) {
  List<Integer> numList = new ArrayList<Integer>();
  List<Object> objList = new ArrayList<Object>();
 // 编译通过
 normAdd(objList, new Object());
 // normAdd
 /*
   * normAdd中定义的方法参数是List<Object>类型,rawAdd中的是List原生类型,而List<Integer>是List的子类型,
   * 却不是List<Object>的子类型,因此报如下编译错误 
 编译错误 The method normAdd(List<Object>, Object)
   * in the type Know is not applicable for the arguments (List<Integer>,
   * Integer)
   */
 normAdd(numList, new Integer(88));
 // rawAdd
 numList.clear();
 objList.clear();
 rawAdd(objList, new Object());
 /*
   * 方法声明参数类型为原生类型list,元素类型信息被抹去,以下代码虽然编译通过,
   * 运行时却会报ClassCastException错误,所以尽量不要使用list原生类型,java保留原生类型主要是为了兼容1.5以前的代码。
   * Exception in thread "main" java.lang.ClassCastException: java.lang.String
   * cannot be cast to java.lang.Integer
   */
 rawAdd(numList, "str");
  Integer num = numList.get(0);
 // geneAdd
 numList.clear();
 objList.clear();
 geneAdd(numList, new Integer(88));
 /*
   * 定义使用了泛型方法,编译时进行类型检查,添加字符串时会报编译错误。 compile error The method geneAdd(List<E>,
   * E) in the type Know is not applicable for the arguments (List<Integer>,
   * String)
   */
 geneAdd(numList, "33");
 // wildCardQueryAdd
 numList.clear();
 objList.clear();
 /*
   * 前面讲了不要使用list原生类型,如果集合中元素类型未知或者无关紧要,则可以使用无界通配符List<?>,
     不像 normAdd(numList,new Integer(88));下面这段代码可以编译通过的,但是方法体中,numList集合不能添加除null以外的任何元素。
   */
 wildCardQueryAdd(numList, new Integer(33));
 }
}

也许大家有个疑问normAdd方法只能传List<Object>类型的参数,rawAdd方法又不建议使用,而wildCardQueryAdd方法中不能对集合添加除null以外的元素(使用场景有限),那该怎么办,上面代码中的泛型方法geneAdd是一个解决途径,另外就是有界通配符了,我们下回再讲。

原文发布于微信公众号 - java达人(drjava)

原文发表时间:2016-05-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ChaMd5安全团队

PHP源码分析之parse_url()的2个小trick

之前从phithon师傅的代码审计小密圈看到pupiles师傅发过一篇文章,讲了parse_url()的很多小tricks,可惜只是给出了tricks的利用方法...

1803
来自专栏九彩拼盘的叨叨叨

学习纲要:JavaScript 数据类型

721
来自专栏王磊的博客

《JavaScript权威指南》——JavaScript核心

前言 这本由David Flanagan著作,并由淘宝前端团队译的《JavaScript权威指南》,也就是我们俗称的“犀牛书”,算是JS界公认的“圣经”了。本书...

3749
来自专栏C语言及其他语言

数组越界为什么没有出错

数组越界 在C语言中, 数组属于构造数据类型。一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不...

40310
来自专栏影子

珍爱生命,远离JS=>JS避坑记

转载请注明源地址: http://www.cnblogs.com/funnyzpc/p/8407952.html

1393
来自专栏小狼的世界

Python3.6学习笔记(三)

面向对象编程 Object Oriented Programming 简称 OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作...

862
来自专栏小樱的经验随笔

浅析ASCII、Unicode和UTF-8三种常见字符编码

什么是字符编码? 计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),...

3566
来自专栏Kevin-ZhangCG

[ Java学习基础 ] Java异常处理

3306
来自专栏机器学习算法与Python学习

python基础-字符串与编码

转载于:廖雪峰的官方网站-python教程 字符编码 我们已经讲过了,字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题。 因为计算机只能处理数字...

48011
来自专栏赵俊的Java专栏

由一道 Java finally 执行顺序的题引发的思考

2344

扫码关注云+社区

领取腾讯云代金券