Может кто-нибудь объяснить объявление этих общих методов Java? - PullRequest
9 голосов
/ 14 января 2011

Я читаю «Дженерик Брача» «Дженерики на языке программирования Java», и меня смущает стиль объявления.Следующий код находится на странице 8:

interface Collection<E> 
{ 
    public boolean containsAll(Collection<?> c); 
    public boolean addAll(Collection<? extends E> c); 
} 


interface Collection<E> 
{ 
    public <T> boolean containsAll(Collection<T> c);
    public <T extends E> boolean addAll(Collection<T> c); 
    // hey, type variables can have bounds too! 
} 

Моя путаница связана со вторым заявлением.Мне не ясно, для чего служит объявление <T> в следующей строке:

    public <T> boolean containsAll(Collection<T> c);

У метода уже есть тип (логический), связанный с ним.

Зачем вам использовать <T> и что он говорит компилятору?

Я думаю, что мой вопрос должен быть более конкретным.

Почему вы пишете:

  public <T> boolean containsAll(Collection<T> c);

против

  public boolean containsAll(Collection<T> c);

Мне не ясно, какова цель <T> в первом объявленииcontainsAll.

Ответы [ 6 ]

3 голосов
/ 14 января 2011

Насколько я могу судить, в этом случае <T> вообще не дает ничего полезного. Он создает метод, который полностью функционально эквивалентен тем, которые вместо этого используют подстановочный знак.

Вот несколько примеров, где будет полезным:

public List<?> transform(List<?> in);
//vs
public <T> List<T> transform(List<T> in);

Выше можно соотнести тип возвращаемого значения с типом ввода. Первый пример не может соотнести тип времени выполнения двух подстановочных знаков.

public void add(List<?> list, Object obj);
//vs
public <T> void add(List<? super T> list, T obj);

В приведенном выше примере первый метод даже не сможет добавить obj к list, поскольку его нельзя считать безопасным для типа. Общий параметр во втором гарантирует, что list может содержать любой тип obj.

3 голосов
/ 14 января 2011

Метод уже связан с типом (логическим).

Это тип return .Полный тип метода - «метод, который принимает параметр Collection<T> (для некоторых T) и возвращает boolean».

И вот тут приходит T: параметрфункция использует это.Другими словами, этот метод можно вызывать с разными типами в качестве аргумента.Единственное ограничение этих типов заключается в том, что они должны реализовывать интерфейс Collection<T>, который сам опирается на общий аргумент T (тип объектов, хранящихся в коллекции).

2 голосов
/ 14 января 2011

? это просто подстановочный знак. Это означает, что метод будет принимать коллекцию любого типа.

<T> является параметром типа для метода. По сути, это присвоение подстановочного знака имени, на которое затем можно ссылаться в другом месте в объявлении и определении метода.

Лучшей иллюстрацией различия будет, если тип возвращаемого значения метода изменяется в зависимости от типа, который был передан.

Скажем, вы начали с метода, подобного

Object getRandomElement( Collection<?> c )

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

С параметром типа вы вместо этого напишите

<T> T getRandomElement( Collection<T> c )

В этом случае, если вы вызываете этот метод с Collection<String>, компилятор знает, что он вернет String.

1 голос
/ 14 января 2011

<T> как здесь используется (в объявлении метода, перед возвращаемым типом) является объявлением универсального типа. Вы можете определить новый универсальный тип для использования в методе: http://download.oracle.com/javase/tutorial/java/generics/genmethods.html

0 голосов
/ 14 января 2011

Объявляется универсальный тип T, используемый методом.Хотя универсальный тип E одинаков для всего интерфейса, T ограничен методом, для которого он объявлен.

0 голосов
/ 14 января 2011

Попробуйте скомпилировать его без <T>.

По сути, это говорит компилятору, что этот метод содержит универсальный тип. Это не требуется в первом примере, потому что? это особый случай, и второй метод ссылается на тип, определенный в самом интерфейсе.

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

...