18

我已经阅读了整个 SCJP6 书籍 Sierra 和 Bates 的书,考试成绩为 88%。

但是,我从来没有听说过这种代码是如何工作的,因为它没有在泛型章节中解释:

Collections.<TimeUnit>reverseOrder()

这种泛型用法是什么?我在一些代码中发现了它,但从未读过任何关于它的内容。在我看来,它允许为类型推断提供一些帮助。我已经尝试过搜索,但并不容易找到(甚至在 SCJP 书籍/考试中也没有!)

那么有人可以给我一个正确的解释它是如何工作的,这是所有的用例等吗?

谢谢


编辑 感谢您的回答,但我希望有更多详细信息:) 所以如果有人想添加一些额外的信息:

更复杂的情况呢?

  • 使用类中声明的类型,我可以做类似Collections.<T>reverseOrder()的事情吗?
  • 使用extends, super?
  • 使用?
  • 只给编译器部分帮助(即O.manyTypesMethod<?,MyHelpTypeNotInfered,?,?,?,?,?>()
4

5 回答 5

18

它是泛型方法的显式类型规范。您总是可以这样做,但在大多数情况下,它是不需要的。但是,如果编译器无法自行推断泛型类型,则在某些情况下需要它。

请参阅教程页面末尾的示例。

更新:只有你的第一个例子是有效的。显式类型参数必须是显式的,所以没有通配符,extends或者super在那里被允许。此外,您要么明确指定每个类型参数,要么不指定它们;即显式类型参数的数量必须与被调用方法的类型参数的数量相匹配。T如果在当前范围内定义良好,例如作为封闭类的类型参数,则允许使用诸如此类的类型参数。

于 2012-06-08T08:46:54.247 回答
3

您是 100% 正确的,这是为了帮助进行类型推断。大多数时候您不需要在 Java 中执行此操作,因为它可以推断类型(甚至从赋值的左侧,这非常酷)。Java 网站上的泛型教程中介绍了此语法。

于 2012-06-08T08:49:19.770 回答
1

只是对其他回复的一个小补充。

当得到相应的编译器错误时:

而“传统”的铸造方式

(Comparator<TimeUnit>) Collections.reverseOrder()

看起来类似于泛型方法

Collections.<TimeUnit>reverseOrder()

转换方法当然不是类型安全的(可能的运行时异常),而泛型方法会在出现问题时产生编译错误。因此,当然首选泛型方法。

于 2012-06-08T09:04:20.463 回答
1

正如其他答案所阐明的那样,这是为了帮助编译器找出您想要的泛型类型。当使用Collections返回泛型类型但不接收参数的实用方法时,通常需要它。

例如,考虑Collections.empty*返回空集合的方法。如果您有一个方法需要Map<String, String>

public static void foo(Map<String, String> map) { }

不能直接传递Collections.emptyMap()给它。即使编译器知道它需要一个Map<String, String>

// This won't compile.
foo(Collections.emptyMap());

你必须在调用中明确声明你想要的类型,我认为这看起来很丑:

foo(Collections.<String, String>emptyMap());

或者,如果在将返回值传递给函数之前将返回值分配给emptyMap变量,则可以在方法调用中省略该类型声明,我认为这很荒谬,因为这似乎没有必要,并且表明编译器确实不一致:有时对没有参数的泛型方法进行类型推断,但有时它不会:

Map<String, String> map = Collections.emptyMap();
foo(map);

这似乎不是一件很重要的事情,但是当泛型类型开始变得更复杂(例如Map<String, List<SomeOtherGenericType<Blah>>>)时,一种开始希望 Java 具有更智能的类型推断(但是,事实并非如此,人们可能会开始编写新的不需要它的类,只是为了避免所有那些丑陋的<>=D)。

于 2012-06-08T13:42:37.277 回答
0

在这种情况下,它是一种告诉 reverseOrder 方法应根据您指定的类型对对象施加何种排序的方法。比较器需要获取有关如何订购物品的特定信息。

于 2012-06-08T08:50:43.440 回答