2014-11-25 4 views
1

Я пытаюсь заменить какой-то старый код более общим подходом, поэтому я попытался использовать 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; 
     } 
+4

Это не будет делать то, что вы ожидаете от этого. Аргумент типа должен быть именем типа. 'c' - переменная. –

+2

'c.getClass(). ToString()' должен btw оценивать '' класс java.lang.Class '' каждый раз. c уже является объектом класса, а 'c.toString()' будет печатать это уже, это класс, и каждый последующий класс будет просто печатать то же самое. – zapl

+0

Хороший улов, @zapl. Лукас: 'c.getSimpleName()', вероятно, больше того, что вы собираетесь с этим битом. –

ответ

4

Это сложный вопрос, сжато, чтобы быть честным, потому что (конструктивно и объективно) вы пропустили некоторые из фундаментальных понятий о том, как дженериков работы.

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 по мере необходимости в рамках метода.

Надеюсь, этого достаточно, чтобы вдохновить вас двигаться в правильном направлении.

+0

Большое спасибо, это ответ на мой вопрос. Я попробовал это аналогично раньше, но я пропустил после статики, которая закончилась ошибкой компилятора. – Lukas

+0

@ Lukas Рад, что это помогло; Возможно, я сконфигурировал цель вашего параметра 'Type' с моим параметром' Class 'в примере, но, надеюсь, вы получите эту идею. Если вы ссылались на 'java.lang.reflect.Type', там, к сожалению, вы действительно не можете сделать с интерфейсом' Type'; «Класс» - это то, что вы хотите придерживаться. В стороне, в некоторых конкретных случаях, вы можете видеть массивы, используемые для аналогичных целей, например. ['ArrayList.toArray'] (https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#toArray (T [])) (примечание без параметров не может возвращать только' Object [] '). –

Смежные вопросы