e代剑客——温柔一刀

生活就像海洋,只有意志坚强的人,才能到达彼岸

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  76 随笔 :: 7 文章 :: 215 评论 :: 0 Trackbacks
1.一个简单的范型示例

在以前,你可能遇到过这样的代码:

1List list = new LinkedList(); 
2
3list.add("a"); 
4
5list.add("b"); 
6
7list.add("c"); 
8
9String name = (String)list.iterator.next(); 

注意,第三行需要强制转换。而使用范型:
 1
 2List<String> list = new LinkedList<String>(); 
 3
 4list.add("a"
 5
 6list.add("b"); 
 7
 8list.add("c"); 
 9
10String name = list.iterator.next(); 
11
12

这里将list声明成String类型的List。List是有一个类型参数的范型接口。这个例子中类型参数是String。

 
2.定义简单的范型

看j2se5.0中List和Iterator接口的实现(片断):
 1
 2public interface List<E>  
 3
 4{  
 5
 6void add(E x); 
 7
 8Iterator<E> iterator(); 
 9
10}
 
11
12public interface Iterator<E>  
13
14{  
15
16E next(); 
17
18boolean hasNext(); 
19
20}
  
21
22

上面的代码我们比较熟悉,但是其中增加了尖括号。尖括号中的内容定义了接口List和Iterator的形式类型参数。类型参数可以用在范型声明中,如类和接口的声明。

一旦声明了范型,你就可以使用它。在上面的例子中使用了List<String>。这里使用String是实参,代替了形参E。如果使用List<Integer>,则用实参Integer代替了形参E。

不管List<Integer>还是List<String>,它们的类只有一个。考虑下面的代码:
1
2List<String> list1 = new LinkedList<String>(); 
3
4List<Integer> list2 = new LinkedList<Integer>(); 
5
6System.out.println(list1.getClass()==list2.getClass()); 
7
 

输出结果为true。

 

一般来说,形式类型参数都是大写,尽量使用单个字母,许多容器类都使用E作为参数。

 

3.范型和继承

考虑下面的代码,你认为它会出错吗?

1
2String s =" xxx@gmail.com"
3
4Object o = s: 
5

当然,String类继承Object类,这样做不会出错。但下面的代码呢?

1List<String> s = new LinkedList<String>(); 
2
3List<Object>o=s; 
4


编译出错!

是的,List<Object>和List<String>没有继承关系。

 

4.通配符

考虑下面一个方法:

 1
 2public void printCollection(Collection<Object> c) 
 3
 4
 5
 6   for(Object o:c) 
 7
 8
 9
10   System.out.printf("%s%n",o); 
11
12}
 
13
14}
 
15


事实上,上面这个方法并不通用,它只能打印Collection<Object>类型的集合,象其他的如Collection<String>、Collection<Integer>并不能被打印,因为对象类型不一致。

为了解决这个问题,可以使用通配符:
 1
 2public void printCollection(Collection<> c) 
 3
 4
 5
 6   for(Object o:c) 
 7
 8
 9
10   System.out.printf("%s%n",o); 
11
12}
 
13
14}
 
15
16

Collection<?>被称作未知类型的集合。问号代表各种类型。

上面的读取集合中的数据时,我们采用Object类型。这样做时可以的,因为不管未知类型最终代表何种类型,它的数据都继承Object类,那么再考虑一下下面的代码:
1
2Collection<?> c = new ArrayList<String>(); 
3
4c.add(new Object());   
5
6

这样做时错误的,因为我们不知道?代表何种类型,所以我们不能直接将Object增加到集合中,这会出现类型不匹配的情况。
 

5.有限制的通配符

考虑下面的代码
 1
 2class Man 
 3
 4
 5
 6   public String name =""
 7
 8}
 
 9
10class GoodMan extends Man 
11
12
13
14   public String name = ""
15
16}
 
17
18class BadMan extends Man 
19
20
21
22   public String name = ""
23
24}
 
25
26

考虑下面的范型方法:
 1
 2public void printName(List<Man> men) 
 3
 4
 5
 6   for(Man man:men) 
 7
 8   
 9
10      System.out.println("姓名:"+ man.name); 
11
12   }
 
13
14}
 
15
16


这个范型方法只能显示List<Man>类型的数据,下面的代码允许显示Man和它的子类。
 1
 2public void printName(List<? extends  Man> men) 
 3
 4
 5
 6   for(Man man:men) 
 7
 8   
 9
10      System.out.println("姓名:" + man.name); 
11
12   }
 
13
14}
 
15
16

这里使用? extends Man代替Man,表明接受任何Man的子类做为参数。

和前面的代码类似,下面的代码也是不正确的:
 1
 2public void adman(List<? extends Man> men) 
 3
 4
 5
 6   GoodMan good = new GoodMan(); 
 7
 8   good.name = "zhupan"
 9
10   men.add(good); 
11
12}
 
13
14

原因也很简单,因为?代表一切继承Man的类,你并不能保证就一定时GoodMan类。

 

和这种用法类似:
 1
 2public void adman(List<? super GoodMan> men) 
 3
 4
 5
 6   GoodMan good = new GoodMan(); 
 7
 8   good.name = "zhupan"
 9
10   men.add(good); 
11
12}
 
13

6.范型方法

考虑下面的代码,我们将一个数组的内容加到一个集合中
 1
 2public  void copyArrayToCollection(Man[] men, Collection<?>c) 
 3
 4
 5
 6for(Man man:men) 
 7
 8
 9
10   c.add(man); 
11
12}
 
13
14}
 
15
16

这段代码时错的!

因为我们并不知道集合C的类型,所以不能将Man类型的数据加到集合中。

可以使用范型方法解决:
 1
 2public <T> void copyArrayToCollection(T[] men, Collection<T>c) 
 3
 4
 5
 6for(T man:men) 
 7
 8
 9
10   c.add(man); 
11
12}
 
13
14}
 
15

这里T时一个形式类型参数。

何时该采用通用方法?何时该采用通配符?

考虑下面的例子:
 1
 2interface  Collection<E> 
 3
 4
 5
 6  public boolean containsAll(Collection<?> c); 
 7
 8public boolean addAll(Collection<? extends E> c); 
 9
10}
 
11
12

改写成通用方法
 1
 2interface  Collection<E> 
 3
 4
 5
 6   public <T> boolean containsAll(Collection<T> c); 
 7
 8public <extends E> boolean addAll(Collection<T> c); 
 9
10}
 
11
12

然而,在这里每个方法T只使用了一次,返回值不依赖形式参数,其他参数也不依赖形式参数。这说明实参被用作多态,这种情况下就应该用通配符。
posted on 2006-08-14 10:16 温柔一刀 阅读(635) 评论(1)  编辑  收藏 所属分类: java相关

评论

# re: java 范型编程 2006-08-14 10:31 testtesttest
test  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航:
 
联系偶 zhupanjava@gmail.com 温柔一刀