`
stinge
  • 浏览: 153667 次
  • 性别: 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泛型的用法及T.class的获取过程解析

    Java泛型的用法及T.class的获取过程解析 Java泛型是Java编程语言中的一种重要特性,它允许开发者在编写代码时指定类型参数,从而提高代码的灵活性和可读性。本文将详细介绍Java泛型的用法 及T.class的获取过程解析...

    Java泛型三篇文章,让你彻底理解泛型(super ,extend等区别)

    Java 泛型详解 Java 泛型是 Java SE 5.0 中引入的一项特征,它允许程序员在编译时检查类型安全,从而减少了 runtime 错误的可能性。泛型的主要优点是可以Reusable Code,让程序员编写更加灵活和可维护的代码。 ...

    Java泛型应用实例

    Java泛型是Java编程语言中的一个强大特性,它允许我们在定义类、接口和方法时指定类型参数,从而实现代码的重用和类型安全。在Java泛型应用实例中,我们可以看到泛型如何帮助我们提高代码的灵活性和效率,减少运行时...

    很好的Java泛型的总结

    Java泛型机制详解 Java泛型是Java语言中的一种机制,用于在编译期检查类型安全。Java泛型的出现解决了Java早期版本中类型安全检查的缺陷。Java泛型的好处是可以在编译期检查类型安全,避免了运行时的...

    java 泛型类的类型识别示例

    综上所述,虽然Java泛型在编译后会进行类型擦除,但通过上述技巧,我们仍然能够在运行时获得关于泛型类实例化类型的一些信息。在实际开发中,这些方法可以帮助我们编写更加灵活和安全的代码。在示例文件`GenericRTTI...

    java泛型技术之发展

    Java泛型是Java编程语言中的一个关键特性,它在2004年随着Java SE 5.0的发布而引入,极大地增强了代码的类型安全性和重用性。本篇文章将深入探讨Java泛型的发展历程、核心概念以及其在实际开发中的应用。 1. **发展...

    SUN公司Java泛型编程文档

    Java泛型是Java编程语言中的一个关键特性,它在2004年随着JDK 5.0的发布被引入。这个特性极大地提高了代码的类型安全性和可读性,减少了在运行时出现ClassCastException的可能性。SUN公司的Java泛型编程文档,包括...

    java 泛型接口示例

    下面我们将详细探讨Java泛型接口的相关知识点。 1. **泛型接口的定义** 泛型接口的定义方式与普通接口类似,只是在接口名之后添加了尖括号`&lt;T&gt;`,其中`T`是一个类型参数,代表某种未知的数据类型。例如: ```java...

    java 泛型方法使用示例

    下面我们将深入探讨Java泛型方法的概念、语法以及使用示例。 **一、泛型方法概念** 泛型方法是一种具有类型参数的方法,这些类型参数可以在方法声明时指定,并在方法体内部使用。与类的泛型类似,它们提供了编译时...

    Java 泛型擦除后的三种补救方法

    Java 泛型是一种强大的工具,它允许我们在编程时指定变量的类型,提供了编译时的类型安全。然而,Java 的泛型在运行时是被擦除的,这意味着在运行时刻,所有的泛型类型信息都会丢失,无法直接用来创建对象或进行类型...

    java泛型的内部原理及更深应用

    Java泛型是Java编程语言中的一个强大特性,它允许在定义类、接口和方法时使用类型参数,从而实现参数化类型。这使得代码更加安全、可读性更强,并且能够减少类型转换的必要。在“java泛型的内部原理及更深应用”这个...

    JAVA泛型加减乘除

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

    java泛型学习ppt

    "Java 泛型学习" Java 泛型是 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的...

    Java泛型使用详细分析.pdf

    Java 泛型使用详细分析 Java 泛型是 Java 语言中的一种类型系统特性,允许开发者在编译期检查类型安全,以避免在运行时出现类型相关的错误。在本文中,我们将详细介绍 Java 泛型的使用方法和实现原理。 一、泛型的...

    Java泛型技术之发展.pdf

    Java泛型是Java编程语言中的一个关键特性,它在2004年随着Java SE 5.0的发布而引入,极大地增强了代码的类型安全性和重用性。本篇文章将深入探讨Java泛型的发展历程、核心概念以及其在实际开发中的应用。 1. **发展...

    Java泛型类型擦除后的补偿

    本文将深入探讨Java泛型类型擦除的概念,并介绍在类型擦除后,为了保持泛型的安全性和便利性,Java设计者所采取的一些补偿机制。 1. **类型擦除**: - 在编译期间,所有的泛型类型信息都会被替换为它们的实际类型...

Global site tag (gtag.js) - Google Analytics