Можно ли изменить окончательную переменную пакета посредством отражения?
Скажем, у меня это:
public class Widget {
final int val = 23;
}
Можно ли изменить значение val через отражение, если оно станет доступным?
Если это так, можно ли предотвратить это, не используя диспетчера безопасности?
Оказывается, изменение конечных членов приводит к тому, что полученные от отражения значения отличаются от значений, возвращаемых обычным кодом! Это довольно страшно.
import java.lang.reflect.Field;
public class Test {
private static final class Widget {
private final int val = 23;
public int getVal() {
return val;
}
}
public static void main(String[] args) throws Exception {
Widget w = new Widget ();
Field m = Widget.class.getDeclaredField("val");
m.setAccessible(true);
m.set(w, 233);
Field m1 = Widget.class.getDeclaredField("val");
m1.setAccessible(true);
System.out.println(m.get(w)); /// PRINT 233
System.out.println(w.getVal()); /// PRINT 23
System.out.println(m1.get(w)); /// PRINT 233
}
}
ДА. Попробуйте этот код:
public static void main(String[] args) throws Exception {
Widget w = new Widget ();
Field m = Widget.class.getDeclaredField("val");
m.setAccessible(true);
m.set(w, 233);
System.out.println(m.get(w)); /// PRINT 233
}
System.out.println(w.val);
показывает 23
, а не 233
. Так что, если вы не делаете доступ через отражение ...
Попробуй это.
Widget() {
checkPerMission();
}
private void checkPerMission() {
Class self = sun.reflect.Reflection.getCallerClass(1);
Class caller = sun.reflect.Reflection.getCallerClass(3);
if (self != caller) {
throw new java.lang.IllegalAccessError();
}
}