Как получить класс продюсера для создания картыРезультаты? - PullRequest
0 голосов
/ 19 июня 2019

У меня есть класс QueryResults с методом, объявленным так, который выдает результаты в одной из многих возможных форм:

public <T> List<T> allRowsAs(Class<T> target)

Я хотел бы получить результаты в виде списка картэкземпляров.Это должно быть возможно.

Кажется, что это должно работать, но даже не скомпилируется:

QueryResult result = ...
List<Map<String, Object>> results = result.allRowsAs(Map<String,Object>.class);

Ответы [ 3 ]

1 голос
/ 19 июня 2019

Передача Map.class в allRowsAs может работать или не работать, в зависимости от того, насколько умным является allRowsAs.

Возможно, что функция использует отражение для перечисления членов / свойств класса, который вы передаете, создания экземпляра класса для каждой строки с помощью Class.newInstance, а затем для заполнения каждого экземпляра из результатов. В этом случае он с треском провалится с Map, потому что, во-первых, у Map нет свойств, которые можно заполнить с помощью отражения, а во-вторых, Map - это интерфейс, а не класс, для которого можно создать экземпляр.

Таким образом, функция должна иметь специальный регистр для Map и предполагать, что вы хотите HashMap<String, Object>, а не что-то еще. Скорее всего, если класс QueryResult поддерживает это, это отдельная функция, например allRowsAsMaps или что-то в этом роде.

Вы также можете найти способ вернуть строки в виде объекта JSON (GSON или Джексон или что-то еще). Похоже, это действительно то, что вы хотите.

0 голосов
/ 19 июня 2019

У дженериков есть свои ограничения. Смотрите там: Ограничения на Дженерики

Используйте это вместо:

public List<Map<String, Object>> allRowsAsMapList(){}
0 голосов
/ 19 июня 2019

Map<String,Object>.class не является допустимой ссылкой на класс, потому что
Классы с суффиксом (<..>) не являются допустимыми переменными класса.
Вы можете сделать это:

result.allRowsAs(Map.class);

И вы также должны определить allRowsAs(), чтобы вернуть List<? extends T>:

public <T> List<? extends T> allRowsAs(Class<T> target){...}

Но это приведет к необработанному предупреждению типа, так как Map является универсальным классом, и вы также должны добавить непроверенное приведение к List<Map<String, Object>>, например:

List<Map<String, Object>> results = (List<Map<String, Object>>) result.allRowsAs(Map.class);

Это определенно не тот способ следовать: непроверенное приведение, очень подробный код на стороне клиента.

В качестве альтернативы вы можете определить метод, специфичный для этого требования:

public <T, U> List<Map<T, U>> allRowsAsMap() {

   // use the map that has rows
   Map<String, Integer> map = ...;
   // cast it to Map<T,U> : not safe but not choice in these conditions
   list.add((Map<T, U>) map);
}

И вы можете использовать его:

List<Map<String, Integer>> list = allRowsAsMap();

Но таким образом, как и в вашем исходном коде, я думаю, что вы не используете дженерики, как следует.
Дженерики разработаны так, чтобы предлагать универсальность и тип безопасности .
Здесь вам не нужна безопасность типов, и универсальность в некотором роде побеждена, так как вы не знаете, чем на самом деле манипулируете.
В вашем случае вам, вероятно, не следует использовать универсальный метод scoped, а использовать универсальные типы с заранее известными типами параметров:

public  List<Map<String, Integer>> allRowsAsMap() {...}

Это менее "сексуально", но более надёжно: нет актерского состава, и вы знаете, чем манипулируете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...