2012-06-08 1 views
18

Я прочитал всю книгу SCJP6 Сьерра и Бейтса, набрал 88% экзамена.Что это за использование дженериков в Java? X. <Y> метод()

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

Collections.<TimeUnit>reverseOrder() 

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

Так может кто-нибудь дать мне правильное объяснение того, как это работает, и все это и т.д.

Благодаря


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

Что о более сложных случаях, как

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

ответ

18

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

См. Пример в конце the tutorial page.

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

3

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

0

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

+0

Извините, но тип в этом случае не имеет ничего общего с видом заказа: я могу дать тип, который я хочу, под капотом всегда будет тот же самый объект выполнения, выполняющий то же самое. Указанный тип просто помогает компилятору –

1

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

При получении по ошибке компилятора:

В то время как «традиционный» отливка подход

(Comparator<TimeUnit>) Collections.reverseOrder() 

похож на дженерики подходить

Collections.<TimeUnit>reverseOrder() 

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

1

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

Например, рассмотрите методы Collections.empty*, которые возвращают пустую коллекцию. Если у вас есть метод, ожидающий Map<String, String>:

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

Вы не непосредственно передать Collections.emptyMap() к нему. The compiler will complain даже если он знает, что он ожидает Map<String, String>:

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

Вы должны явно declare the type you want in the call, что я думаю, что выглядит довольно уродливо:

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

Или вы можете пропустить эту декларацию типа в методе звоните, если вы assign the emptyMap return value to a variable перед передачей его функции, что я считаю довольно смешным, потому что это кажется ненужным, и это показывает, что компилятор действительно непоследовательный: он иногда делает тип infere сть по общим методам без каких-либо параметров, но иногда это не так:

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

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

+0

Спасибо. Итак, вы подразумеваете, что вывод типа не работает для параметров метода ??? Это всегда так? –

+0

@SebastienLorber Я не уверен. Кроме того, я думаю, что Java 7 добавила некоторые функции вывода типа, хотя первый пример [все еще не компилируется] (http://ideone.com/4H1yx). Одна вещь, которая была добавлена, - это вывод типа для генерических вызовов конструктора, но он работает так же, как и общие методы, например [присваивание переменной] (http://ideone.com/sNoD6) использует вывод типа, но используя выражение [как параметр] (http://ideone.com/nHpfX) напрямую не выполняется: S – epidemian

 Смежные вопросы

  • Нет связанных вопросов^_^