Якщо ні, що SecurityManagerце не заважає вам це робити, ви можете використовувати, setAccessibleщоб обійти privateта скинути модифікатор, щоб позбутися finalта фактично змінити private static finalполе.
Ось приклад:
import java.lang.reflect.*;
public class EverythingIsTrue {
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
public static void main(String args[]) throws Exception {
setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"
}
}
Якщо припустимо, що "не SecurityExceptionкинуто", наведений вище код друкується "Everything is true".
Тут насправді зроблено наступне:
- Примітивні
booleanзначення trueі falseв mainвводяться в автоматичне позначення типу Boolean"константи" Boolean.TRUEтаBoolean.FALSE
- Рефлексія використовується для зміни
public static final Boolean.FALSEпозначення, на яке BooleanпосилаєтьсяBoolean.TRUE
- Як наслідок, згодом щоразу, коли a автоматично
falseзавантажується Boolean.FALSE, воно посилається на те саме, що Booleanі те , на яке посилаєтьсяBoolean.TRUE
- Все, що було
"false"зараз, є"true"
Пов'язані питання
Коваджі
Ви повинні бути дуже обережними, коли ви робите щось подібне. Він може не працювати, тому що SecurityManagerможе бути присутнім, але навіть якщо він не працює, залежно від схеми використання, він може працювати, а може і не працювати.
JLS 17.5.3 Подальші зміни остаточних полів
У деяких випадках, таких як десеріалізація, системі потрібно буде змінити finalполя об’єкта після побудови. finalполя можуть бути змінені за допомогою відображення та інших засобів, що залежать від реалізації. Єдиний зразок, в якому це має розумну семантику, - це той, в якому будується об’єкт і потім finalоновлюються поля об’єкта. Об'єкт не повинен бути видимим для інших потоків, а також finalполя читання, поки не будуть завершені всі оновлення finalполів об’єкта. Замороження finalполя відбуваються як в кінці конструктора, в якому встановлено finalполе, так і відразу після кожної модифікації finalполя за допомогою відображення або іншого спеціального механізму.
Вже тоді є ряд ускладнень. Якщо finalполе ініціалізується до константи часу компіляції в декларації поля, зміни в finalполі можуть не спостерігатися, оскільки використання цього finalполя замінюються під час компіляції на постійну часу компіляції.
Ще одна проблема полягає в тому, що специфікація дозволяє агресивно оптимізувати finalполя. У межах потоку допустимо впорядкувати зчитування finalполя з тими модифікаціями остаточного поля, які не відбуваються в конструкторі.
Дивись також
- JLS 15.28 Постійна експресія
- Малоймовірно, що ця методика працює з примітивом
private static final boolean, тому що вона невід'ємна як константа часу компіляції, і, отже, "нове" значення може не спостерігатися
Додаток: Про побітну маніпуляцію
По суті,
field.getModifiers() & ~Modifier.FINAL
вимикає біт , відповідний Modifier.FINALз field.getModifiers(). &є побитовим і, і ~є порозрядним доповненням.
Дивись також
Запам’ятайте постійні вирази
Ще не в змозі вирішити це? - впали в депресію, як я це зробив? Чи виглядає ваш код таким чином?
public class A {
private final String myVar = "Some Value";
}
Читаючи коментарі до цієї відповіді, зокрема, від @Pshemo, це нагадало мені, що з постійними виразами обробляються різні, тому змінити її буде неможливо . Отже, вам потрібно буде змінити код, щоб він виглядав так:
public class A {
private final String myVar;
private A() {
myVar = "Some Value";
}
}
якщо ти не власник класу ... я тебе відчуваю!
Детальніше про те, чому ця поведінка читає це ?