Ответ 1
Что касается вашего первого вопроса, рассмотрите объявление поля, например
public List<String> parameterizedField;
JVM не поддерживает объект, представляющий тип List<String>
(как и объект Class
). Поэтому необходимо создать новый объект Type
(ParameterizedType
в данном случае), представляющий этот тип и возвращающий его (он также может кэшировать его для будущего использования). Он будет делать то же самое для
public E genericField;
создание объекта TypeVariable
в этом случае.
Для
public String regularTypeField;
однако тип известен, JVM поддерживает объект Class
для String
и поэтому ему нужно только вернуть его.
Во втором случае, тип токена hack
new TypeToken<List<String>>() {}
внутренне создает Type
, который представляет List<String>
, который в противном случае невозможно было бы получить непосредственно из-за стирания типа.
Вызов resolveType
проверяет Type
, который вы ему даете, и разрешает его на основе аргумента типа TypeToken
.
В вашем примере вызываемый getGenericReturnType()
возвращает Type
, представляющий переменную типа, объявленную в классе List
. Поскольку вы параметризовали List
с помощью String
, resolveType()
вернет String
. Он связывает аргумент типа, указанный вами в маркете типа, с его соответствующей переменной типа, используемой в методах или полях.
Если вы использовали
new TypeToken<List<String>>() {}.
resolveType(Iterator.class.getMethod("next").getGenericReturnType())
он вернул бы E
, потому что эта переменная типа не связана с той, которую вы привязали в маркере типа.
Использование разрешенных в обоих случаях разных.