知识大全 J2SE5.0新特性示例---泛型

Posted 类型

篇首语:守望相助,一缕阳光也将照亮心扉;同心协力,一点火光也能温暖灵魂。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 J2SE5.0新特性示例---泛型相关的知识,希望对你有一定的参考价值。

J2SE5.0新特性示例---泛型  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  简介

  泛型其实并不是一种新的语言元素 C++中早就就有 但是在C++之后的java却没有吸收这个特性 现在Java也有了泛型的特性 大概也和 Net的竞争有关系吧

  首先看泛型的一个应用

  在过去 我们可能经常要写一些类似这样的代码

  

  List stringList=new LinkedList();stringList add( firstString );stringList add( secondString );String str=(String)erator() next();

  实际上第三行对String的类型转换意义并不大 因为通常我们如果在操作一个List 都是知道这个List里面放的是什么类型对象的 但是我们如果不这样写又通不过语法检查

  利用java的泛型机制 我们可以这么写

  

  List<String> stringList=new LinkedList<String>();stringList add( firstString );stringList add( secondString );String str=erator() next();

  这样做的好处是在定义容器的时候就指明了容器中的类型 一方面我们不再需要取一个元素时候做强制类型转换 另外一方面如果在这个容器中放入的对象类型不符合要求 那么会在编译时候产生一个错误 而不是在运行时候才抛出一个异常

  另外这样也提高了程序的可读性

  泛型类型的定义

  下面是一个简单的使用泛型类的定义

  

  public class MyGenericClass<T>     private T value;

  public T getValue()        return value;   

  public void setValue(T value)        this value = value;   

  值得注意的一点是 静态变量不能够使用泛型定义 也就是说类似下面的语句是非法的

   public class MyGenericClass<T>     public static T value;//错误的定义

  此外 泛型的定义不会被继承 举个例子来说 如果A是B的子类 而C是一个声明了泛型定义的类型的话 C<A>不是C<B>的子类 为了更好的说明 可以看下面的代码 这段代码是错误的

   List<String> strList =new ArrayList<String>();List<Object> objList=strList;  //错误的赋值

  不过这样一段代码是正确的

   List<Object> strList =new ArrayList<Object>();strList add( a string );

  统配类型

  假设我们需要这样一个函数 使用它可以把一个集合中所有的元素打印出来 在以前我们可能这样定义

   void printCollection(Collection c)     Iterator i = erator();    for (k = ; k < c size(); k++)           System out println(i next());   

  使用新的泛型特性我们可以这样写

   void printCollection(Collection<Object> c)    for (Object e : c)           System out println(e);   

  但是这样有一个问题 假如我们现在有个对象类型是Collection<String> 那么我们不能够将它作为参数传给printCollection 因为Collection<String>并不是Collection<Object>的子类

  为了解决这个问题 我们可以使用统配类型? 也就是定义成下面这个样子

   void printCollection(Collection<?> c)    for (Object e : c)           System out println(e);   

  可以说Collection<?>是所有Collection的父类

  再来看一段下面的代码

   private void clearAllMaps(Collection<Map> c)       for(Map m:c)                  m clear();      

  毫无疑问 它也存在上面我们所说的问题 也就是对HashMap之类Map的子类无法进行操作 但是如果我们将参数改成Collection<?>又不大合理 因为我们只希望对父类为Map的子类进行操作 那么我们可以这样改写

   private void clearAllMaps(Collection<? extends Map> c)    for(Map m:c)           m clear();   

  类似于? extends Map之类的统配符称为限定统配类型

  假设一个对象h类型为Collection<HashMap> 那么我们将h作为参数传给clearAllMaps 如下面一段代码所示

   List<HashMap<String String>> h=new ArrayList<HashMap<String String>>();HashMap<String String> m=new HashMap<String String>();m put( key value );h add(m);clearAllMaps(h);

  对于在类似于上面所说 使用了? extend XXX的方法 值得注意的一点是不能够在方法体内用XXX的子类对象作为代替 如下面一段代码是错误的

   public void addRectangle(List<? extends Shape> shapes)    shapes add( new Rectangle()); // 错误用法!

  这里我们假设Rectangle是Shape的一个子类

  不允许这样写的原因比较简单 因为调用该方法时候参数类型可能是Shape的另外一个子类 假如说Shape除了Rectangle这个子类以外还有另外一个子类Circle 那么我们可以把一个List<Circle>类型的对象作为参数传给这个方法(注意这样是合法的) 而在方法体内却把一个Rectangle对象放到了shapes里面 这显然是不合理的

  除了extends 在泛型参数类型中还可以使用super关键字 参照下面一段程序

private void addString(Collection <? super String> c)       c add( a String );

  泛型函数

  我们在前面提到了统配类型 现在让我们来设想一个函数 它实现这样的功能 将一个数组中的元素添加到一个Collection中 为了保证程序的通用性 我们可能会写出另外一段错误的代码

   private void fromArrayToCollection(Object[] a Collection<?> c)    for (Object o : a)           c add(o); // 错误的代码   

  那么这个函数应该怎么写呢?我们可以通过对函数添加泛型参数的方法实现 如下面所示

   private <T> void  exfromArrayToCollection(T[] a   Collection<T> c)       for (T o : a)                  c add(o); //这样是正确的      

  那么 在什么时候我们应该使用统配类型 什么时候我们应该使用泛型函数呢?答案是取决于函数参数之间 函数参数和返回值之间的类型依赖性

  如果一个函数的参数类型与函数返回的参数没有必然关联 同时对于该函数其他的参数的类型也没有依赖关系 那么我们就应该使用统配符 否则就应该使用泛型函数

  为了更清楚地说明这一点 我们可以看一下java util包中Collections类型几个方法的定义

   class Collections     static void swap(List<?> list int i int j)     static <T> void  copy                                 (List<? super T> dest List<? extends T> src)   

  其中swap函数实际上也可以这样定义

   static <T>void swap(List<T> list int i int j)

  但是注意到这里泛型类型参数T只在参数中用到了一次 也就是说它和函数其他部分没有依赖性 这可以看作是我们应该使用?的一个标志

cha138/Article/program/Java/Javascript/201311/25360

相关参考

知识大全 在Eclipse 3.1体验J2SE 5.0新特性六

在Eclipse3.1体验J2SE5.0新特性六  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 在Eclipse 3.1体验J2SE 5.0新特性四(图)

在Eclipse3.1体验J2SE5.0新特性四(图)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧

知识大全 在Eclipse 3.1体验J2SE 5.0新特性二(图)

在Eclipse3.1体验J2SE5.0新特性二(图)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧

知识大全 在Eclipse 3.1体验J2SE 5.0新特性七(图)

在Eclipse3.1体验J2SE5.0新特性七(图)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧

知识大全 在Eclipse 3.1体验J2SE 5.0新特性八(图)

在Eclipse3.1体验J2SE5.0新特性八(图)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧

知识大全 J2SE(TM) 5.0 语言特性

J2SE(TM)5.0语言特性  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  [C风格格式化输出

知识大全 JDK 5.0中的泛型类型学习

JDK5.0中的泛型类型学习  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  JDK中增加的泛型类

知识大全 MySQL 5.0 新特性教程 存储过程:第二讲

MySQL5.0新特性教程存储过程:第二讲  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Why

知识大全 MySQL 5.0新特性教程 存储过程:第一讲

MySQL5.0新特性教程存储过程:第一讲  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Int

知识大全 MySQL 5.0 数据库新特性的存储过程

MySQL5.0数据库新特性的存储过程  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  当你提交一