Подтвердить что ты не робот

Как получить атрибут `.class` из параметра общего типа?

В принятом ответе на этот вопрос описывается, как создать экземпляр T в классе Generic<T>. Это включает в себя передачу параметра Class<T> конструктору Generic и вызов метода newInstance из этого.

Затем создается новый экземпляр Generic<Bar> и передается параметр Bar.class.

Что вы будете делать, если параметр generic type для нового класса Generic не является некоторым известным классом, например Bar, но сам является параметром типового типа? Предположим, что у меня был другой класс Skeet<J>, и я хотел создать новый экземпляр Generic<J> изнутри этого класса. Затем, если я попытаюсь пройти в J.class, я получаю следующую ошибку компилятора:

cannot select from a type variable.

Есть ли способ обойти это?

Конкретный бит кода, вызывающий ошибку для меня:

public class InputField<W extends Component & WidgetInterface>
                                                 extends InputFieldArray<W>
{
  public InputField(String labelText)
  {
    super(new String[] {labelText}, W.class);
  }
  /* ... */
}

public class InputFieldArray<W extends Component & WidgetInterface>
                                                                 extends JPanel
{
   /* ... */
  public InputFieldArray(String[] labelText, Class<W> clazz)
                          throws InstantiationException, IllegalAccessException
  {
    /* ... */

    for (int i = 0 ; i < labelText.length ; i++) {
      newLabel = new JLabel(labelText[i]);
      newWidget = clazz.newInstance();
      /* ... */
    }
    /* ... */
  }
  /* ... */
}

Ошибка происходит, потому что я не могу написать W.class. Есть ли другой способ передачи в той же информации?

4b9b3361

Ответ 1

Использование .class в параметре типа недопустимо - из-за типа erasure, W будет стерто до Component во время выполнения. InputField необходимо также взять Class<W> от вызывающего, например InputFieldArray:

public InputField(String labelText, Class<W> clazz)
{
    super(new String[] {labelText}, clazz);
}

Ответ 2

W может быть недоступен из-за стирания типа. Вы должны потребовать, чтобы в метод был передан Class<W>. Вы получаете объект класса, и его общий способ гарантирует, что из-за ковариации передается только W и никакого подкласса.

public InputField(String labelText, Class<W> cls)
{
    super(new String[] {labelText}, cls);
}

возьмет W.class, но не WSubtype.class.

Ответ 3

Я сделал это вот так:

Это определение моего класса:

public class ManagerGeneric <T> {

Это в моем методе:

// Get the type of generic parameter
Type typeOfT = new TypeToken<T>(){}.getType();
// Deserialize
T data = gson.fromJson(json, typeOfT);