Java — Как передать универсальный параметр как Class конструктору

#java #generics #inheritance

#java #общие #наследование

Вопрос:

У меня здесь проблема, которую все еще не удается решить, дело в том, что у меня есть этот абстрактный класс:

 public abstract class AbstractBean<T> {
    private Class<T> entityClass;

    public AbstractBean(Class<T> entityClass) {
        this.entityClass = entityClass;
    }
    ...
}
  

Теперь у меня есть другой класс, который наследует этот абстрактный:

 @Stateless
@LocalBean
public class BasicUserBean<T extends BasicUser> extends AbstractBean<T>  {
    private Class<T> user;    

    public BasicUserBean() {  
        super(user);  // Error: cannot reference user before supertype contructor has been called.
    }
}
  

Мой вопрос в том, как я могу заставить это работать?, Я пытаюсь сделать класс BasicUserBean наследуемым, поэтому, если у меня есть класс PersonBean, который наследует BasicUserBean, тогда я мог бы установить в Generic объект Person, который также наследует объект BasicUser. И в конечном итоге это будет:

 @Stateless
@LocalBean
public class PersonBean extends BasicUserBean<Person>  {

    public PersonBean() {
        super(Person.class);
    }
    ...
}
  

Я просто хочу унаследовать базовую функциональность от BasicUserBean для всех потомков, поэтому мне не нужно повторять один и тот же код среди всех потомков. Спасибо!.

Комментарии:

1. Итак, в чем проблема с вашим последним фрагментом кода?

2. Компилятор выдает ошибку: «не удается сослаться на пользователя до вызова конструктора супертипа».

3. Я имею в виду, какие проблемы с super(Person.class); сниппетом?

4. какой у вас BasicUser класс …? любой фрагмент кода? также Person класс может быть полезен.

5. Вы хотите, чтобы подклассы занимали место Person.class ?

Ответ №1:

Вам нужно добавить конструктор в BasicUserBean , взяв Class<T>

 public BasicUserBean(Class<T> entityClass) {
    super(entityClass);
}
  

Ваш конструктор без аргументов не будет работать, поскольку класс, который вы расширяете, требует T . Вы не можете иметь a T в своем конструкторе, не принимая T в качестве аргумента; во всяком случае, не без приведения.

Комментарии:

1. Тогда BasicUserBean() конструктор без аргументов и user свойство member также можно безопасно удалить, поскольку в них не будет необходимости.

2. Спасибо, Йохан, это решило проблему. Даже подумав, после этого я получил сообщение компилятора, в котором говорилось «Класс EJB должен иметь общедоступный или защищенный конструктор без аргументов», поэтому я просто добавил конструктор «без аргументов» как к абстрактному классу, так и к классу BasicUserBean, и теперь он работает нормально. Еще раз спасибо.

Ответ №2:

Как указано в ошибке, вы не можете передать поле экземпляра в вызов суперконструктора. Обратите внимание, что поле user всегда null находится в точке, которую вы вызываете super , так в чем же будет смысл. Вам нужно будет передать user в конструктор и передать это в super или установить user как константу.

Ответ №3:

Если AbstractUserBean — это ваш собственный класс, и вам разрешено его изменять, вы можете заменить его конструктор из

 public AbstractBean(Class<T> entityClass) {
    this.entityClass = entityClass;
}
  

к этому

 public AbstractBean() {
    ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
    this.entityClass = (Class<T>) type.getActualTypeArguments()[0];
}
  

Таким образом, параметризованные конструкторы вообще не требуются.