Eclipse 3.1中的Java泛型支持

Java 5 提供泛型支持,泛型支持是开发人员多年以来所要求的特性。它代表了 Java 编程语言一次具有重要意义的升级。像泛型这么复杂的技术,不仅对工具供应商也对开发人员带来了挑战。本文着重介绍 Eclipse 如何应对泛型挑战以及泛型给 Java 语言带来的变化,展示了如何在 Eclipse 中充分利用泛型,包括对于快速帮助、快速修复、重构和项目参数选择的支持。此外,还展示了完全泛型化语言的一些微妙而重要的方面。

Java 中的泛型

几乎从第一个版本开始,Java 技术的创立者们就已经开始讨论对该语言添加泛型支持。C++ 通过标准模板库对泛型进行支持,但是由于缺少所有其他类(嵌入在 Java 语言中的 Object 类中)的一个统一父类,泛型的实现也受到阻碍。Java 编程语言的泛型支持是其历史上最重大的语法变化。由于某些显而易见的原因,工具支持比其他 SDK 升级的步法要慢得多。尽管如此,现在 Eclipse V3.1 已经对这些语言的新特性有了出色的支持。本文重点介绍其中的一些新特性。

Java 5 项目

为了打开 Eclipse V3.1 中的 Java 泛型支持,需要在机器上安装 Java 5,从一些平常的地方都可以下载到 Java 5。泛型支持连同项目属性一起出现在编译器设置页面。这意味着像以前一样,每个项目具有独立的 SDK 设置。为了创建使用泛型的项目,必须在创建项目时指定语言级别或者通过现有项目的项目属性指定语言级别。

Java 5 设置使用两个特定的属性页。第一个属性页指定编译器设置。

图 1. 针对 Java 5 支持的特定于编译器的设置

除非您已经在 Eclipse for Java 5 中设置了默认项目设置,否则需要为该项目覆盖那些设置。JDK compliance 区域允许您决定源文件和类文件的设置。当您把源文件设置为 5.0 级别时,就会获得很多新的内容帮助和重构选项。

另一个相关属性对话框是树型视图中的 Errors/Warnings 区域。

图 2. 项目属性的 Errors/Warnings 区域

大量 J2SE 5 选项能够控制 Eclipse 为您的 Java 5 代码产生什么类型的错误和警告(请参见表 1)表 1. Eclipse 为 Java 5 代码产生的错误和警告

J2SE 5 选项

警告类型

Unchecked generic type operation

编译器每当遇到未经检查的泛型类型操作,就将发出一个错误或者警告。这种操作包括诸如 List 或 ArrayList 等类型上的操作,但没有指定类型。每当您使用一个保存有对象的旧式 Collection 类时就会产生一个警告。

Generic type parameter declared with a final type bound

编译器每当遇到一个涉及 final 类型的类型绑定时,就会发出一个错误或者警告。请看这个示例方法签名:

public int doIt(List extends String> list)

因为 String 是 final 类型,参数不能扩展 String,所以这样写比较有效:

public int doIt(Listlist)

Inexact type match for vararg arguments

当编译器不能从 varargs 参数确定开发人员的意图时,它将生成一个警告。有一些与数组相关的 varargs 是不明确的。

Boxing and unboxing conversions

对自动装箱操作发出警告(装箱操作可能影响性能),并且不再对类型包装对象做对象身份的假设。这是一个默认状态下被忽略的小警告。

Missing @Override annotation

应该为任何重写的方法包含 @Override 注释。缺少这个注释可能表示开发人员没有意识到该方法被重写。

Missing @Deprecated annotation

由于缺少 @Deprecated 标志而产生的警告。

Annotation is used as super interface

您不能把 Deprecated 类作为超级接口。例如,不推荐这种写法:

public interface BadForm extends Deprecated {

}

Not all enum constants covered on switch

switch 语句缺少枚举项意味着您可能遗漏一些枚举选项。

Unhandled warning tokens in @SuppressWarnings

Java 5 允许您添加注释以抑制编译器警告。如果您拼写错了一个警告或者使用了一个并不存在的警告,这个标志将发出一个警告。

Enable @SuppressWarnings annotations

打开程序地(用代码)抑制您不关心的警告的能力。

