J2SE5.0新特性之范型编程

晁岳攀 smallnest@163.com

本章主要参考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只使用了一次,返回值不依赖形式参数,其他参数也不依赖形式参数。这说明实参被用作多态,这种情况下就应该用通配符。

转载于:https://www.cnblogs.com/believeit/archive/2004/12/08/2183241.html

J2SE5.0新特性之范型编程相关推荐

  1. Android 7.0新特性——依然范特西

    在2016年8月22日,谷歌正式推送Android 7.0 Nougat正式版.Android的版本推送真是快啊!6.0还没完全推广,7.0已经推送了.作为开发者不努力真的跟不上节奏了.那么,我先细说 ...

  2. 分析 C# 2.0 新特性 -- 范型(Generics)

    分析 C# 2.0 新特性 -- 范型(Generics) 作者:梁振[MS-MVP]   范型是提高面向对象程序多态性设计衍生的. 1,C# 多态性设计回顾和展望 在引入范型这个概念之前,回顾一下1 ...

  3. 【收藏】C# 2.03.0新特性总结

    c#2.0新特性 范型 我们知道通用的数据结构可以采用object存储任何数据类型.使用object问题是: 显示的强制转带来的代码复杂性 换装箱拆箱的性能损失(为什么有性能损失?因为涉及动态内存分配 ...

  4. 微软热门知识点之------c#3.0新特性【转】

    C# 3.0 davies 发表于 2005-9-16 09:53 | 分类: Programming :: 刚DotNet版看到有人贴了C# 3.0 的介绍,大概翻了一下,有不少惊喜,C#中引入了很 ...

  5. 分析 C# 2.0 新特性 -- 空类型(Nullable Types)

    分析 C# 2.0 新特性  -- 空类型(Nullable Types) 在讨论C# 2.0 空类型前,先回顾一下.NET 1.0和.NET 1.1对于类型有下面这样的定义: ".NET  ...

  6. [翻译] C# 8.0 新特性

    原文: Building C# 8.0 [译注:原文主标题如此,但内容大部分为新特性介绍,所以意译标题为 "C# 8.0 新特性"] C# 的下一个主要版本是 8.0.我们已经为它 ...

  7. C#6.0,C#7.0新特性

    C#6.0,C#7.0新特性 C#6.0新特性 Auto-Property enhancements(自动属性增强) Read-only auto-properties (真正的只读属性) Auto- ...

  8. WCF4.0新特性体验(6):路由服务Routing Service(下)

    紧接前文WCF4.0新特性体验(5):路由服务Routing Service(上).今天我们介绍WCF4.0消息路由的实现机制,然后会讲解路由服务的实现过程. [4]WCF与路由服务: 其实在介绍WC ...

  9. 精进不休 .NET 4.0 (4) - C# 4.0 新特性之命名参数和可选参数

    [索引页] [源码下载] 精进不休 .NET 4.0 (4) - C# 4.0 新特性之命名参数和可选参数, 动态绑定(dynamic), 泛型协变和逆变, CountdownEvent, Barri ...

最新文章

  1. android中文首字母排序,Android上汉字按拼音排序如何实现?
  2. 分享Silverlight/WPF/Windows Phone一周学习导读(10月1日-10月15日)
  3. 计算机病毒不可能侵入rom,2008年职称计算机考试计算机基础试题7
  4. html css右下角三角形,html – 框内的CSS中的三角形
  5. 疯狂的程序员-第五章
  6. 软件测试--测试Demo
  7. Thymeleaf引用片段传入参数
  8. 触发ALV事件时报错MOVE_TO_LIT_NOTALLOWED_NODATA
  9. Java基本数据类型及String类
  10. Mysql-Windows下重置密码/修改密码
  11. 阿里云、腾讯云纷纷宕机后,用户只能坐等损失?
  12. 用Windows XP自带的性能监视器测试瑞星2010性能(转)
  13. 【python笔记】可迭代对象和迭代器
  14. verilog之状态机详细解释(一)
  15. 【SDOI 2009】学校食堂 Dining
  16. 昆仑通态触摸屏数据转发上传_说说昆仑通态(MCGS)的数组功能
  17. GCJ-02火星坐标系和WGS-84坐标系转换关系
  18. 火车票软件哪个好用_买火车票的软件哪个最好
  19. 使用bootloader进行远程固件升级(32MCU)
  20. 联想Thinkpad E430 原装win8改版win7的BIOS设置

热门文章

  1. xcode 正确的使用断点
  2. 你用什么软件做笔记?
  3. 2023南华大学计算机考研信息汇总
  4. Charles抓包神器常用功能,常见问题解决
  5. ORA-01810: format code appears twice
  6. Rust:并发编程(concurrent programming)
  7. oralce 经典习题系列-查询
  8. 4.JDK安装与卸载
  9. 找出列表中的偶数位元素
  10. 成功解决:计算交叉熵lossFunction报错“1D target tensor expected, multi-target not supported”的解决办法