`

Java 泛型初步

阅读更多

When you take an element out of a Collection, you must cast it to the type of element that is stored in the collection. Besides being inconvenient, this is unsafe. The compiler does not check that your cast is the same as the collection's type, so the cast can fail at run time.

Generics provides a way for you to communicate the type of a collection to the compiler, so that it can be checked. Once the compiler knows the element type of the collection, the compiler can check that you have used the collection consistently and can insert the correct casts on values being taken out of the collection.

Here is a simple example taken from the existing Collections tutorial:

// Removes 4-letter words from c. Elements must be strings
static void expurgate(Collection c) {
    for (Iterator i = c.iterator(); i.hasNext(); )
      if (((String) i.next()).length() == 4)
        i.remove();
}

Here is the same example modified to use generics:

// Removes the 4-letter words from c
static void expurgate(Collection<String> c) {
    for (Iterator<String> i = c.iterator(); i.hasNext(); )
      if (i.next().length() == 4)
        i.remove();
}

When you see the code <Type>, read it as “of Type”; the declaration above reads as “Collection of String c.” The code using generics is clearer and safer. We have eliminated an unsafe cast and a number of extra parentheses. More importantly, we have moved part of the specification of the method from a comment to its signature, so the compiler can verify at compile time that the type constraints are not violated at run time. Because the program compiles without warnings, we can state with certainty that it will not throw a ClassCastException at run time. The net effect of using generics, especially in large programs, is improved readability and robustness.

To paraphrase Generics Specification Lead Gilad Bracha, when we declare c to be of type Collection<String>, this tells us something about the variable c that holds true wherever and whenever it is used, and the compiler guarantees it (assuming the program compiles without warnings). A cast, on the other hand, tells us something the programmer thinks is true at a single point in the code, and the VM checks whether the programmer is right only at run time.

While the primary use of generics is collections, there are many other uses. “Holder classes,” such as WeakReference and ThreadLocal, have all been generified, that is, they have been retrofitted to make use of generics. More surprisingly, class Class has been generified. Class literals now function as type tokens, providing both run-time and compile-time type information. This enables a style of static factories exemplified by the getAnnotation method in the new AnnotatedElement interface:

    <T extends Annotation> T getAnnotation(Class<T> annotationType); 

This is a generic method. It infers the value of its type parameter T from its argument, and returns an appropriate instance of T, as illustrated by the following snippet:

    Author a = Othello.class.getAnnotation(Author.class);

Prior to generics, you would have had to cast the result to Author. Also you would have had no way to make the compiler check that the actual parameter represented a subclass of Annotation.

Generics are implemented by type erasure: generic type information is present only at compile time, after which it is erased by the compiler. The main advantage of this approach is that it provides total interoperability between generic code and legacy code that uses non-parameterized types (which are technically known as raw types). The main disadvantages are that parameter type information is not available at run time, and that automatically generated casts may fail when interoperating with ill-behaved legacy code. There is, however, a way to achieve guaranteed run-time type safety for generic collections even when interoperating with ill-behaved legacy code.

The java.util.Collections class has been outfitted with wrapper classes that provide guaranteed run-time type safety. They are similar in structure to the synchronized and unmodifiable wrappers. These “checked collection wrappers” are very useful for debugging. Suppose you have a set of strings, s, into which some legacy code is mysteriously inserting an integer. Without the wrapper, you will not find out about the problem until you read the problem element from the set, and an automatically generated cast to String fails. At this point, it is too late to determine the source of the problem. If, however, you replace the declaration:

    Set<String> s = new HashSet<String>();

with this declaration:

    Set<String> s = Collections.checkedSet(new HashSet<String>(), String.class);

the collection will throw a ClassCastException at the point where the legacy code attempts to insert the integer. The resulting stack trace will allow you to diagnose and repair the problem.

You should use generics everywhere you can. The extra effort in generifying code is well worth the gains in clarity and type safety. It is straightforward to use a generic library, but it requires some expertise to write a generic library, or to generify an existing library. There is one caveat: You may not use generics (or any other Tiger features) if you intend to deploy the compiled code on a pre-5.0 virtual machine.

If you are familiar with C++'s template mechanism, you might think that generics are similar, but the similarity is superficial. Generics do not generate a new class for each specialization, nor do they permit “template metaprogramming.”

分享到:
评论

相关推荐

    Java泛型和反射机制

    初步学习Java的泛型和反射机制,通过一些简单的例子来学习泛型,反射

    初步理解Java的泛型特性

    Java的泛型特性是其语言的一个重要组成部分,自Java SE 1.5版本引入以来,极大地增强了代码的类型安全性,同时也提高了代码的可读性和复用性。泛型允许我们在编写代码时,定义一个可以处理多种数据类型的通用结构,...

    Java-Generics-and-Collections-2:Java Generics and Collections Java泛型和集合

    泛型与集合 使用 进行初步翻译. 将利用碎片时间进行整理和校对,完整的时间段适合做其他需要大量思考的事,如果你有兴趣欢迎提交PR。 TODO 数据校对 目录 2.4 获取和放置原则 2.5 数组 2.6 通配符与类型参数 2.7 ...

    java教程初步讲解

    Java教程初步讲解旨在为初学者提供一套全面而深入的学习路径,帮助他们快速掌握这门广泛应用于全球的编程语言。Java以其“一次编写,到处运行”的跨平台特性,以及在企业级应用、移动开发(尤其是Android)、云计算...

    初步了解java编程语言

    - 集合框架支持泛型,提供高效的数据存储和操作。 7. **多线程**: - Java内置对多线程的支持,可以通过实现Runnable接口或继承Thread类创建线程。 - 线程同步机制包括synchronized关键字、wait(), notify(), ...

    Java2Pas(Java代码转换成Delphi代码)

    1. 项目迁移:当一个组织决定从Java转向Delphi,或者希望将部分Java组件整合到Delphi项目中时,Java2Pas可以帮助快速完成代码的初步转换。 2. 代码复用:开发者可以利用Java2Pas将已有的成熟Java库转换为Delphi代码...

    java初步指南

    13. **泛型**:Java泛型允许在类型中使用类型参数,提高了代码的类型安全性和重用性。 14. **模块系统**:自Java 9开始引入了模块系统,它提高了大型应用程序的可维护性和性能。 15. **Java标准库**:Java附带了...

    Java解惑(中文版)_java_java解惑_solve65p_

    7. **集合框架**:熟悉ArrayList、LinkedList、HashSet、HashMap等集合类的使用,以及泛型的概念。 8. **输入/输出流**:理解I/O流的概念,包括文件操作、字节流和字符流的使用。 9. **多线程**:学习如何创建和...

    java2参考大全

    书中首先对Java语言的基础知识进行了详细介绍,这包括Java的核心概念、基础语法和基本结构,旨在让读者能够对Java语言有一个初步的认识和理解。之后,书中通过具体的实例,对Java语言进行了系统化的讲解,帮助读者更...

    Java程序设计PPT详解

    《Java程序设计》共分12章,内容包括Java语言概述、面向对象编程初步、Java的基本语法、类库与数组、面向对象编程深入、图形用户界面编程、异常处理和输入输出,以及多线程编程等内容。 本书讲解Java程序设计知识...

    北大计算机系java培训讲义

    九、Java泛型 泛型是Java 5引入的新特性,增强了类型安全性和代码可读性。学员需要理解泛型的基本用法和限制。 十、Java 8及以后的新特性 包括Lambda表达式、Stream API、日期和时间API等新特性,都是提升Java编程...

    Java(PDF版)

    2. **环境配置**:解释如何下载和安装Java Development Kit (JDK),以及如何设置Java开发环境,如配置JAVA_HOME变量和集成开发环境(IDE)的初步使用。 3. **语法基础**:涵盖Java的基本语法,包括数据类型(如整型...

    CoreJava.rarCoreJava.rar

    Java泛型引入于1.5版本,允许在定义集合、接口和方法时指定类型参数,增强了类型安全,减少了强制类型转换的麻烦。泛型通配符如、extends T、super T提供了更灵活的类型约束。 十、Lambda表达式 自Java 8起,引入...

    现代编译器的Java实现(第二版).pdf 下载

    书中不仅覆盖了编译器的各个阶段,还详细介绍了如何利用Java语言的特点来优化编译过程,比如利用泛型、反射等高级特性。 ### 结论 对于想要深入了解Java内部机制、提升编程技能或从事软件开发工具链研究的专业人士...

    java学习PDF下载地址全 百度云盘下载

    1. **Java简介**:介绍Java的历史、特点、应用领域以及与其它编程语言的对比,使学习者对Java有一个初步认识。 2. **环境配置**:讲解如何安装Java Development Kit (JDK) 和设置环境变量,为后续开发工作奠定基础...

    java编程逻辑

    15. **Java编程工具**:如Eclipse、IntelliJ IDEA等集成开发环境的使用,以及Maven或Gradle构建工具的初步接触。 通过学习"Java编程逻辑",读者不仅可以掌握Java语言的基础,还能建立起良好的编程思维,为进一步...

    Java经典教程,初学者的最好的宝典,从入门到精通(下)

    本教程"Java经典教程,初学者的最好的宝典,从入门到精通(下)"是专门为那些希望掌握Java编程技能的人设计的,尤其是对Java有初步兴趣并希望深入学习的读者。下面将详细阐述Java的一些核心知识点,这些内容可能包含...

    java程序设计教程(清华大学)

    5. **第8章 泛型-枚举-内部类**:泛型提供了类型安全,枚举用于定义常量集合,而内部类则是Java中实现复杂设计模式的重要工具。 6. **第9章 异常**:讲解了如何处理运行时错误和异常,包括try-catch-finally语句块...

Global site tag (gtag.js) - Google Analytics