`
stinge
  • 浏览: 149777 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java泛型

    博客分类:
  • java
 
阅读更多

泛型 Generic type 或者 generics )是对  Java   语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。

可以在集合框架( Collection framework )中看到 泛型 的动机。例如, Map 类允许您向一个 Map 添加任意类的对象,即使最常见的情况是在给定映射( map )中保存某个特定类型(比如 String )的对象。

因为 Map.get() 被定义为返回 Object ,所以一般必须将 Map.get() 的结果强制类型转换为期望的类型,如下面的代码所示:

Map m = new HashMap();
m.put("key", "blarg");
String s = (String) m.get("key");
 

 

要让程序通过编译,必须将 get() 的结果强制类型转换为 String ,并且希望结果真的是一个 String 。但是有可能某人已经在该映射中保存了不是 String 的东西,这样的话,上面的代码将会抛出 ClassCastException

理想情况下,您可能会得出这样一个观点,即 m 是一个 Map ,它将 String 键映射到 String 值。这可以让您消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型的键或值保存在集合中。这就是 泛型 所做的工作。

  泛型 的好处

Java   语言中引入 泛型 是一个较大的功能增强。不仅语言、类型系统和编译器有了较大的变化,以支持 泛型 ,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为 泛型 化的了。这带来了很多好处:

类型安全。   泛型 的主要目标是提高   Java   程序的类型安全。通过知道使用 泛型 定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有 泛型 ,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。

Java   程序中的一种流行技术是定义这样的集合,即它的元素或键是公共类型的,比如 “String 列表 或者 “String String 的映射 。通过在变量声明中捕获这一附加的类型信息, 泛型 允许编译器实施这些附加的类型约束。类型错误现在就可以在编译时被捕获了,而不是在运行时当作 ClassCastException 展示出来。将类型检查从运行时挪到编译时有助于您更容易找到错误,并可提高程序的可靠性。

消除强制类型转换。   泛型 的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。

尽管减少强制类型转换可以降低使用 泛型 类的代码的罗嗦程度,但是声明 泛型 变量会带来相应的罗嗦。比较下面两个代码例子。

该代码不使用 泛型

List li = new ArrayList();
li.put(new Integer(3));
Integer i = (Integer) li.get(0);
 

 

 

该代码使用 泛型

List<Integer> li = new ArrayList<Integer>();
li.put(new Integer(3));
Integer i = li.get(0);

 

在简单的程序中使用一次 泛型 变量不会降低罗嗦程度。但是对于多次使用 泛型 变量的大型程序来说,则可以累积起来降低罗嗦程度。

潜在的性能收益。   泛型 为较大的优化带来可能。在 泛型 的初始实现中,编译器将强制类型转换(没有 泛型 的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来可能。

由于 泛型 的实现方式,支持 泛型 (几乎)不需要 JVM 或类文件更改。所有工作都在编译器中完成,编译器生成类似于没有 泛型 (和强制类型转换)时所写的代码,只是更能确保类型安全而已。


泛型 用法的例子

泛型 的许多最佳例子都来自集合框架,因为 泛型 让您在保存在集合中的元素上指定类型约束。考虑这个使用 Map 类的例子,其中涉及一定程度的优化,即 Map.get() 返回的结果将确实是一个 String

Map m = new HashMap();
m.put("key", "blarg");
String s = (String) m.get("key");
 

如果有人已经在映射中放置了不是 String 的其他东西,上面的代码将会抛出 ClassCastException 泛型 允许您表达这样的类型约束,即 m 是一个将 String 键映射到 String 值的 Map 。这可以消除代码中的强制类型转换,同时获得一个附加的类型检查层,这个检查层可以防止有人将错误类型的键或值保存在集合中。

下面的代码示例展示了 JDK 5.0 中集合框架中的 Map 接口的定义的一部分:

public interface Map<K, V> {
public void put(K key, V value);
public V get(K key);
}

 

注意该接口的两个附加物:

类型参数 K V 在类级别的规格说明,表示在声明一个 Map 类型的变量时指定的类型的占位符。

get() put() 和其他方法的方法签名中使用的 K V

为了赢得使用 泛型 的好处,必须在定义或实例化 Map 类型的变量时为 K V 提供具体的值。以一种相对直观的方式做这件事:

Map<String, String> m = new HashMap<String, String>();
m.put("key", "blarg");
String s = m.get("key");
 

 

当使用 Map 泛型 化版本时,您不再需要将 Map.get() 的结果强制类型转换为 String ,因为编译器知道 get() 将返回一个 String

在使用 泛型 的版本中并没有减少键盘录入;实际上,比使用强制类型转换的版本需要做更多键入。使用 泛型 只是带来了附加的类型安全。因为编译器知道关于您将放进 Map 中的键和值的类型的更多信息,所以类型检查从执行时挪到了编译时,这会提高可靠性并加快开发速度。


向后兼容

  Java   语言中引入 泛型 的一个重要目标就是维护向后兼容。尽管 JDK 5.0 的标准类库中的许多类,比如集合框架,都已经 泛型 化了,但是使用集合类(比如 HashMap ArrayList )的现有代码将继续不加修改地在 JDK 5.0 中工作。当然,没有利用 泛型 的现有代码将不会赢得 泛型 的类型安全好处。

 


  泛型 基础

类型参数

在定义 泛型 类或声明 泛型 类的变量时,使用尖括号来指定形式类型参数。形式类型参数与实际类型参数之间的关系类似于形式方法参数与实际方法参数之间的关系,只是类型参数表示类型,而不是表示值。

泛型 类中的类型参数几乎可以用于任何可以使用类名的地方。例如,下面是   java .util.Map 接口的定义的摘录:

public interface Map<K, V> {
public void put(K key, V value);
public V get(K key);
}
 

 

Map 接口是由两个类型参数化的,这两个类型是键类型 K 和值类型 V 。(不使用 泛型 )将会接受或返回 Object 的方法现在在它们的方法签名中使用 K V ,指示附加的类型约束位于 Map 的规格说明之下。

当声明或者实例化一个 泛型 的对象时,必须指定类型参数的值:

Map<String, String> map = new HashMap<String, String>();
 

 

注意,在本例中,必须指定两次类型参数。一次是在声明变量 map 的类型时,另一次是在选择 HashMap 类的参数化以便可以实例化正确类型的一个实例时。

编译器在遇到一个 Map<String, String> 类型的变量时,知道 K V 现在被绑定为 String ,因此它知道在这样的变量上调用 Map.get() 将会得到 String 类型。

除了异常类型、枚举或匿名内部类以外,任何类都可以具有类型参数。


命名类型参数

推荐的命名约定是使用大写的单个字母名称作为类型参数。这与 C++ 约定有所不同(参阅 附录 A :与 C++ 模板的比较),并反映了大多数 泛型 类将具有少量类型参数的假定。对于常见的 泛型 模式,推荐的名称是:

K —— 键,比如映射的键。  
V ——
值,比如 List Set 的内容,或者 Map 中的值。  
E ——
异常类。  
T —— 
泛型


泛型 不是协变的

关于 泛型 的混淆,一个常见的来源就是假设它们像数组一样是协变的。其实它们不是协变的。 List<Object> 不是 List<String> 的父类型。

如果 A 扩展 B ,那么 A 的数组也是 B 的数组,并且完全可以在需要 B[] 的地方使用 A[]

Integer[] intArray = new Integer[10]; 
Number[] numberArray = intArray;
 

 

上面的代码是有效的,因为一个 Integer 一个 Number ,因而一个 In

 

分享到:
评论

相关推荐

    Java泛型编程指南.pdf

    Java泛型编程指南.pdf 此文章译自SUN的泛型编程指南

    Java泛型和集合

    Java Generics and Collections 英文版,详细描述java 泛型技术

    java 泛型类的类型识别示例

    java 泛型类的类型识别示例 java 泛型类的类型识别示例 java 泛型类的类型识别示例

    java 泛型接口示例

    java 泛型接口示例 java 泛型接口示例 java 泛型接口示例

    java 泛型方法使用示例

    java 泛型方法使用示例 java 泛型方法使用示例 java 泛型方法使用示例

    Java泛型的用法及T.class的获取过程解析

    主要介绍了Java泛型的用法及T.class的获取过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    JAVA泛型加减乘除

    这是一个使用JAVA实现的泛型编程,分为两部分,第一部分创建泛型类,并实例化泛型对象,得出相加结果。 第二部分用户自行输入0--4,选择要进行的加减乘除运算或退出,再输入要进行运算的两个数,并返回运算结果及...

    java泛型技术之发展

    java泛型技术之发展,学习JAVA 泛型的不错东东

    1.java泛型定义.zip

    1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1....

    很好的Java泛型的总结

    很好的Java泛型的总结,看完之后你一定会知道java泛型的底层机制,你一定会学会Java泛型!

    4.java泛型的限制.zip

    4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip...

    java泛型学习ppt

    java,学习java泛型,java培训之泛型.pptxjava培训之泛型.pptxjava培训之泛型.pptxjava培训之泛型.pptx

    java泛型总结

    深入理解java泛型,包括类名泛型的定义,方法泛型定义,泛型的返回

    SUN公司Java泛型编程文档

    Sun公司的Java泛型编程文档,英文原版和网络翻译版,想对泛型有更清楚的认识的朋友可以看看,必定会有所帮助

    java泛型详解.pdf

    java泛型详解.pdf

    JAVA泛型简单排序实例

    JAVA泛型源代码实现以下功能:返回数组元素的最大值/最小值下标;判断数组元素是否按升序排列;T对象数组排序;二分法查找key元素;

    思维导图之Java泛型详解

    思维导图之Java泛型详解

    Java泛型技术之发展

    Java泛型技术之发展

    JAVA泛型教程(帮你解决学习泛型的苦恼)

    JAVA泛型教程(帮你解决学习泛型的苦恼). Java 泛型编程可能会碰到很多问题,本教程可能会对你有帮助哦。

Global site tag (gtag.js) - Google Analytics