我正在阅读Effective Java 2nd Edition,在Item 28: Use bounded wildcards to increase API flexibility中有以下内容:
// Two possible declarations for the swap method public static <E> void swap(List<E> list, int i, int j); public static void swap(List<?> list, int i, int j);
这两个声明中的哪一个更可取,为什么?在公共场合 API,第二个更好,因为它更简单。你传入一个列表 - 任何 list-和方法交换索引元素。没有类型 担心的参数。通常,如果仅显示类型参数 在方法声明中,将其替换为通配符。
我使用unbounded类型参数测试它,我没有看到任何缺点,我可以传递任何列表,我没有类型参数的问题,实际上无界的类型参数更好,因为我不需要帮手方法解释顺序:
有一种方法可以实现此方法,而无需使用不安全的方法 演员或原始类型。我们的想法是编写一个私有帮助方法 捕获通配符类型。辅助方法必须是通用方法 为了捕捉类型。这是它的外观:
public static void swap(List<?> list, int i, int j) { swapHelper(list, i, j); } // Private helper method for wildcard capture private static <E> void swapHelper(List<E> list, int i, int j) { list.set(i, list.set(j, list.get(i))); }
最后,这是我使用类型参数的实现:
public static <E> void swap(List<E> list, int i, int j) {
list.set(i, list.set(j, list.get(i)));
}
和用法:
List<Object> integers = (...)
swap(integers, 1,2);
那么,为什么我要使用通配符呢?
问题是:为什么第二种方式更简单?我看不出原因!我想念一些细节?我真的很想了解布洛赫的意思。
答案 0 :(得分:2)
首先,要了解布洛赫在这里提出关于偏好的声明 - 你不一定要同意他(我在这一点上目睹了长时间和艰苦的讨论,所以你不是唯一的一个。)
然而,他确实说明了为什么他认为这更好。我会尝试提出他的关键点,以便他们更清楚。在公共API中,第二个更好,因为...没有类型参数需要担心。通常,如果类型参数在方法声明中只出现一次,请将其替换为通配符....
这个稍微复杂的实现......允许我们导出漂亮的基于通配符的声明....
在API中使用通配符类型虽然棘手,但却使API变得更加灵活。
换句话说,Bloch认为需要E
类型是一个您不应向客户公开的实现细节 - swap()
方法适用于任何List
方法因此?
是&#34;正确&#34;并且公开E
绝不会使用户受益。从某种意义上说,这是项目52的概括:通过接口引用对象。
请特别注意,此建议仅针对公共API。没有必要只在你打电话的代码中实现这种解决方法。
这个例子也可以说是人为的 - 两个解决方案之间并没有太大的区别,但希望你能想象出更复杂的方法需要通用类型作为其实现的一部分,而不是它们的公共签名。布洛赫的一般观点是,当用户不需要了解泛型类型时,即使这样做看起来微不足道,也不需要将这些知识强加给他们。