Подтвердить что ты не робот

Как получить тип значения карты в Java?

Возможный дубликат:
Получить общий тип java.util.List

У меня есть карта, и я хочу получить тип T из экземпляра этой Карты. Как я могу это сделать?

например. Я хочу сделать что-то вроде:

Map<String, Double> map = new HashMap<String, Double>();
...
String vtype = map.getValueType().getClass().getName(); //I want to get Double here

Конечно, в API нет такой функции getValueType().

4b9b3361

Ответ 1

Вы не можете получить его из экземпляра, потому что в генераторах Java параметр типа доступен только во время компиляции, а не во время выполнения.

Это называется стиранием типа. Более формальное определение предоставляется в JLS.

Ответ 2

Если ваш Map является объявленным полем, вы можете сделать следующее:

import java.lang.reflect.*;
import java.util.*;

public class Generic {
    private Map<String, Number> map = new HashMap<String, Number>();

    public static void main(String[] args) {
        try {
            ParameterizedType pt = (ParameterizedType)Generic.class.getDeclaredField("map").getGenericType();
            for(Type type : pt.getActualTypeArguments()) {
                System.out.println(type.toString());
            }
        } catch(NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

Вышеприведенный код напечатает:

class java.lang.String
class java.lang.Number

Однако, если вы просто имеете экземпляр Map, например. если он передан методу, вы не можете получить информацию в это время:

public static void getType(Map<String, Number> erased) {
    // cannot get the generic type information directly off the "erased" parameter here
}

Вы можете захватить подпись метода (опять же, используя отражение, как в моем примере выше), чтобы определить тип erased, но это никуда не денется (см. ниже).

Edit:

Следует отметить комментарии BalusC ниже. Вам действительно не нужно это делать; вы уже объявили тип карты, поэтому вы не получаете больше информации, чем у вас уже есть. См. Его ответ здесь.

Ответ 3

Хотя были даны правильные ответы, есть еще одна альтернатива, которая еще не указана. В основном поля и методы - это не единственные места, где может существовать общая информация типа: объявление суперкласса также содержит эту информацию.

Это означает, что если ваша Карта фактически является подтипом типа:

class MyStringMap extends HashMap<String,String> { }

тогда можно определить общие параметры типа, которые были использованы, вызвав "getGenericSuperclass" (на "instance.getClass()" ), а затем обратившись к назначенным фактическим параметрам типа. Он действительно задействован, так как нужно перемещаться по иерархии типов, чтобы обеспечить правильную привязку параметров к Map (может быть aliased и т.д.), Но это можно сделать. И именно так "супер токен" используется для передачи общего объявления типа:

  new TypeToken<Map<String, Double>>() { }

который используется многими фреймворками Java (Jersey, Guice, Jackson и многие другие)

Проблема заключается в том, что, хотя это позволяет определить номинальные типы экземпляра, оно работает только в том случае, если существует фактический не общий подкласс универсального типа, и я не знаю, как обеспечить выполнение этого требования (вызов код может показаться странным, что для этой цели он должен создать несколько поддельный Подкласс класса).