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,

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