Как изменить значение приватного финального поля?
Стоит сразу сказать, это очень плохая практика. Такое изменение грубо нарушает принципы сокрытия данных, и потенциально ломает инвариантность состояния объекта.
Для этого трюка необходимо прибегнуть к использованию Reflection API.
Сначала получим дескриптор поля – экземпляр класса Field. У объекта метаклассаClass<X> интересующего нас класса вызовем метод getDeclaredField(). Просто getField() не сработает, потому что он работает только с публичными полями. Параметром передается строка с именем поля.
Полученного экземпляра Field уже достаточно для доступа к изменяемым приватным полям. Перед обращением требуется сделать его доступным, вызвав setAccessible(true).
Сам доступ осуществляется методами get*() и set*(). Так как Field представляет дескриптор поля класса, без привязки к конкретному экземпляру класса, экземпляр передается параметром в методы доступа. Для статического поля передается null.
Чтобы побороть неизменяемость финального поля, нужно снять его модификатор final. Все модификаторы поля хранятся в поле modifiersдескриптора. То есть, нужно также с помощью рефлекшена сделать доступным и обновить поле уже объекта Field.
Поле modifiers хранит модификаторы в виде битовой маски. Для изменения придется прибегнуть к битовым операторам.
Полный код установки значения 42 в поле myField объекта myObject выглядит так:
Field field = myObject.class.getDeclaredField( "myField" );
field.setAccessible( true );
Field modifiersField = Field.class.getDeclaredField( "modifiers" );
modifiersField.setAccessible( true );
modifiersField.setInt( field, field.getModifiers() & ~Modifier.FINAL );
field.setInt(myObject, 42);
#Классы