为什么我在使用Generic类时不需要指定类型参数?

Dan*_*tro 1 java

今天这个代码编译时我很惊讶:

class GenericClass<T> {
    public void emptyMethod(T instance) {
        // ..
    }

    public void print(T instance) {
        System.out.println(instance);
    }
}

public class Main {

    public static void main(String[] args) {
        GenericClass first = new GenericClass();
        System.out.println("Wow");
        first.emptyMethod(10);
        first.print(16);
    }

}
Run Code Online (Sandbox Code Playgroud)

编译器发出警告(类型安全:方法emptyMethod(Object)属于原始类型GenericList.对泛型类型GenericList的引用应该参数化),但无论如何它不会导致编译器错误并且它运行'正常'(至少提供的打印方法).正如我所理解的,编译器使用object作为类型参数,但我觉得它反直觉.为什么编译器会这样做呢?为什么它不要求我指定类型参数?

Jon*_*eet 7

你基本上是在使用原始类.

回想一下在Java中首次引入泛型时:已经使用了大量代码List,ArrayList等等.为了避免破坏所有代码,但仍然重用现有类,引入了原始类型 - 它基本上使用了泛型输入好像不是一个.

正如你所看到的,你得到一个警告 - 所以值得避免 - 但这是它被允许的主要原因.

有关更多信息,请参阅JLS的4.8节,其中包括:

原始类型与通配符密切相关.两者都基于存在类型.原始类型可以被认为是通配符,其类型规则是故意不合理的,以适应与遗留代码的交互.从历史上看,原始类型先于通配符; 它们最初是在GJ中引入的,并在文章中描述了过去的未来安全:Gilad Bracha,Martin Odersky,David Stoutamire和Philip Wadler在Java编程语言中添加了通用性,参见ACM会议论文集 - 面向编程,系统,语言和应用(OOPSLA 98),1998年10月.