Я вынужден использовать метод интерфейса с подписью, которую я не могу изменить:
List parse(String path, Class clazz)
Предполагается вернуть список объектов с типом, переданным в параметре clazz
, например:
List<TagsRun> runs = reader.parse(path, TagsRun.class)
Мне нужно реализовать парсер JSON, и вопрос в том, как установить тип параметра clazz
в список результатов?
Я использую Gson, и это может быть что-то вроде:
List parse(String path, Class clazz) {
Type collectionType = new TypeToken<List<TagsRun>>(){}.getType();
List<TagsRun> myList = new Gson.fromJson(json, collectionType);
return myList
}
Но как здесь заменить конкретный Список <TagsRun> на Список <тип clazz>?
Единственное рабочее решение, которое я сделал, требует изменения сигнатуры метода:
<T> List<T> parse(String path, Class<T[]> clazz ) {
T[] arr = new Gson().fromJson(new File(path).text(), clazz);
return Arrays.asList(arr);
}
Другими словами, как вернуть список объектов, имеющих тот же тип, что и аргумент clazz
, используя сигнатуру:
List parse(String path, Class clazz)
Заранее спасибо.
Может список преобразовать?
List<TagsRun> myList = new Gson.fromJson(json, collectionType);
List<Clazz> = Arrays.asList(myList.toArray(new Clazz[0]));
Редактировать: Думаю, это может вам помочь: https://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#checkedCollection(java.util.Collection,%20java.lang.Class) - Прокрутите вниз до раздела Список, если вы этого не заметили
какой тип новый Gson.fromJson (json, collectionType); возвращаясь в свой код? Тип объекта может быть решением, преобразовав его позже на другом этапе ?!
либо я ошибаюсь, но не могли бы вы просто выполнить List <clazz.getClass ()> ...
Нет, я не могу. Поскольку общие списки существуют только во время компиляции, а не во время выполнения. Таким образом, невозможно параметризовать список во время выполнения.
Поскольку вы не можете изменить подпись метода, нет смысла возвращать список с параметром типа.
public List foo() {
ArrayList<String> strings = new ArrayList<>();
return strings;
}
public void methodUsingFoo() {
// possible but you should check if the assumption is correct:
List<String> uncheckedAssignment = foo(); // so don't do this
// this is what foo *will* return:
List actualResult = foo();
}
Вместо этого вы можете сделать что-то вроде этого:
public void methodUsingParse() {
Class clazz = Object.class; // or whatever class you want or need
// this is what your method *will* return:
List actualResult = parse("/path/to/somewhere", clazz);
// best way would be to check each element:
for(Object element : actualResult) {
if (clazz.equals(element.getClass())) {
// do your stuff here
}
}
}
Что я забыл: Я не думаю, что это вообще возможно сделать так, как вам хотелось бы.
Решил, наконец:
@Override
List parse(String path, Class clazz) {
List result = []
JsonArray jsonArray = new JsonParser()
.parse(new File(path).getText(CHARSET))
.getAsJsonArray()
Gson gson = new Gson()
jsonArray.each {
result.add(gson.fromJson(it, clazz))
}
return result
}
Хитрость заключается в том, чтобы сначала получить массив, а затем использовать gson.fromJson(it, clazz)
для каждого элемента массива. Это преобразует каждый элемент json в массиве в POJO, а затем добавит его в список результатов.
Проблема в том, что у меня в методе нет типа ТегиЗапуск. У меня только Класс и не могу установить тип List во время выполнения.