一旦您根据喜好设定了所有的项目选项,就可以开始在 Eclipse 中使用泛型了。

从特定类型向泛型转换  请考虑清单 1 中的简单类,它创建了一个 Employee 和 Manager 对象的列表(Manager 扩展自 Employee),将他们打印出来,给他们涨工资后再打印出来。

清单 1. HR 类

package com.nealford.devworks.generics.generics;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

public class HR {

public HR() {

List empList = new ArrayList(5);

empList.add(new Employee("Homer", 200.0, 1995));

empList.add(new Employee("Lenny", 300.0, 2000));

empList.add(new Employee("Waylon", 700.0, 1965));

empList.add(new Manager("Monty", 2000.0, 1933,

(Employee) empList.get(2)));

printEmployees(empList);

System.out.println("----- Give everyone a raise -----");

for (int i = 0; i < empList.size(); i++)

((Employee) empList.get(i)).applyRaise(5);

printEmployees(empList);

System.out.println("The maximum salary for any employee is "+

Employee.MAX_SALARY);

System.out.println("Sort employees by salary");

Collections.sort(empList);

printEmployees(empList);

System.out.println("Sort employees by name");

Collections.sort(empList, new Employee.NameComparer());

printEmployees(empList);

System.out.println("Sort employees by hire year");

Collections.sort(empList, Employee.getHireYearComparator());

printEmployees(empList);

}

public void printEmployees(List emps) {

for (int i = 0; i < emps.size(); i++)

System.out.println(emps.get(i));

}

public static void main(String[] args) {

new HR();

}

}

如果您打开了 Java 5 支持,编译这段代码会出现多种警告信息。

快速修复特性

每当 Eclipse 要给您的代码建议一种改进时,Eclipse 的快速修复特性就显示为编辑器窗口左侧边栏上的一个灯泡。在清单 1 中的代码中,您将会看到多个快速修复。

图 3. 快速修复灯泡指示您的代码待改进

快速修复使用灯泡和黄色波浪线指示待改进处。如果将鼠标移动至黄色波浪线上,可以看到出现在图 4 中的改进建议。

图 4. 快速修复指示什么应该被通用化

这里所列的快速修复建议只有一条建议。边上的灯泡提出建议,添加一个本地变量保存 List 的 add() 方法的返回值。然而,在这里该方法返回一个布尔类型值,并且被忽略了。

为了定位快速修复建议,移至重构菜单。Eclipse 中很多重构与 Java 5 中的泛型直接相关。“Infer Generic Type Arguments”重构将给列表增加泛型支持。 第一个对话框允许您选择选项。

图 5. Infer Generic Type Arguments choices 对话框

第一个选项与一个结论相关,这个结论是 clone() 方法将返回接收者类型而不是另外一个类型(相关类)。大部分功能良好的类都遵守这个规则,如果您知道您的类不遵守这个规则,则不要选中这个选项。当第二个选项未选中时,将保留“raw”(非泛型)参数,而不是推断出正确的泛型参数类型。

Eclipse 中的大多数重构中,您都可以预览您的类将发生什么变化。点击这个对话框上的 Preview 按钮将出现图 6 所示的对话框。

图 6. Preview the generic refactoring

更新后的代码如下:

清单 2. 更新后的代码ListempList = new ArrayList(5);

empList.add(new Employee("Homer", 200.0, 1995));

empList.add(new Employee("Lenny", 300.0, 2000));

empList.add(new Employee("Waylon", 700.0, 1965));

empList.add(new Manager("Monty", 2000.0, 1933, empList.get(2)));

代码发生了两个有趣的变化。第一 —— 也是最明显的 —— List 和 ArrayList 声明现在是 Employee 类型的泛型。第二 —— 不太明显 —— 代码最后一行发生的变化。您观察一下 Manager 类的原来的 empList 添加,它的最后一个参数需要针对 Assistant 域强制类型转换为 Employee。而 Infer 重构足够聪明,它可以删除现在不必要的类型强制转换。

在介绍完快速修复之前,Eclipse 还在 Java 5 支持中增加了另外一个有趣的方面:您可以得到为方法添加注释的建议,比如 @Override。您还具有针对注释的内容帮助。

