Вопрос об обобщении Java - PullRequest
1 голос
/ 13 июля 2010

Хорошо, я думал, что довольно хорошо понял дженерики, но по какой-то причине я не могу понять, почему это не работает.У меня есть два класса, или я должен сказать, что у Google есть два класса (я пытаюсь реализовать их Контакты API).У них есть класс ContactEntry (сокращенно ниже):

package com.google.gdata.data.contacts;

public class ContactEntry extends BasePersonEntry<ContactEntry> {

  public ContactEntry() {
    super();
    getCategories().add(CATEGORY);
  }

  public ContactEntry(BaseEntry<?> sourceEntry) {
    super(sourceEntry);
  }

}

Я остановил один или два метода, но ничего важного, на самом деле это просто реализация его родительского класса BasePersonEntry, в котором есть большинство важных вещей, которые касаютсяниже приведен сокращенный код записи о человеке:

package com.google.gdata.data.contacts;

public abstract class BasePersonEntry<E extends BasePersonEntry> extends
    BaseEntry<E> {

  public BasePersonEntry() {
    super();
  }

  public BasePersonEntry(BaseEntry<?> sourceEntry) {
    super(sourceEntry);
  }

  public List<CalendarLink> getCalendarLinks() {
    return getRepeatingExtension(CalendarLink.class);
  }

  public void addCalendarLink(CalendarLink calendarLink) {
    getCalendarLinks().add(calendarLink);
  }

  public boolean hasCalendarLinks() {
    return hasRepeatingExtension(CalendarLink.class);
  }

}

Теперь ... я не могу понять, если я сделаю что-то вроде следующего:

public void method1(StringBuilder sb, ContactEntry contact) {
 if (contact.hasCalendarLinks()) {
  for (CalendarLink calendarLink : contact.getCalendarLinks()) {
   ...
  }
 }
}

Все работает нормально.Он может интерпретировать, что getCalendarLinks возвращает список типа CalendarLink.Однако, если я хочу абстрагировать этот метод и использовать мой метод BasePersonEntry, например:

public void method1(StringBuilder sb, BasePersonEntry entry) {
 if (entry.hasCalendarLinks()) {
  for (CalendarLink calendarLink : entry.getCalendarLinks()) {
   ...
  }
 }
}

Я получаю ошибку компилятора:

incompatible types
found   : java.lang.Object
required: com.google.gdata.data.contacts.CalendarLink

За всю свою жизнь япросто не могу понять почему?Вызов getCalendarLinks - это тот же самый метод EXACT (посредством наследования), он возвращает тот же самый EXACT.Может быть, это связано с тем, что BasePersonEntry является абстрактным классом?

Если кто-нибудь может пролить свет на это, я был бы очень признателен.Если это поможет, вы можете найти полную версию этого исходного кода, размещенного в Google, здесь: Ссылка на Google Library Download .Я пытался сделать это с версией 1.41.3 их библиотек gdata-java.

1 Ответ

2 голосов
/ 13 июля 2010

Проблема с вашим новым определением заключается в том, что он использует Raw type, а не Generic type.

В результате тип результата удаляется из всего, включая getCalendarLinks и его подпись уменьшена до эквивалента List<Object> getCalendarLinks( )

Чтобы исправить это, измените объявление на:

public void method1(StringBuilder sb, BasePersonEntry<?> entry)

Примечание <?> после BasePersonEntry.Таким образом, это универсальный тип.

Кроме того, вы, вероятно, захотите изменить универсальное объявление класса на

public abstract class BasePersonEntry<E extends BasePersonEntry<E> >

Без <E> ваш компилятор (или IDE) сгенерирует предупреждение unchecked.

...