Spec-Zone .ru
спецификации, руководства, описания, API
|
Вот несколько типичных проблем, с которыми встречаются разработчики с объяснениями того, почему происходить и как разрешить их.
пример генерирует FieldTrouble
IllegalArgumentException
. Field.setInt()
Integer
со значением типа примитива. В неотражательном эквиваленте Integer val = 42
, компилятор преобразовал бы (или поле) тип примитива 42
к ссылочному типу как new Integer(42)
так, чтобы его проверка типа приняла оператор. При использовании отражения введите проверку, только происходит во времени выполнения, таким образом, нет никакой возможности к полю значения.
import java.lang.reflect.Field; public class FieldTrouble { public Integer val; public static void main(String... args) { FieldTrouble ft = new FieldTrouble(); try { Class<?> c = ft.getClass(); Field f = c.getDeclaredField("val"); f.setInt(ft, 42); // IllegalArgumentException // production code should handle these exceptions more gracefully } catch (NoSuchFieldException x) { x.printStackTrace(); } catch (IllegalAccessException x) { x.printStackTrace(); } } }
$ java FieldTrouble Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.Object field FieldTrouble.val to (long)42 at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException (UnsafeFieldAccessorImpl.java:146) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException (UnsafeFieldAccessorImpl.java:174) at sun.reflect.UnsafeObjectFieldAccessorImpl.setLong (UnsafeObjectFieldAccessorImpl.java:102) at java.lang.reflect.Field.setLong(Field.java:831) at FieldTrouble.main(FieldTrouble.java:11)
Чтобы устранить это исключение, проблематичная строка должна быть заменена следующим вызовом Field.set(Object obj, Object value)
f.set(ft, new Integer(43));
Class.isAssignableFrom()
isAssignableFrom()
возвратится false
в этом тесте, который может использоваться программно, чтобы проверить, возможно ли определенное преобразование: Integer.class.isAssignableFrom(int.class) == false
Точно так же автоматическое преобразование от примитивного до ссылочного типа также невозможно в отражении.
int.class.isAssignableFrom(Integer.class) == false
Проницательный читатель может заметить это если
пример, показанный ранее, используется, чтобы получить информацию о непубличном поле, это перестанет работать:FieldSpy
$ java FieldSpy java.lang.String count java.lang.NoSuchFieldException: count at java.lang.Class.getField(Class.java:1519) at FieldSpy.main(FieldSpy.java:12)
Class.getField()
и Class.getFields()
Class
объект. Получать все объявленные поля (но не наследованный) в Class
, используйте Class.getDeclaredFields()
IllegalAccessException
private
или иначе недоступное поле или установить значение a final
поле (независимо от его модификаторов доступа).
пример иллюстрирует тип трассировки стека, которая следует из попытки установить заключительное поле.FieldTroubleToo
import java.lang.reflect.Field; public class FieldTroubleToo { public final boolean b = true; public static void main(String... args) { FieldTroubleToo ft = new FieldTroubleToo(); try { Class<?> c = ft.getClass(); Field f = c.getDeclaredField("b"); // f.setAccessible(true); // solution f.setBoolean(ft, Boolean.FALSE); // IllegalAccessException // production code should handle these exceptions more gracefully } catch (NoSuchFieldException x) { x.printStackTrace(); } catch (IllegalArgumentException x) { x.printStackTrace(); } catch (IllegalAccessException x) { x.printStackTrace(); } } }
$ java FieldTroubleToo java.lang.IllegalAccessException: Can not set final boolean field FieldTroubleToo.b to (boolean)false at sun.reflect.UnsafeFieldAccessorImpl. throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:55) at sun.reflect.UnsafeFieldAccessorImpl. throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:63) at sun.reflect.UnsafeQualifiedBooleanFieldAccessorImpl.setBoolean (UnsafeQualifiedBooleanFieldAccessorImpl.java:78) at java.lang.reflect.Field.setBoolean(Field.java:686) at FieldTroubleToo.main(FieldTroubleToo.java:12)
final
поля от того, чтобы быть установленным после инициализации class. Однако, Field
как объявляют, расширяется AccessibleObject
который обеспечивает возможность подавить эту проверку.AccessibleObject.setAccessible()
AccessibleObject.setAccessible()