Zakładając, że nie przeszkadza SecurityManagerci to zrobić, możesz użyć setAccessibledo obejścia privatei zresetowania modyfikatora, aby się go pozbyć finali faktycznie zmodyfikować private static finalpole.
Oto przykład:
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"
}
}
Zakładając, że nie SecurityExceptionzostanie wyrzucony, powyższy kod zostanie wydrukowany "Everything is true".
To, co faktycznie tutaj zrobiono, wygląda następująco:
- Prymitywne
booleanwartości truei falsew mainsą autoboxed do typu odniesienia Boolean„stałych” Boolean.TRUEiBoolean.FALSE
- Odbicie służy do zmiany
public static final Boolean.FALSEodniesienia do, Booleano którym mowa wBoolean.TRUE
- W rezultacie, za każdym razem, gdy a
falsejest autoboxowane Boolean.FALSE, odnosi się do tego samegoBoolean jak ten, zwaną przezBoolean.TRUE
- Wszystko, co było
"false"teraz, jest"true"
Powiązane pytania
Ostrzeżenia
Za każdym razem, gdy robisz coś takiego, należy zachować szczególną ostrożność. Może nie działać, ponieważ SecurityManagermoże być obecny, ale nawet jeśli nie działa, w zależności od wzorca użytkowania może działać lub nie.
JLS 17.5.3 Późniejsza modyfikacja pól końcowych
W niektórych przypadkach, takich jak deserializacja, system będzie musiał zmienić finalpola obiektu po zakończeniu budowy. finalpola można zmieniać za pomocą refleksji i innych środków zależnych od implementacji. Jedyny wzorzec, w którym ma to rozsądną semantykę, to taki, w którym obiekt jest konstruowany, a następnie finalpola obiektu są aktualizowane. Obiekt nie powinien być widoczny dla innych wątków, a finalpola nie powinny być odczytywane, dopóki wszystkie aktualizacje finalpól obiektu nie zostaną zakończone. Zamrożenie finalpola występuje zarówno na końcu konstruktora, w którym finalpole jest ustawione, jak i natychmiast po każdej modyfikacji finalpola poprzez odbicie lub inny specjalny mechanizm.
Nawet wtedy istnieje wiele komplikacji. Jeśli finalpole zostanie zainicjowane do stałej czasu kompilacji w deklaracji pola, zmiany w finalpolu mogą nie zostać zaobserwowane, ponieważ użycie tego finalpola jest zastępowane w czasie kompilacji stałą czasu kompilacji.
Innym problemem jest to, że specyfikacja pozwala na agresywną optymalizację finalpól. W obrębie wątku dopuszcza się zmianę kolejności odczytów finalpola z tymi modyfikacjami pola końcowego, które nie mają miejsca w konstruktorze.
Zobacz też
- JLS 15.28 Wyrażenie stałe
- Jest mało prawdopodobne, aby ta technika działała z prymitywem
private static final boolean, ponieważ jest ona nieodłączna jako stała czasowa kompilacji, a zatem „nowa” wartość może nie być obserwowalna
Dodatek: o manipulacji bitowej
Głównie,
field.getModifiers() & ~Modifier.FINAL
wyłącza bit odpowiadający Modifier.FINALod field.getModifiers(). &jest bitowo-i, i ~jest bit-dopełniaczem.
Zobacz też
Pamiętaj o stałych wyrażeniach
Nadal nie jesteś w stanie rozwiązać tego ?, popadłeś w depresję tak jak ja? Czy twój kod wygląda tak?
public class A {
private final String myVar = "Some Value";
}
Czytając komentarze do tej odpowiedzi, szczególnie tej autorstwa @Pshemo, przypomniałem sobie, że Wyrażenia stałe są obsługiwane inaczej, więc nie będzie można ich modyfikować. Dlatego musisz zmienić kod, aby wyglądał następująco:
public class A {
private final String myVar;
private A() {
myVar = "Some Value";
}
}
jeśli nie jesteś właścicielem klasy ... Czuję cię!
Aby uzyskać więcej informacji o tym, dlaczego to zachowanie czyta to ?