Общий метод для получения экземпляра из параметра класса

У меня есть общий класс с подклассами:

class Item<T>
{
     //
}

class IntItem extends Item<Integer>
{
    //
}

Мне нужен метод для получения экземпляра Item из его класса. Я пробовал такие методы, как:

<T extends Item<T>> T getItem(Class<T> itemClass)
{
  return ...
}


<T> Item<T> getItem(Class<Item<T>> itemClass)
{
    return ...
}

Но это не работает:

// Does not compile: "inference variable T has incompatible equality constraints Integer,IntItem"
IntItem ii = getItem(IntItem.class); 

Каков правильный способ сделать это?

РЕДАКТИРОВАТЬ после кардинального ответа системы

Обратите внимание, что вопрос касается только сигнатур дженериков/методов.

Тот же вопрос, но с передачей экземпляра элемента в качестве параметра:

IntItem ii = getItem2(anIntItem); 

static <T extends Item<E>,E> T getItem(Class<T> itemClass)
{
    return ...
}

static <T extends Item<E>,E> T getItem2(T item)
{ 
     // Does not compile: "error: incompatible types: Item cannot be converted to T"
     return getItem(item.getClass();
}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, вашему методу getItem нужен отдельный общий параметр для установки в вашем параметре Item (я собираюсь использовать E). Во-вторых, просто используйте Class#newInstance:

public static <T extends Item<E>, E> T getItem(Class<T> itemType)
        throws InstantiationException, IllegalAccessException {
    return itemType.newInstance();
}

Вы также можете полностью опустить часть extends Item<?>. Хотя это позволит методу создавать экземпляры других типов, он по-прежнему будет отлично работать для типов Item.

Если в будущем вы захотите добавить параметры в свои конструкторы элементов, вы можете использовать Class#getConstructor(Class<?>...) или Class#getConstructors(), чтобы найти конструктор, который вы хотите использовать, затем Constructor#newInstance(Object...) для создания вашего экземпляра. Вот два примера:

// This example does NOT work with null arguments
public static <T> T getItem(Class<T> itemType, Object... arguments)
        throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException,
        IllegalArgumentException, InvocationTargetException {
    Class<?>[] parameterTypes = Arrays.stream(arguments).map(Object::getClass).toArray(Class[]::new);
    return getItem(itemType, parameterTypes, arguments);
}

// This example works with null arguments
public static <T> T getItem(Class<T> itemType, Class<?>[] parameterTypes, Object[] arguments)
        throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException,
        IllegalArgumentException, InvocationTargetException {
    Constructor<T> constructor = itemType.getConstructor(parameterTypes);
    return constructor.newInstance(arguments);
}

Ваше "во-первых" решает мою проблему, вы получите ответ. Но я понимаю, что есть побочная проблема, я обновлю свой вопрос.

jjazzboss 31.03.2023 22:50

Другие вопросы по теме