Java理论与实践: 使用通配符简化泛型使用 - 编程入门网
参数 V 被引入到方法签名中并且 没有绑定到其他任何类型参数,它也可以表示任何未知类型,因此,某些未知 T 的 Box<T> 也可能是某些未知 V 的 Box<V>(这和 lambda 积分中 的 α 减法原则相似,允许重命名边界变量)。现在 reboxHelper() 中的表达 式 box.get() 不再具有 Object 类型,它具有 V 类型 — 并允许将 V 传递给 Box<V>.put()。
我们本来可以将 rebox() 声明为一个泛型方法,类似 reboxHelper(),但这 被认为是一种糟糕的 API 设计样式。此处的主要设计原则是 “如果以后绝不会 按名称引用,则不要进行命名”。就泛型方法来说,如果一个类型参数在方法签 名中只出现一次,它很有可能是一个通配符而不是一个命名的类型参数。一般来 说,带有通配符的 API 比带有泛型方法的 API 更简单,在更复杂的方法声明中 类型名称的增多会降低声明的可读性。因为在需要时始终可以通过专有的捕获助 手恢复名称,这个方法让您能够保持 API 整洁,同时不会删除有用的信息。 Java理论与实践: 使用通配符简化泛型使用(3)时间:2010-12-20 IBM Brian Goetz类型推断 捕获助手技巧涉及多个因素:类型推断和捕获转换。Java 编译器在很多情况 下都不能执行类型推断,但是可以为泛型方法推断类型参数(其他语言更加依赖 类型推断,将来我们可以看到 Java 语言中会添加更多的类型推断特性)。如果 愿意,您可以指定类型参数的值,但只有当您能够命名该类型时才可以这样做 — 并且不能够表示捕获类型。因此要使用这种技巧,要求编译器能够为您推断 类型。捕获转换允许编译器为已捕获的通配符产生一个占位符类型名,以便对它 进行类型推断。 当解析一个泛型方法的调用时,编译器将设法推断类型参数它能达到的最具 体类型。 例如,对于下面这个泛型方法: public static<T> T identity(T arg) { return arg }; 和它的调用:
编译器能够推断 T 是 Integer、Number、 Serializable 或 Object,但它 选择 Integer 作为满足约束的最具体类型。 当构造泛型实例时,可以使用类型推断减少冗余。例如,使用 Box 类创建 Box<String> 要求您指定两次类型参数 String: Box<String> box = new BoxImpl<String>(); 即使可以使用 IDE 执行一些工作,也不要违背 DRY(Don''t Repeat Yourself)原则。然而,如果实现类 BoxImpl 提供一个类似清单 5 的泛型工厂 方法(这始终是个好主意),则可以减少客户机代码的冗余: 清单 5. 一个泛型工厂方法,可以避免不必要地指定类型参数
如果使用 BoxImpl.make() 工厂实例化一个 Box,您只需要指定一次类型参 数: Box<String> myBox = BoxImpl.make(); 泛型 make() 方法为一些类型 V 返回一个 Box<V>,返回值被用于需 要 Box<String> 的上下文中。编译器确定 String 是 V 能接受的满足类 型约束的最具体类型,因此此处将 V 推断为 String。您还可以手动地指定 V 的值: Box<String> myBox = BoxImpl.<String>make(); 除了减少一些键盘操作以外,此处演示的工厂方法技巧还提供了优于构造函 数的其他优势:您能够为它们提高更具描述性的名称,它们能够返回命名返回类 型的子类型,它们不需要为每次调用创建新的实例,从而能够共享不可变的实例 (参见 参考资料 中的 Effective Java, Item #1,了解有关静态工厂的更多优 点)。 结束语 通配符无疑非常复杂:由 Java 编译器产 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |