Обобщения и рефлексия в Java - PullRequest
2 голосов
/ 21 февраля 2010

Это, вероятно, очень простой вопрос, но я действительно новичок в дженериках в Java, и мне трудно изменить мой мыслительный процесс по сравнению с тем, как все делается в C #, так что терпите меня.

Я пытаюсь создать общий репозиторий на Java. Я создал интерфейс IRepository, который выглядит следующим образом:

public interface IRepository<T extends IEntity>

И класс репозитория, который выглядит следующим образом:

public class Repository<T extends IEntity> implements IRepository<T>

Теперь из конструктора моего класса Repository я хотел бы иметь возможность "предугадать" точный тип T. Например, если я создаю такой репозиторий, как этот:

IRepository<MyClass> repo = new Repository<MyClass>();

Я хотел бы знать, что T на самом деле MyClass. В C # это тривиально, но очевидно, что дженерики - это совершенно другой зверь в Java, и я не могу найти ничего, что помогло бы мне сделать это.

Ответы [ 3 ]

5 голосов
/ 21 февраля 2010

Java использует стирание типа , поэтому конкретная информация теряется во время выполнения - вы знаете только, что этот тип является общим, а не то, какой конкретный аргумент вы указали во время компиляции.

2 голосов
/ 21 февраля 2010

Вы всегда можете добавить фактический тип T в свой конструктор, например:

public class Repository<T> implements IRepository<T>
  public Repository(Class<T> type) {
  }
}

и создать экземпляр как

IRepository<MyClass> repo = new Repository<MyClass>(MyClass.class);
0 голосов
/ 21 февраля 2010

Я проделал нечто подобное (также для реализации шаблона Repository / Registry) и, немного поработав, вы сможете выяснить тип. Заметьте, однако, что я делал это не с интерфейсами, а с базовым классом, а также отмечал, что потребовалось немало проб и ошибок, чтобы найти работающее решение. Этот код работал на Sun JVM, поэтому, возможно, я наткнулся на область, специфичную для JVM.

Также - как уже упоминалось в другом комментарии, то, что вы можете сделать это, не означает, что вы обязательно должны:)

import java.lang.reflect.ParameterizedType;
...
public static Class<?> type(Object target) {
    Class base = target.getClass();
    while (base != null) {
        Object gsuper = base.getGenericSuperclass();
        if (gsuper != null && gsuper instanceof ParameterizedType) {
            Object o = ((ParameterizedType) gsuper).getActualTypeArguments()[0];
            if (o instanceof Class) {
                return (Class<?>) o;
            }
        }
        base = base.getSuperclass();
    }

    return null;
}

Я использовал это из моего класса BaseRepository как:

Class<?> type = type(SomeRepository);

где:

public class SomeRepository extends Repository<MyEntity> {
... 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...