TypeReference<Map <String, String >> () {}
Несколько дней назад я начал работать над проектом веб-сервиса. Этот проект использует Джексона для маршалинга и демаршаллинга объектов JSON. Итак, мой вопрос:
Почему всегда я должен поставить {}
когда я создаю экземпляр TypeReference
? Я знаю, что конструктор protected
, но почему protected
? Я думаю, что это как хак, чтобы сделать видимым конструктор, создающий реализацию конструктора, так как TypeReference
является abstract
и ты можешь сделать это. Но какой в этом смысл?
String jsonString = "{\" firstName\":\"John\",\"lastName\":\"Chen\"}";
ObjectMapper objectMapper = new ObjectMapper();
// properties will store name and value pairs read from jsonString
Map<String, String> properties = objectMapper.readvalue(
jsonString, new TypeReference<Map<String, String>>()
{ //
});
1 ответ
TL;DR
С помощью подклассов возможно TypeReference
извлечь фактический параметр универсального типа. Например:
TypeReference<String> ref = new TypeReference<String>(){};
System.out.println(ref.getType());
Печать:
class java.lang.String
Это может быть полезно, когда вы не можете использовать обычные классы. Например, когда это не работает:
// doesn't work
Type type = ArrayList<String>.class;
Вы все еще можете получить этот класс с помощью TypeReference
:
// will yield Class<ArrayList<String>>>
Type type = new TypeReference<ArrayList<String>>(){}.getType();
детализированный
При взгляде на исходный код TypeReference
(используя Jackson 2.8.5) вы можете видеть, что тело конструктора содержит следующие строки:
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof Class<?>) { // sanity check, should never happen
throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
}
_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
Интересные строки - первые и последние. Давайте внимательнее посмотрим на первую строку:
Type superClass = getClass().getGenericSuperclass();
Например, когда вы создаете подкласс, используя анонимный класс:
TypeReference<SomeStype> ref = new TypeReference<SomeType>(){};
затем getClass
возвращает текущий Class
объект (анонимный класс) и getGenericSuperclass()
вернет Class
объект из class
текущая реализация простирается от, в нашем случае, superClass
будет равно Class<TypeReference<?>>
,
Нет при просмотре последней строки из тела конструктора:
_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
Как мы знаем, что superClass
это Class
объект для TypeReference<?>
мы знаем, что он имеет общий параметр. Отсюда приведение к ParameterizedType
, Это указано Type
имеет метод getActualyTypeArguments()
который возвращает массив всех общих параметров, указанных этим классом. В нашем случае это просто 1. Так [0]
даст первый элемент. В примере мы получим фактически указанный параметр типа SomeType
,