Отражение не полностью реализовано в Android 2.2?

#android #reflection

#Android #отражение

Вопрос:

У меня есть некоторый код, который отлично работает в 2.3 и выше. Однако в 2.2 я получаю исключение NullPointerException при присвоении className:

 if(field.getType() == java.util.ArrayList.class)
   className = ((ParameterizedType)field.getGenericType()).toString();
  

Редактировать

Я немного покопался в документах Android и обнаружил, что некоторые методы недоступны до 9 уровня API. Однако утверждается, что GetType(), getGenericType() и ParameterizedType поддерживаются на уровне API 1. Так почему же этот код не работает?

Полевые документы:http://developer.android.com/reference/java/lang/reflect/Field.html

Документы ParameterizedType:http://developer.android.com/reference/java/lang/reflect/ParameterizedType.html

Редактировать

Я обнаружил, что вызов field.getGenericType() не приводит к сбою программы, но молча выдает исключение com.sun.jdi.InvocationException. Похоже, что тип, возвращаемый вызовом getGenericType(), недействителен? Опять же, это работает на 2.3 и выше, но почему это исключение выдается и перехватывается на 2.2 и ниже?

Комментарии:

1. Нам было бы проще, если бы вы сообщили нам, какой объект / вызов вызывает NPE.

2. @WarrenFaith В строке, где classname = …

3. и какой вызов / объект в этой строке? Может быть, field это значение равно null или getGenericType() возвращает null, так что приведение и toString() выдает NPE. Будьте как можно конкретнее, пожалуйста.

4. @WarrenFaith Я обновил вопрос. однако поле никогда не было нулевым.

Ответ №1:

Это известная проблема, вот запрос в системе отслеживания ошибок Android: Проблема 6636: NPE в org.apache.harmony.luni.lang.reflect.ListOfTypes

Это было исправлено в Android 2.3, но не было перенесено в более ранние версии Android, поэтому вы видите сбой в Android 2.2.

Чтобы быть более подробным: если вы запустите этот код (расширенную версию вашего собственного кода) на Android 2.2 :

 public class ReproduceBugActivity extends Activity {
  private static final String TAG = "ReproduceBugActivity";
  private ArrayList<Object> mArrayList;

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    try {
      String className = null;
      Field field = getClass().getDeclaredField("mArrayList");
      if (field.getType() == java.util.ArrayList.class)
        className = ((ParameterizedType)field.getGenericType()).toString();
      Log.i(TAG, "className = "   className);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
  

Вы получите это исключение:

 java.lang.NullPointerException
   at org.apache.harmony.luni.lang.reflect.ListOfTypes.length(ListOfTypes.java:47)
   at org.apache.harmony.luni.lang.reflect.ImplForType.toString(ImplForType.java:83)
   at com.reproducebug.ReproduceBugActivity.onCreate(ReproduceBugActivity.java:23)
  

из-за вышеупомянутой ошибки в реализации отражения Java. На Android 2.3 ошибка была исправлена, и вместо этого вы увидите это в logcat:

 I/ReproduceBugActivity(23449): className = java.util.ArrayList<java.lang.Object>
  

com.sun.jdi.InvocationException Исключение, которое вы видите, не связано с этим, насколько я могу судить.

Комментарии:

1. Попробуйте вставить эту строку в свой код: Введите type = field.getGenericType(); . Когда я навожу на него курсор во время отладки, переменной rawType в type присваивается значение null, но, похоже, у нее правильное имя rawType. Однако в нем говорится, что метод вызвал исключение com.sun.jdi.InvocationException. Я думаю, что NPE происходит из метода toString (), вызываемого для объекта. Кроме того, ошибка, на которую вы ссылались, была довольно расплывчатой, и я мало что понял из нее. Я предполагаю, что это не будет исправлено ни в какой момент, но мне все еще интересно, почему это нельзя исправить или нет обходного пути.

2. Я попробовал то, что вы предложили, и теперь я вижу, что вы имеете в виду под «com.sun.jdi.InvocationException». Это просто способ Eclipse сказать «Я не смог вызвать toString () для объекта, на который вы наводите курсор, потому что я получаю NPE». Сообщение об ошибке, на которое я ссылался, было в основном для справки. В качестве обхода ошибки вы могли бы попытаться избежать использования обобщений для полей, в которых вы используете отражение, потому что тогда Type.toString() не приведет к сбою. Вы также могли бы попытаться избежать Type.toString() .

3. Хороший материал. Вероятно, лучший ответ, который я собираюсь получить. Действительно хотелось бы, чтобы ответы на подобные ошибки было легче получить, или, по крайней мере, они были бы прокомментированы в документах SDK.