class Response<T>
{ ... }
Response response = new Response();
Run Code Online (Sandbox Code Playgroud)
上面的代码编译.我不明白隐含的是什么.编译器不应该要求'T'的类型规范吗?例如以下内容:
Response<String> response = new Response<String>();
Run Code Online (Sandbox Code Playgroud)
从技术上讲,它应该/应该.但是,为了向后兼容Java 5,这没有完成,因此不需要通用参数.而且由于泛型是通过擦除实现的,所以无论你是否声明参数,所发出的字节码都是相同的 - 你所缺少的只是一些编译时检查.
(注意,如果在response对象上调用方法,编译器会警告您使用"原始类型",这意味着您以非泛型方式使用泛型类,因此它不能为您强制执行任何约束.)
编辑:关于向后兼容性,这是一种平衡行为,并且Sun明显牺牲了一些方面来改进/维护其他方面.打破向后兼容性将是一件非常重要的事情 - 这意味着迁移到最新版本的Java将是一个非常重要的项目,并且会在企业内部产生更大的阻力来升级.
这里的重大决定是通过擦除来实现泛型,这样它们就是"仅编译时"构造,并且生成的字节码与先前版本相同.这样做的优点是,例如java.util.HashMap在1.5中仍然可以通过1.4编写的代码访问(当然这种优势也可以扩展到您自己的类).但是,有很多观点,特别是那些习惯使用类似技术的其他语言中的仿制药,这不是最好的决定,并且削弱了仿制药的实用性.我不会在这里谈论它.
至于它是否颠覆了编译器想要强制执行的检查; 我认为这并不像你想象的那么糟糕. 是的,您可以编写代码,使编译器不进行任何泛型检查,并且您可以故意破坏预期的语义.但是,编译时检查并不是某种安全功能,它们只是帮助您,作为一种静态分析形式,可以获取某些类型的错误.如果你想颠覆它们,请随意这样做.但是如果你正确编写了通用类,那么你将得到你想要的编译时检查.
特别是因为编译器(可以)给你关于原始类型的警告,有一个明确的升级路径从1.4到5.升级你的JDK - 你的旧代码仍然编译,尽管有警告.然后使用这些警告来追踪违规行为,并在需要时生成旧代码.在我看来,这比简单地拒绝编译旧的(可能是功能性的!)代码要好得多,直到每个语句都添加了适当的泛型.
大多数IDE都允许您对不同警告类型的严重性进行分类,这样,如果您从头开始开发Java 5应用程序,则可以告诉它将所有原始类型警告视为完全停止构建错误.