`

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的泛型特性,是Java入门学习中的基础知识,需要的朋友可以参考下

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

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

    Java程序设计PPT详解

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

    java之路,主要是java中的学习过程与基础项目.rar

    最开始要学习的是 Java 基础,学习了这部分,就会对 Java 语言有一个初步的了解。其实大部分语言的基础知识都是大同小异,如果之前已经学习过其他语言如C、C++,那学习这部分会更快。 这部分主要学习的内容有:基本...

    实验项目D、Java应用专题编程

    4、初步了解和掌握Java集合框架。 5、掌握Java包装类的基本用法。 6、初步掌握几个常用类和接口的含义和使用。 ★专题:文件IO和数据库编程★ 1、掌握File类的使用。 2、掌握字节流IO的操作。 3、掌握字符流IO的...

    Java语音学习,基础教程

    学习集合:理解Java中的Collection、泛型、List、Set、Collections、Map和HashMap等概念和用法。 掌握异常处理:了解Java的异常体系、异常分类,学会声明、抛出和捕获异常,并自定义异常。 初步掌握多线程:理解线程...

    达内java培训目录

    JavaSE核心 异常处理、多线程基础、IO系统、网络编程、Java反射机制、JVM性能调优(JVM内存结构剖析、GC分析及调优、JVM内存参数优化)、Java泛型、JDK新特性 熟练掌握JavaSE核心内容,特别是IO和多线程;初步具备...

    JAVA基础课程讲义

     泛型 144 思考作业 145 上机作业 145 第八章 IO技术 146 为什么需要学习IO技术 146 基本概念 146 数据源 146 流的概念 146 第一个简单的IO流程序及深入(将文件中的数据读入) 146 Java中流的概念细分 148 Java中...

    AIC的Java课程1-6章

     初步认识面向对象编程,Java视一切为对象。  使用输入和输出语句编写简单的Java应用程序。  区分applet与application(浏览器和虚拟机上运行)。  编写简单的applet,并嵌入HTML文档,掌握其...

    Java典型模块

    第1篇 Java开发必备基础 第1章 搭建Java开发环境 1.1 Java的过去、现在和未来 1.1.1 Java的历史 1.1.2 Java的语言特点 1.1.3 Java API简介 1.1.4 Java未来发展 1.2 Java程序设计环境 1.2.1 命令行工具——JDK 6.0 ...

    Java-预备知识-Java基础

    语法、数组、面向对象、抽象类、接口、枚举、常用类、集合、泛型、注解、异常处理、多线程、IO 流、网络编程、反射。 学习目标:打下扎实的语言基础,深刻理解面向对象的抽象概念,具备初步编码能力,培养对于编程的...

    JavaNotes:自学,存放学习笔记

    Java笔记 自学ing,存放学习笔记 目录 JavaSE ...非双向IO和初步IO MySQL MySQL MySQL常用操作 MySQL高效优化 Oracle Oracle Oracle优化 Oracle 春天 行动计划 国际奥委会 春天 SpringMVC 弹簧靴

    JavaDemo:Java相关演示代码实现

    Java演示 Java相关演示代码实现 ##针对对象 类的继承 类的扩展 异常 ##泛型与容器 泛型 列表和数值 地图和集合 ...初步任务 同步与协作 ##动态与函数式编程 反射 注解 动态代理 类加载机制 函数式编程

    AndroidAll:Android程序员需要掌握的技术栈:数据结构算法,程序架构,设计模式,性能优化,插件化,热更新,Kotlin,NDK,Jetpack,以及常用的开源框架源码分析如Flutter,Router,RxJava, Glide,LeakCanary,Dagger2,Retrofit,OkHttp,ButterKnife等

    最全的Android技术栈 内容涵盖绝大部分Android程序员需要的技能:「数据结构算法」「程序...彻底搞懂Kotlin泛型 Kotlin集合 操作符重载 Kotlin协程 Android基础 四大组件 活动启动模式 数据存储 初步操作 IPC 熟悉常用

    Scala程序设计(第2版)

    22.2 Java泛型与Scala泛型 430 22.3 JavaBean的性质 432 22.4 AnyVal类型与Java原生类型 433 22.5 Java代码中的Scala名称 433 22.6 本章回顾与下一章提要 434 第23章 应用程序设计 435 23.1 回顾...

Global site tag (gtag.js) - Google Analytics