图 7. 针对注释的快速修复和内容帮助扩展

快速帮助特性

Eclipse V3.1 已经添加了快速帮助以促进 Java 5 中的泛型支持。请考虑这个普通的 for() 循环,参见清单 3 中的 printEmployees() 方法。

清单 3. for() 循环public void printEmployees(Listemps) {

for (int i = 0; i < emps.size(); i++)

System.out.println(emps.get(i));

}

除了对泛型的支持外,Java 5 现在也支持 for...each 循环。快速帮助建议将 for loop 变成 for...each,变化后的代码如清单 4 所示。

清单 4. for...each 循环

public void printEmployees(Listemps) {

for (Employee emp : emps)

System.out.println(emp);

}

这个版本由于完全删除了 i 变量和 get() 方法调用而变得清洁多了。

泛型类型  Eclipse V3.1 为了扩展到泛型类型而扩大了对类型操作的支持。这意味着:

泛型类型能够被安全地重命名。

类型变量能够被安全地重命名。

泛型方法能够从泛型代码中抽象出来或者嵌入泛型代码。

代码帮助可以自动将合适的类型参数插入参数化的类型中。

Eclipse 中的搜索工具对于泛型类型已经具有了更高的智能性。请考虑如下代码:

清单 5. 泛型类型public void doEmployeeAnalysis() {

ListempList = new ArrayList(5);

ListhireDates = new ArrayList(5);

Listdepartments = new ArrayList(10);

List extends Employee> allMgrs = new ArrayList(5);

. . .

如果您选中第一个 List声明并且选择 Search > References > Project,Eclipse 将显示给您所有的 list 声明。

图 8. Eclipse 在寻找泛型引用方面已经变得聪明

您也可以通过 Search 窗口隐藏良好的特性来过滤这些结果。如果您访问 Search 窗口菜单(在右上角,最小化和最大化按钮的旁边),您可以找到泛型感知的过滤选项。

图 9. 搜索窗口的过滤菜单允许您过滤泛型感知的结果

如果您使用 Filter Incompatible 过滤结果,将删除两个不是基于 Employee 的条目。结果如图 10 所示。

图 10. Filter Incompatible 在搜索窗口过滤掉与非 Employee 相关的条目

深入了解泛型

不幸的是,Eclipse 不能解决您所有的泛型问题。事实上,有时重构会为您要解决的问题产生语法正确但是语义不正确的代码。具有讽刺意味的是,在泛型出现之前的那些日子更轻松,因为您必须将所有东西都作为对象的泛型集合传递。而现在您必须小心地传递正确类型的集合。

考虑这个例子。在 HR 应用程序中,您添加一个方法确定雇员的退休年龄。然而,Employee 的年龄是来自于 Employee 的父类:Person。写一个方法只接受在这个实例中工作的雇员,但是您不想将您的应用程序只用于雇员。如果将来您需要查询以前的雇员(作为 Persons),该怎么办呢?

这个问题的解决方案在于灵活的泛型参数。请考虑清单 6 中的代码,它接受任何扩展自 Person 的类。

清单 6. 示例 SELECT 语句public ListempsOverRetirementAge(

List extends Person> people) {

Listretirees = new ArrayList(1);

for (Person e : people)

if (e.getAge() > 65)

retirees.add(e);

return retirees;

}

该方法接受 Person 的任何子类,所以更灵活。使用泛型的时候,您应该牢记这一点。在本例中,泛型实际上比较特定(至少,他们应该称这种语言特性为“特定性”)。仔细识别参数类型能够使您的代码获得同样的灵活性,因此性能比泛型更好,但是具有泛型提供的附加的类型安全性。

结束语

泛型支持大大增强了 Java 编程语言,工具供应商必然需要很长时间才能赶上。现在有了好的工具支持,您应该开始利用这种高级语言特性。它使代码更加可读 —— 因为删除了类型强制转换 —— 并且允许编译器为您做更多的工作。任何时候您都可以让编译器和其他的工具(如 IDE)做更多的工作,这意味着您要做的工作更少。

java泛型属性_java泛型介绍相关推荐

  1. java 泛型属性_Java泛型

    一.定义 泛型可以用来指代任意对象类型. 二.泛型和多态 1.引入多态 定义一个C1类:里面有个Integer属性,给出它的构造方法.打印其类型和get\set方法. 1 packagecom.swu ...

  2. java泛型 初始化_Java泛型详解

    概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用. 什么是泛型?为什么要使用泛型? 泛型,即"参数化类型".一提到参数,最熟悉的就是定义方法时有 ...

  3. java 泛型参数_Java泛型

    一.概述 Java泛型(generics)是JDK 5中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许程序员在编译时监测非法的类型.使用泛型机制编写的程序代码要比那些杂乱地使用Obje ...

  4. 泛型java 代码讲解_Java泛型详解

    2516326-5475e88a458a09e4.png 一,打破砂锅问到底 泛型存在的意义? 泛型类,泛型接口,泛型方法如何定义? 如何限定类型变量? 泛型中使用的约束和局限性有哪些? 泛型类型的继 ...

  5. java泛型方法 通配符_Java泛型教程–示例类,接口,方法,通配符等

    java泛型方法 通配符 泛型是Java编程的核心功能之一,它是Java 5中引入的.如果您使用的是Java Collections ,并且版本5或更高版本,则可以肯定使用了它. 将泛型与集合类一起使 ...

  6. java泛型面试_Java泛型面试问题

    java泛型面试 Java面试中的通用面试问题在相当长的时间内在Java 5周围越来越普遍,许多应用程序都转移到Java 5上,并且几乎所有新的Java开发都发生在Tiger(Java 5的代号)上. ...

  7. java泛型特点_java泛型简单总结

    Java泛型简单总结 1)基本概念: 泛型(Generic Type或Generics)是 对Java语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看做是使用参数化类型时 ...

  8. java泛型 包_Java泛型应用浅析

    Java泛型应用浅析 Java泛型,饿,这个东西吗,嚼一下还是有必要的.有啥用呢?小弟曾觉着吧,吹牛是条不错的出路,但没一次没有不吹破的.(绕吧^_^) 详解呢,没啥必要了,参见附件解压后Java泛型 ...

  9. java 泛型示例_Java泛型示例教程–泛型方法,类,接口

    java 泛型示例 Java Genrics is one of the most important features introduced in Java 5. Java Genrics是Java ...

