Generics: компилятор кажется неспособным распознавать, что тип, передаваемый на аргумент, совпадает с тем, что возвращается - почему?

StackOverflow https://stackoverflow.com/questions/3120428

  •  30-09-2019
  •  | 
  •  

Вопрос

Скажем, у меня есть несколько пож, которые все распространяют общий супертип, BaseObject.

у меня есть GenericDao который объявлен как public interface GenericDao<T>.

Для каждого типа DAO у меня есть интерфейс, который расширяет общий тип и ограничивает его бетонному типу (public interface UserDao extends GenericDao<User>) а затем реализация типа конкретной дао.

В классе, которые пытаются использовать ряд GenericDao реализации, у меня есть метод, который выглядит как

public <T extends BaseObject> long create(T object) {
    return getDao(object.getClass()).save(object);
}

Если я реализую getDao() так что это параметр является Class объект, такой как

private <T extends BaseObject> GenericDao<T> getDao(Class<T> clazz) { ... }

Тогда звонок getDao(object.getClass() в create() Метод не может компилировать - компилятор, кажется, интерпретирует тип возврата getDao() так как

GenericDao<? extends BaseContractObject>

вместо того, чтобы признать, что getDao(Class<T>) собирается вернуть меня GenericDao одинакового типа T.

Может кто-нибудь объяснить, почему это? Я понимаю, что повторные появления одного и того же типа связаны или подстановочный знак не нуждаются в том же типе; Однако кажется, что компилятор должен признать от подписи getDao(Class<T>) что T прошедший, должен быть тот же t вернулся (но, очевидно, он не способен распознавать это, Зачем это часть, которую я не понимаю).

Если я вместо этого определяю getDaoподпись, чтобы быть

private <T extends BaseContractObject> GenericDao<T> getDao(T obj) { ... }

Тогда нет проблем в составлении create() реализация, которая выглядит как

public <T extends BaseContractObject> long create(T object) {
    return getDao(object).save(object);
}

Так почему же компилятор способен распознавать в этом случае, что T Аргумент передан getDao(T) то же самое T в возвращении типа, тогда как он не мог распознать это, когда аргумент был Class<T>?

Это было полезно?

Решение

Выражение object.getClass(), где объект имеет тип T extends BaseObject, возвращает А. Class<? extends BaseObject>, а не а Class<T> Как можно ожидать. Так, getDao() возвращает дао одного и того же типа, который он получает; Это просто не получает ожидаемый тип.

Другие советы

Это проблема стирания классического типа. getClass() имеет следующую подпись:

public final native Class<? extends Object> getClass();

Если у тебя есть String и сделать а getClass() на нем класс, который вы получаете, это Class<? extends String>. Отказ Javadocs читают:

 * @return The <code>java.lang.Class</code> object that represents
 *         the runtime class of the object.  The result is of type
 *         {@code Class<? extends X>} where X is the
 *         erasure of the static type of the expression on which
 *         <code>getClass</code> is called.

Вам нужно будет заставить отказаться от следующего, чтобы получить его на работу:

@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>)object.getClass();
return getDao(clazz).save(object);

Это подходит для меня.

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

http://www.angelikalanger.com/genericsfaq/faqsions/typeparameters.html#faq206.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top