Я пытаюсь заменить какой-то старый код более общим подходом, поэтому я попытался использовать generics. К сожалению, до сих пор я не работал. Я должен динамически загружать хэш-карту объектов из строки json. Но до сих пор я не работал, поскольку строка 4
HashMap<String,c> hm = new HashMap<String,c>();
говорит "Неизвестный класс c". Что я делаю не так?
public static HashMap<String,?> getEntries(Context context, Type t)
{
Class c = t.getClass();
HashMap<String,c> hm = new HashMap<String,c>();
try
{
File fl = new File(context.getCacheDir(),c.getClass().toString() + ".json");
FileInputStream fin = new FileInputStream(fl);
BufferedReader reader = new BufferedReader(new InputStreamReader(fin));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
fin.close();
hm = new Gson().fromJson(sb.toString(), t);
}catch(Exception i)
{
}
return hm;
}
Это трудный вопрос, чтобы ответить кратко, честно говоря, потому что (конструктивно и объективно) вам не хватает некоторых фундаментальных концепций работы дженериков.
c
- экземпляр Class
который является Object
как и все остальное. Параметры типового типа должны быть типами, а не объектами. Если вы хотите установить ограничения на свой тип HashMap
вам придется выражать эти ограничения в виде общих параметров типа. Например:
public static <T> HashMap<String,T> getEntries (Context context, Type type) {
HashMap<String,T> hm = new HashMap<String,T>();
...
}
Однако, поскольку нет способа вывести тип T
из любого из параметров, Class
T
не всегда доступен в рамках метода. Типичным подходом является добавление некоторого полезного параметра, который также может ограничивать тип, например:
public static <T> HashMap<String,T> getEntries (Context context, Type type, Class<T> clazz) {
HashMap<String,T> hm = new HashMap<String,T>();
...
}
С этим вы можете позвонить следующим образом:
HashMap<String,String> entries = getEntries(context, type, String.class);
И вы также можете использовать clazz
мере необходимости в методе.
Надеюсь, этого достаточно, чтобы вдохновить вас двигаться в правильном направлении.
Type
с моим параметром Class<T>
в примере, но, надеюсь, вы поняли идею. Если вы имели в виду java.lang.reflect.Type
, к сожалению, с интерфейсом Type
вы мало что можете сделать; Class
как правило, то, что вы хотите придерживаться. Кроме того, в некоторых конкретных случаях вы можете увидеть массивы, используемые для аналогичных целей, например, ArrayList.toArray
(обратите внимание, что безпараметрическая версия может возвращать только Object[]
).
c
является переменной.c.getClass().toString()
следует, между прочим, каждый раз оценивать как"class java.lang.Class"
. c уже является объектомClass
иc.toString()
напечатает это, это класс, и каждый последующий класс просто напечатает его.