什么是范型算法?

什么是范型算法?

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

1.一个简单的范型示例

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

List list = new LinkedList();

list.add(“麻省理工”);

list.add(“普林斯顿”);

list.add(“伯克利”);

java/lang/String.java.html" target="_blank">String name = (java/lang/String.java.html" target="_blank">String)list.iterator.next();

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

List<java/lang/String.java.html" target="_blank">String> list = new LinkedList<java/lang/String.java.html" target="_blank">String>();

list.add(“麻省理工”);

list.add(“普林斯顿”);

list.add(“伯克利”);

java/lang/String.java.html" target="_blank">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<java/lang/String.java.html" target="_blank">String> list1 = new LinkedList<java/lang/String.java.html" target="_blank">String>();

List<java/lang/Integer.java.html" target="_blank">Integer> list2 = new LinkedList<java/lang/Integer.java.html" target="_blank">Integer>();

java/lang/System.java.html" target="_blank">System.out.println(list1.getClass()==list2.getClass());

输出结果为true。

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

3.范型和继承

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

java/lang/String.java.html" target="_blank">String s = “smallnest@163.com”;

java/lang/Object.java.html" target="_blank">Object o = s:

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

List<java/lang/String.java.html" target="_blank">String> s = new LinkedList<java/lang/String.java.html" target="_blank">String>();

List<java/lang/Object.java.html" target="_blank">Object>o=s;

编译出错!

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

4.通配符

考虑下面一个方法:

public void printCollection(Collection<java/lang/Object.java.html" target="_blank">Object> c)

{

for(java/lang/Object.java.html" target="_blank">Object o:c)

{

java/lang/System.java.html" target="_blank">System.out.printf(“%s%n”,o);

}

}

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

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

public void printCollection(Collection<?> c)

{

for(java/lang/Object.java.html" target="_blank">Object o:c)

{

java/lang/System.java.html" target="_blank">System.out.printf(“%s%n”,o);

}

}

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

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

Collection<?> c = new ArrayList<java/lang/String.java.html" target="_blank">String>();

c.add(new java/lang/Object.java.html" target="_blank">Object()); //!!!!

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

5.有限制的通配符

考虑下面的代码

class Man

{

public java/lang/String.java.html" target="_blank">String name = “”;

}

class GoodMan extends Man

{

public java/lang/String.java.html" target="_blank">String name = “”

}

class BadMan extends Man

{

public java/lang/String.java.html" target="_blank">String name = “”

}

考虑下面的范型方法:

public void printName(List<Man> men)

{

for(Man man:men)

{

java/lang/System.java.html" target="_blank">System.out.println(“姓名:” + man.name);

}

}

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

public void printName(List<? extends Man> men)

{

for(Man man:men)

{

java/lang/System.java.html" target="_blank">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只使用了一次,返回值不依赖形式参数,其他参数也不依赖形式参数。这说明实参被用作多态,这种情况下就应该用通配符。
温馨提示:内容为网友见解,仅供参考
第1个回答  推荐于2016-09-11
普遍适用有
普遍适用类型 (int, float, userdefine...)
普遍适用算法 (insert, delete, find, ...)
其实,就是使用模板

比如
int max(int,int);
用模板
template<typename T>
T max(T,T);(什么类型都能比较大小)
就是普遍适用类型的例子

简述泛型集合框架相比于数组有什么好处?
好处有:1、编译时的强类型检查;2、消除显示的类型强制转换;3、更好的代码复用性,比如实现泛型算法。Java,是由Sun公司于1995年推出的编程语言。用Java实现的HotJava浏览器(支持Java applet)显示了Java的魅力:跨平台、动态的Web、Internet计算。从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览...

C++,三个点的参数是什么意思
这个表示这个函数的参数可以为任意的。不管传递什么类型的变量进去都可以。

C++:Cstring 与string类型的区别是什么?
char*为C编程中最常用的字符串指针,一般以’\\0’为结束标志;在MFC、ATL中使用字符串尽量使用CString,毕竟都是微软的孩子,各方面都比其它更有优势,而在非微软平台上或对移植性要求较高的场合推荐使用string,标准模板库提供了那么强大的泛型算法,没必要再自己去造车轮。

c++考试会考什么内容
2:紧接着就是面向对象的特征,继承,封装,多态等概念。3:小程序填空 4:独立写个小程序

数据结构是什么啊
数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排...

C语言和C++有什么区别?
1、C语言:是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。2、C++:是C语言的继承,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计。二、优势不同 1、C语言:能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要...

C++中string 是什么意思
ANSI与unicode均可);char*为C编程中最常用的字符串指针,一般以’\\0’为结束标志;在MFC、ATL中使用字符串尽量使用CString,毕竟都是微软的孩子,各方面都比其它更有优势,而在非微软平台上或对移植性要求较高的场合推荐使用string,标准模板库提供了那么强大的泛型算法,没必要再自己去造车轮。

C++中string 是什么意思
string 是C++中的字符串。字符串对象是一种特殊类型的容器,专门设计来操作的字符序列。C + +字符串对象属于一个类,这个类有很多内置的特点,在操作方式,更直观,另外还有很多有用的成员函数。

相似回答
大家正在搜