Java集合有个特点:当我们把一个对象“丢进”集合里后,集合就会“忘记”这个对象的数据类型,当再次取出该对象时,
该对象的编译类型就变成了Obejct类型(其运行时类型没变)。
Java集合之所以设计成这样,是因为设计集合的程序员不会知道我们需要它来保存什么类型的对象,所以他们把集合
设计成能保存任何类型的对象,只要求具有很好的通用性,但这样做也带来了两个问题:
== 集合对元素类型没有任何限制,这样可能引发一些问题:例如想创建一个只能保存Dog对象的集合,但程序也可以很
轻松的将Cat对象“丢”进去,所以可能引发异常。
== 由于把对象“丢进”集合时,集合丢失了对象的状态信息,集合只之道它盛装的是Object,因此取出集合元素后还
需要进行强制类型转换。这种强制类型转换既会增加编程的复杂度,也可能引发ClassException.
StrList集合类,该集合只能存放String对象。看下面的程序:
上面程序成功创建了一个特殊的List:strList,这个List集合只能保存字符串对象,不能保存其他类型的对象。创建
这种特殊集合的方法是:在集合接口、类后增加尖括号,尖括号里放一个数据类型,即表明这个集合接口、集合类只能
保存特定类型的对象。我们说List是带一个类型参数的泛型接口,在本例中,类型参数是String。在创建这个ArrayList
对象的时候也指定了一个类型参数。
该对象的编译类型就变成了Obejct类型(其运行时类型没变)。
Java集合之所以设计成这样,是因为设计集合的程序员不会知道我们需要它来保存什么类型的对象,所以他们把集合
设计成能保存任何类型的对象,只要求具有很好的通用性,但这样做也带来了两个问题:
== 集合对元素类型没有任何限制,这样可能引发一些问题:例如想创建一个只能保存Dog对象的集合,但程序也可以很
轻松的将Cat对象“丢”进去,所以可能引发异常。
== 由于把对象“丢进”集合时,集合丢失了对象的状态信息,集合只之道它盛装的是Object,因此取出集合元素后还
需要进行强制类型转换。这种强制类型转换既会增加编程的复杂度,也可能引发ClassException.
编译时不检查类型的异常
看下面的程序:
- public class ListErr {
- public static void main(String[] args) {
- //创建一个只想保存字符串的List集合
- List strList = new ArrayList();
- strList.add("我爱Java");
- strList.add("我爱Android");
- //“一不小心”把一个Integer对象“丢进”了集合
- strList.add(5);
- for(int i = 0;i<strList.size();i++){
- //因为List里取出的全部是Object,所以必须强制类型转换
- //最后一个元素将出现ClassException异常
- String str = (String)strList.get(i);
- System.out.println(str);
- }
- }
- }
手动实现编译时检查类型
如果希望创建一个List对象,且该List对象中只能保存字符串类型,那我们可以扩展ArrayList,下面程序创建了一个StrList集合类,该集合只能存放String对象。看下面的程序:
- /**
- * 自定义一个StrList集合类,使用组合的方式来复用ArrayList
- * @author Administrator
- *
- */
- public class StrList {
- private List strList = new ArrayList();
- //定义StrList的add方法
- public boolean add(String ele){
- return strList.add(ele);
- }
- //重写get方法,将get方法的返回值类型改为String类型
- public String get(int index){
- return (String)strList.get(index);
- }
- public int size(){
- return strList.size();
- }
- }
- public class CheckType {
- public static void main(String[] args) {
- //创建一个只想保存字符串的List集合
- StrList strList = new StrList();
- strList.add("我爱Java");
- strList.add("我爱Android");
- //下面语句不能把Integer对象“丢进”集合中,将引起编译错误
- // strList.add(6);
- System.out.println(strList);
- for(int i = 0;i<strList.size();i++){
- //因为StrList里元素的类型就是String类型,所以无需强制性转换
- String str = strList.get(i);
- }
- }
- }
使用泛型
对于上面的程序可以这样进行改进:
- public class GenericList {
- public static void main(String[] args) {
- //创建一个只想保存字符串的List集合
- List<String> strList = new ArrayList<String>();
- strList.add("我爱Java");
- strList.add("我爱Android");
- //下面代码将引起编译错误
- // strList.add(6);
- for(int i = 0;i<strList.size();i++){
- //下面无需强制性转换
- String str = strList.get(i);
- }
- }
- }
这种特殊集合的方法是:在集合接口、类后增加尖括号,尖括号里放一个数据类型,即表明这个集合接口、集合类只能
保存特定类型的对象。我们说List是带一个类型参数的泛型接口,在本例中,类型参数是String。在创建这个ArrayList
对象的时候也指定了一个类型参数。