最新文章

  1. Java Web 中的一些问题
  2. Linux VI编辑器
  3. SpringMVC入门案例
  4. 在一台服务器绑定多个IP
  5. COM编程入门---转发
  6. php归档函数(按时间)实现
  7. 如何在Microsoft Word中插入签名
  8. 网页用数学公式编辑器 可以集成到FCKeditor
  9. Android项目持续集成之Jenkins的使用
  10. [转载]Spring Cloud微服务Sentinel+Apollo限流、熔断实战
  11. C#创建Windows服务程序
  12. 【ArcGIS|空间分析】地形特征相关计算
  13. python kivy kv模板调用_正确使用.kv文件进行Kivy并将其导入到Python...
  14. word中有软回车(每行后面有向下的箭头)的解决方法
  15. someone you loved 歌词翻译
  16. ios备忘录下载安卓版_如何下载和平精英国际服?
  17. 不能装载文档控件。请在检查浏览器的选项中检查浏览器的安全设置_【网络安全知识系列(五)】如何正确设置浏览器!...
  18. node.js 安装详细步骤
  19. 转:GTD,Get Things Done(搞定时间管理)
  20. 曲速未来 揭秘:以太坊区块链和ERC20代币的技术挑战

热门文章

  1. 实证型高水平英语论文基本结构与写作体会
  2. telnet端口解决如何连接的问题
  3. 一看就懂:时间复杂度与空间复杂度
  4. 京东全员涨至16薪,网友:别人家的老板
  5. 计算机音乐创作比赛作品,2015年(第八届)中国大学生计算机设计大赛“计算机音乐创作类”决赛在我院隆重开幕...
  6. qstring 字符串查找_Qt QString常用方法
  7. windows7部署hitchhiker
  8. 网站SEO,HTTP请求的关键数字----6
  9. 数字上的错误后缀_域名创业方法之前后缀完美搭配
  10. 腾讯云 centOS 下安装 chrome 浏览器