Java泛型和类型安全的容器

示例:

1 public class Apple {
2     private static long counter;
3     private final long id = counter++;
4     
5     public long id(){
6         return id;
7     }
8 }
1 public class Orange {
2 
3 }
 1 public class ApplesAndOrangesWithoutGenerics {
 2     @SuppressWarnings({ "rawtypes", "unchecked" })
 3     public static void main(String[] args) {
 4         //定义一个ArrayList容器, 不指定其类型
 5         ArrayList apples = new ArrayList();
 6         for (int i = 0; i < 3; i++) {
 7             apples.add(new Apple());
 8         }
 9         
10         apples.add(new Orange());
11         
12         //此时, apples容器中存在4个对象, 其中前三个为Apple类型, 最后一个为Orange类型
13         for (int i = 0; i < apples.size(); i++) {
14             //get()方法取值时, 得到的只是Object的引用, 必须将其强制转型为Apple, 否则编译错误
15             //当试图将Orange对象转型为Apple时, 发生类型转换异常
16             System.out.println(((Apple)apples.get(i)).id());
17             /*
18              * output:
19              * 0
20              * 1
21              * 2
22              * */
23         }
24     }
25 }

    在本例中,因为ArrayList保存的是Object,所以可以将Apple对象和Orange对象放进容器中,当在使用ArrayList的get()方法来取出Apple对象时,得到的只是Object的引用,必须将其转型为Apple,因此,需在调用Apple的id()方法之前,强制进行转型,否则,

就会得到编译错误。

 

    刚才声明容器时没有预先定义类型,默认为Object,现在使用预定义泛型来看看:

 1 public class ApplesAndOrangesWithoutGenerics2 {
 2     public static void main(String[] args) {
 3         //定义一个保存Apple对象的ArrayList, 尖括号括起来的是类型参数
 4         //它指定了这个容器示例可以保存的类型, 通过使用泛型, 就可以在编译器放置将错误类型的对象放置到容器中
 5         ArrayList<Apple> apples = new ArrayList<Apple>();
 6         for (int i = 0; i < 3; i++) {
 7             apples.add(new Apple());
 8         }
 9         
10         //apples.add(new Orange());  编译器可以阻止将Orange放置到apples中
11         
12         for (int i = 0; i < apples.size(); i++) {
13             System.out.println(apples.get(i).id());
14         }
15         
16         for (Apple c : apples) {
17             System.out.println(c.id());
18         }
19         
20         /*output
21          * 0
22          * 1
23          * 2
24          * 0
25          * 1
26          * 2
27          * */
28     }
29 }

    我们注意到,定义了容器类型后,编译器可以阻止将Orange放置到apples中,因为此时Orange对象的类型与容器类型不匹配,发生编译错误;另外,将元素从容器中取出时,类型转换也不再时必须的了,因为容器知道自己保存的是什么类型,因此会在调用

get()时帮忙转型。

posted @ 2018-01-22 22:59  dukeshi  阅读(1178)  评论(0编辑  收藏  举报