Аннотация, чтобы сделать доступным универсальный тип - PullRequest
11 голосов
/ 12 июня 2010

Учитывая универсальный интерфейс, такой как

interface DomainObjectDAO<T>
{
   T newInstance();
   add(T t);
   remove(T t);
   T findById(int id);
   // etc...    
}

Я хотел бы создать подынтерфейс, который определяет параметр типа:

  interface CustomerDAO extends DomainObjectDAO<Customer> 
  {
       // customer-specific queries - incidental.
  }

Реализация должна знать фактический тип параметра шаблона, но, конечно, средство стирания типа недоступно во время выполнения.Есть ли какая-нибудь аннотация, которую я мог бы включить, чтобы объявить тип интерфейса?Что-то вроде

  @GenericParameter(Customer.class)
  interface CustomerDAO extends DomainObjectDAO<Customer> 
  {
  }

Реализация может затем извлечь эту аннотацию из интерфейса и использовать ее в качестве замены для доступа к универсальному типу во время выполнения.

Некоторый фон:

Этот интерфейсреализован с использованием динамических прокси JDK, как указано здесь .Неуниверсальная версия этого интерфейса работала хорошо, но было бы лучше использовать универсальные шаблоны и не нужно создавать методы в подинтерфейсе только для указания типа объекта домена.Обобщения и прокси-серверы заботятся о большинстве вещей, но фактический тип необходим во время выполнения для реализации метода newInstance, среди прочего.

Ответы [ 2 ]

7 голосов
/ 12 июня 2010

Можно найти фактический аргумент типа подчиненного интерфейса Dao (CustomerDAO), вызвав следующий метод:

import java.lang.reflect.ParameterizedType;

public static Class<?> getDomainClass(final Class<?> daoInterface) {
    ParameterizedType type = (ParameterizedType) daoInterface.getGenericInterfaces()[0];
    return (Class<?>) type.getActualTypeArguments()[0];
}

Когда вы называете это как

Class<?> domainClass = getDomainClass(daoInterface);

с daoInterface == CustomerDAO.class, тогда вы получите domainClass == Customer.class.

В моей реализации DaoFactory выполняет этот вызов и использует domainClass в качестве аргумента конструктора для DaoInvocationHandler.

1 голос
/ 12 июня 2010

Реализация должна знать фактический тип параметра шаблона.

Конечно, любая реализация CustomerDao неявно знает , что параметром типа является Customer. Он реализует DomainObjectDAO<Customer>, а не DomainObjectDAO<T>.

Проблемы могут возникнуть только в том случае, если класс CustomerDao расширяет общий абстрактный класс, и этот общий абстрактный класс должен знать фактический тип T. Но вы можете справиться с этим, передав объект Class для T (в данном случае Customer.class) суперклассу в качестве аргумента конструктора.

...