我见过的大多数参考资料,以及我的IDE代码完成都让我在变量类型及其实现上指定了Generic类型,例如。
List<String> string = new ArrayList<String>();
最近我开始在实现中跳过泛型类型,例如。
List<String> strings = new ArrayList();
假设编译器只检查它的spiffy泛型voodoo的类型,并且实现不应该关心,因为它的泛型类型在编译时会被删除,并且根本不应该影响运行时。
我天真吗?是否有理由在实现中包含泛型类型?
答案 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首先添加类型推断。 : - )
同时最好编写警告清洁代码。