Java 泛型 - 类型声明

标签 java generics

class Response<T>
{ ... }

Response response = new Response();

上面的代码可以编译。但我不明白这意味着什么。编译器不应该要求“T”的类型规范吗?例如像下面这样:

Response<String> response = new Response<String>(); 

最佳答案

从技术上讲,它应该/应该。然而,为了向后兼容 Java 5,这并没有完成,因此不需要通用参数。而且由于泛型无论如何都是通过删除来实现的,因此无论您是否声明参数,发出的字节码都是相同的 - 您所错过的只是一些编译时检查。

(请注意,如果您在 response 对象上调用方法,编译器将警告您使用“原始类型”,这意味着您正在使用泛型类以非通用方式,因此它无法为您强制执行任何约束。)

编辑:关于向后兼容性,这是一种平衡行为,Sun 显然牺牲了某些方面来改进/维护其他方面。破坏向后兼容性将是一件大事 - 这意味着迁移到最新版本的 Java 将是一个不小的项目,并且会在企业内部产生更大的升级阻力。

这里的重大决定是通过删除来实现泛型,这样它们就是“仅编译时”构造,并且生成的字节码与以前的版本相同。这样做的优点是,例如1.5 中的 java.util.HashMap 仍然可以通过 1.4 中编写的代码访问(当然,这个优势也扩展到您自己的类)。然而,有很多人认为,这不是最好的决定,并且削弱了泛型的实用性,尤其是那些习惯了其他语言中的泛型并希望使用类似技术的人。我不会在这里权衡这一点。

至于它是否破坏了编译器想要强制执行的检查;我认为情况没有你想象的那么糟糕。 是的,您可以编写代码,使编译器不执行任何泛型检查,并且您可以故意破坏预期的语义。然而,编译时检查并不意味着某种安全功能,它们只是为了帮助您,作为一种静态分析形式,可以发现某些类型的错误。如果您想要颠覆它们,请随意这样做。但是,如果您正确编写泛型类,那么您将获得您想要的编译时检查。

特别是因为编译器(可以)向您提供有关原始类型的警告,因此从 1.4 到 5 有一个明确的升级路径。升级您的 JDK - 尽管有警告,您的旧代码仍然可以编译。然后使用这些警告来追查违规行为,并在需要时生成旧代码。在我看来,这比简单地拒绝编译旧的(可能是功能性的!)代码要好得多,直到每个语句都添加了适当的泛型。

大多数 IDE 都会让您对不同警告类型的严重性进行分类,这样,如果您从头开始开发 Java 5 应用程序,您可以告诉它将所有原始类型警告视为完全停止构建错误.

关于Java 泛型 - 类型声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3257548/

相关文章:

java - "<T extends SuperClass>"的正确用法

java - 泛型、类型删除和静态结构方法

c# - 为什么通用类型定义实现的接口(interface)会丢失类型信息?

java - Selenium waitForPageToLoad 结束条件

ios - 通用 UITableViewCell 标识符

java - Aspectj 围绕字段和类初始化的建议

java - 在非 Maven 项目中放置 log4j.xml 文件的位置

关于通配符的 Java 语言规范

java - 使用 DefaultHttpClient 和 Swingworker 实现 cookie 持久化

java - 具有多个键的映射