Что это за использование дженериков в Java? Метод х. ()

Я прочитал всю книгу SCJP6 Сьерра и Бейтс книги, набрал 88% экзамена.

но все же, я никогда не слышал о том, как работает этот вид кода, поскольку он не объясняется в главе generics:

Collections.<TimeUnit>reverseOrder()

что это за использование дженериков? Я обнаружил это в каком-то коде, но никогда не читал об этом. Мне кажется, это позволяет дать некоторую помощь в определении типа. Я пытался найти об этом, но это не так легко найти (и это даже не в SCJP книга / экзамен!)

так может кто-нибудь дать мне достойное объяснение того, как это работает, в навигации и т. д?

спасибо


редактировать Спасибо за ответы, но я ожидал более подробной информации:) поэтому, если кто-то хочет добавить дополнительную информацию:

как насчет более сложных случаев, таких как

  • используя тип, объявленный в классе, могу ли я сделать что-то вроде Collections.<T>reverseOrder() например?
  • используя extends, super?
  • используя ?
  • предоставление компилятору только частичной помощи (т. е. O.manyTypesMethod<?,MyHelpTypeNotInfered,?,?,?,?,?>() )

5 ответов


это явная спецификация типа универсального метода. Вы всегда можете это сделать, но в большинстве случаев это не нужно. Однако в некоторых случаях это необходимо, если компилятор не может самостоятельно вывести универсальный тип.

см. пример ближе к концу учебник страница.

обновление: действителен только первый из ваших примеров. Аргумент explicit type должен быть, ну, явным, поэтому нет подстановочных знаков,extends или super разрешена там. Более того, либо вы указываете каждый аргумент типа явно, либо ни один из них; т. е. количество явных аргументов типа должно соответствовать количеству параметров типа вызываемого метода. Параметр типа, например T допускается, если он хорошо определен в текущей области, например, как параметр типа заключающего класса.


вы на 100% правы, это поможет с выводом типа. В большинстве случаев вам не нужно делать это на Java, так как он может вывести тип (даже с левой стороны задания, что довольно круто). Этот синтаксис рассматривается в учебник по дженерикам на веб-сайте Java.


просто небольшое дополнение к другим ответам.

при получении соответствующей ошибки компилятора:

в то время как" традиционный " подход к кастингу

(Comparator<TimeUnit>) Collections.reverseOrder()

похоже на подход дженериков

Collections.<TimeUnit>reverseOrder()

подход кастинга, конечно, не является типобезопасным (возможное исключение времени выполнения), в то время как подход generics создаст ошибку компиляции, если есть проблема. Поэтому, конечно, предпочтительнее подход дженериков.


как выяснили другие ответы, это поможет компилятору выяснить, какой общий тип вы хотите. Обычно это необходимо при использовании Collections utility методы, которые возвращают что-то общего типа и не получают параметры.

например,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 вернуть значение переменной прежде чем передать его функции, что я думаю, довольно смешно, потому что это кажется ненужным, и это показывает что компилятор действительно непоследователен: it иногда делает вывод типа на общие методы без параметров, но иногда это не так:

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

это может показаться не очень важным, но когда общие типы начинают усложняться (например,Map<String, List<SomeOtherGenericType<Blah>>>) один вид начинает желать, чтобы Java имел более интеллектуальный вывод типа (но, поскольку это не так, вероятно, начнут писать новые классы, где это не нужно, просто чтобы избежать всех этих уродина!--11--> =D).


в этом случае это способ сообщить методу reverseOrder, какой порядок должен быть наложен на объект, на основе того, какой тип вы укажете. Компаратор должен получить конкретную информацию о том, как заказать вещи.