#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.