Java:在Type和Implementation上指定泛型

时间:2009-01-27 08:45:15

标签: java generics

我见过的大多数参考资料,以及我的IDE代码完成都让我在变量类型及其实现上指定了Generic类型,例如。

List<String> string = new ArrayList<String>();

最近我开始在实现中跳过泛型类型,例如。

List<String> strings = new ArrayList();

假设编译器只检查它的spiffy泛型voodoo的类型,并且实现不应该关心,因为它的泛型类型在编译时会被删除,并且根本不应该影响运行时。

我天真吗?是否有理由在实现中包含泛型类型?

4 个答案:

答案 0 :(得分:6)

编译器可能允许您编写具有此类分配的代码(取决于您的警告/错误设置),但它不安全。这是一个例子:

List<Date> dates = new ArrayList<Date>();
List list = dates;
List<String> strings = list;

strings.add("a");
Date d = dates.get(0); // Boom!!

答案 1 :(得分:4)

  

是否有理由在实现中包含泛型类型?

这是必需的,因为它不一定是相同的:

List<? extends Number> numbers = new ArrayList<Integer>();

避免常见情况的一种方法是使用静态实用程序方法,让编译器的类型推断完成其余的工作:

class CollectionUtilities {
   static <T> ArrayList<T> arrayList () { return new ArrayList<T>(); }
}

...

import static CollectionUtilities.*;

List<Integer> numbers = arrayList();

这是类型安全的,并且在实现上不需要泛型类型。 (之所以这样的例子是不安全的,在列表变量的类型上缺少泛型类型,无论你是否需要在变量的类型和实现上都指定泛型类型,都无需做任何事情。)

答案 2 :(得分:0)

虽然在这些情况下能够省略类型泛型定义会很好,但它确实会产生警告。 (有一个严肃的建议是使用非原始语法扩展语言,以推断类型。)你真的不应该忽视编译器警告的习惯。作为Pete Kirkham,您可以使用已存在的类型推断(虽然我建议使用较短的名称)。

答案 3 :(得分:0)

在您展示的简单情况下,您的代码完全可行,因为(在类型擦除之后)编译器将生成完全相同的字节代码。

然而,在稍微复杂的情况下,你可能会遇到麻烦。这就是编译器想要为这种类型的代码发出警告的原因。另外,如果添加了类型化(Java 8?),那么这段代码将被破坏。除非Java 7首先添加类型推断。 : - )

同时最好编写警告清洁代码。