分享
 
 
 

J2SE5.0新特性之范型编程

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

本章主要参考sun公司文档。

C++程序员对范型编程肯定不陌生,尤其在STL大行其道的时候,C#2.0也将实现范型编程的功能。Java也不甘示弱,也推出了范型编程的语言新特性。

1.一个简单的范型示例

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

List list = new LinkedList(); list.add(“麻省理工”); list.add(“普林斯顿”); list.add(“伯克利”); String name = (String)list.iterator.next();

注意,第三行需要强制转换。而使用范型:

List<String> list = new LinkedList<String>(); list.add(“麻省理工”); list.add(“普林斯顿”); list.add(“伯克利”); String name = list.iterator.next();

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

2.定义简单的范型

看j2se5.0中List和Iterator接口的实现(片断):

public interface List<E> { void add(E x); Iterator<E> iterator(); } public interface Iterator<E> { E next(); boolean hasNext(); }

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

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

不管List<Integer>还是List<String>,它们的类只有一个。考虑下面的代码:

List<String> list1 = new LinkedList<String>(); List<Integer> list2 = new LinkedList<Integer>(); System.out.println(list1.getClass()==list2.getClass());

输出结果为true。

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

3.范型和继承

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

String s = “smallnest@163.com”; Object o = s:

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

List<String> s = new LinkedList<String>(); List<Object>o=s;

编译出错!

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

4.通配符

考虑下面一个方法:

public void printCollection(Collection<Object> c) { for(Object o:c) { System.out.printf(“%s%n”,o); } }

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

为了解决这个问题,可以使用通配符:

public void printCollection(Collection<?> c) { for(Object o:c) { System.out.printf(“%s%n”,o); } }

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

上面的读取集合中的数据时,我们采用Object类型。这样做时可以的,因为不管未知类型最终代表何种类型,它的数据都继承Object类,那么再考虑一下下面的代码:

Collection<?> c = new ArrayList<String>(); c.add(new Object()); //!!!!

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

5.有限制的通配符

考虑下面的代码

class Man { public String name = “”; } class GoodMan extends Man { public String name = “” } class BadMan extends Man { public String name = “” }

考虑下面的范型方法:

public void printName(List<Man> men) { for(Man man:men) { System.out.println(“姓名:” + man.name); } }

这个范型方法只能显示List<Man>类型的数据,下面的代码允许显示Man和它的子类。

public void printName(List<? extends Man> men) { for(Man man:men) { System.out.println(“姓名:” + man.name); } }

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

和前面的代码类似,下面的代码也是不正确的:

public void adman(List<? extends Man> men) { GoodMan good = new GoodMan(); good.name = “晁岳攀”; men.add(good); }

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

和这种用法类似:

public void adman(List<? super GoodMan> men) { GoodMan good = new GoodMan(); good.name = “晁岳攀”; men.add(good); }

6.范型方法

考虑下面的代码,我们将一个数组的内容加到一个集合中

public void copyArrayToCollection(Man[] men, Collection<?>c) { for(Man man:men) { c.add(man); } }

这段代码时错的!

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

可以使用范型方法解决:

public <T> void copyArrayToCollection(T[] men, Collection<T>c) { for(T man:men) { c.add(man); } }

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

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

考虑下面的例子:

interface Collection<E> { public boolean containsAll(Collection<?> c); public boolean addAll(Collection<? extends E> c); }

改写成通用方法

interface Collection<E> { public <T> boolean containsAll(Collection<T> c); public <T extends E> boolean addAll(Collection<T> c); }

然而,在这里每个方法T只使用了一次,返回值不依赖形式参数,其他参数也不依赖形式参数。这说明实参被用作多态,这种情况下就应该用通配符。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有