Как получить экземпляр класса универсального типа T

Старая запись, но в случае, если кто-то вроде меня наткнулся на нее:

Для ContextMenuStrip выше не работало для меня, но это привело к обнаружению того, что произошло.

void DeleteMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
    ContextMenuStrip menu = sender as ContextMenuStrip;
    Control sourceControl = menu.SourceControl;
    MessageBox.Show(sourceControl.Name);
}

Это дало мне имя ожидаемого контроля. Вы можете ввести подтверждение и т. Д. С операторами if, я просто отправляю сообщения, чтобы добраться до точки.

630
задан Peter Mortensen 27 September 2015 в 07:35
поделиться

6 ответов

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

Популярным решением этой проблемы является передача Class параметра типа в конструктор универсального типа, например

class Foo<T> {
    final Class<T> typeParameterClass;

    public Foo(Class<T> typeParameterClass) {
        this.typeParameterClass = typeParameterClass;
    }

    public void bar() {
        // you can access the typeParameterClass here and do whatever you like
    }
}
533
ответ дан 22 November 2019 в 21:47
поделиться

Этот вопрос стар, но теперь лучшим является использование Google Gson.

пример для получения пользовательским viewModel.

Class<CustomViewModel<String>> clazz = new GenericClass<CustomViewModel<String>>().getRawType();
CustomViewModel<String> viewModel = viewModelProvider.get(clazz);

Универсальный класс

class GenericClass<T>(private val rawType: Class<*>) {

    constructor():this(`$Gson$Types`.getRawType(object : TypeToken<T>() {}.getType()))

    fun getRawType(): Class<T> {
        return rawType as Class<T>
    }
}
типа
0
ответ дан 22 November 2019 в 21:47
поделиться

Это является довольно прямым. Если Вам нужно из того же класса:

Class clazz = this.getClass();
ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
try {
        Class typeClass = Class.forName( parameterizedType.getActualTypeArguments()[0].getTypeName() );
        // You have the instance of type 'T' in typeClass variable

        System.out.println( "Class instance name: "+  typeClass.getName() );
    } catch (ClassNotFoundException e) {
        System.out.println( "ClassNotFound!! Something wrong! "+ e.getMessage() );
    }
1
ответ дан 22 November 2019 в 21:47
поделиться

Стандартный подход / обходной путь / решение - добавить объект class в конструктор (ы), например:

 public class Foo<T> {

    private Class<T> type;
    public Foo(Class<T> type) {
      this.type = type;
    }

    public Class<T> getType() {
      return type;
    }

    public T newInstance() {
      return type.newInstance();
    }
 }
35
ответ дан 22 November 2019 в 21:47
поделиться

Вы не можете этого сделать из-за стирания типов. См. также вопрос на Stack Overflow Java generics - type erasure - when and what happens.

10
ответ дан 22 November 2019 в 21:47
поделиться

Лучше, чем класс, предложенный другими, - передать объект, который может делать то, что вы бы сделали с Класс, например, создать новый экземпляр.

interface Factory<T> {
  T apply();
}

<T> void List<T> make10(Factory<T> factory) {
  List<T> result = new ArrayList<T>();
  for (int a = 0; a < 10; a++)
    result.add(factory.apply());
  return result;
}

class FooFactory<T> implements Factory<Foo<T>> {
  public Foo<T> apply() {
    return new Foo<T>();
  }
}

List<Foo<Integer>> foos = make10(new FooFactory<Integer>());
8
ответ дан 22 November 2019 в 21:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: