As other posters have indicated, setAccessible
is only applicable to that instance of your java.lang.reflect.Field
, so setting the accessibility back to its original state is not needed.
However...
If you want your calls to field.setAccessible(true)
to be persistent you need to use underlying methods in java.lang.Class
and java.lang.reflect.Field
. The public facing methods send you copies of the Field
instance, so it "forgets" after each time you do something like class.getField(name)
import java.lang.reflect.*;
import sun.reflect.FieldAccessor;
public class Reflect {
private static Method privateGetDeclaredFields;
private static Method getFieldAccessor;
public static Field[] fields(Class<?> clazz) throws Exception {
return (Field[]) privateGetDeclaredFields.invoke(clazz, false);
}
public static <T> T get(Object instance, Field field) throws Exception {
return ((FieldAccessor) getFieldAccessor.invoke(field, instance)).get(instance);
}
public static void set(Object instance, Field field, Object value) throws Exception {
((FieldAccessor) getFieldAccessor.invoke(field, instance)).set(instance, value);
}
static {
try {
// These are used to access the direct Field instances instead of the copies you normally get through #getDeclaredFields.
privateGetDeclaredFields = Class.class.getDeclaredMethod("privateGetDeclaredFields", boolean.class);
privateGetDeclaredFields.setAccessible(true);
getFieldAccessor = Field.class.getDeclaredMethod("getFieldAccessor", Object.class);
getFieldAccessor.setAccessible(true);
} catch (Exception e) {
// Should only occur if the internals change.
e.printStackTrace();
}
}
}
Update: This implementation is for Java 8, future versions change the backend which breaks this. The same concept still applies though should you really wish to continue this strategy.