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

Верните экземпляр класса с его общим типом

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

public abstract class AbstractHandler<T> {

    ...
    public abstract Class<T> handledType();
}

Тогда у меня есть эта реализация:

public class ConcreteHandler extends AbstractHandler<Map<String, List<Thing>>> {

    @Override
    public Class<Map<String, List<Thing>>> handledType() {
        //what do I return here?!
    }
}

Я не могу вернуть Map<String, List<Thing>>.class, так как это даже не действует синтаксически. Я попытался сделать общий тип параметра в подтипе HashMap<String, List<Thing>>, а затем возвратить new HashMap<String, List<Thing>>().getClass(), но это не работает, потому что тип возврата Class<T>#getClass() равен Class<? extends T>. Я посмотрел на TypeToken из Guava, а метод getRawType выглядел многообещающим, но он возвращает Class<? super T>.

У меня есть обходное решение, которое выглядит так:

public class ThingListMap {
    private Map<String, List<Thing>> thingListMap;

    ...
}

и я просто использую ThingListMap как общий тип-параметр.

Другим возможным обходным путем является выполнение принудительного ввода:

public Class<Map<String, List<Thing>>> handledType() {
    return (Class<Map<String, List<Thing>>>) new HashMap<String, List<Thing>>().getClass();
}

Есть ли более элегантный способ сделать это?

EDIT: В ответ на один из ответов я не могу изменить подпись метода handledType, так как я не владею или не управляю его источником.

4b9b3361

Ответ 1

По какой-то причине Java не позволяет использовать Map.class непосредственно для Class<Map<String, List<Thing>>>. В любом случае, это непроверенный бросок.

Но легально перевести его дважды, сначала на Class<?>, затем на Class<Map<String, List<Thing>>>.

return (Class<Map<String, List<Thing>>>) (Class<?>) Map.class;

Будучи непроверенным, вы можете добавить @SuppressWarnings("unchecked").

Ответ 2

Гува подход к этому заключается в использовании TypeToken. Ваш класс станет

public abstract class AbstractHandler<T> {
    public TypeToken<T> handledType();
}

public class ConcreteHandler extends AbstractHandler<Map<String, List<Thing>>> {
    @Override
    public TypeToken<Map<String, List<Thing>>> handledType() {
        return new TypeToken<Map<String, List<Thing>>>() {};
    }
}