Wenn es der Sicherheitsmanager zulässt, kann ein Programm auch private- oder protected-Attribute ändern und Methoden/Konstruktoren eingeschränkter Sichtbarkeit aufrufen. Die Schlüsselfigur in diesem Spiel ist die Oberklasse java.lang.reflect.AccessibleObject, die den Klassen Field und Excecutable (und damit Constructor und Method) die Methode setAccessible(boolean) vererbt. Ist das Argument true und lässt der Sicherheitsmanager die Operation zu, lässt sich auf jedes Element (also Konstruktor, Attribut oder Methode) ungleich der Sichtbarkeitseinstellungen zugreifen:
public class ReadPrivate { @SuppressWarnings( "unused" ) private String privateKey = "Schnuppelhase"; public static void main( String[] args ) throws Exception { ReadPrivate key = new ReadPrivate(); Class<?> c = key.getClass(); java.lang.reflect.Field field = c.getDeclaredField( "privateKey" ); field.setAccessible( true ); System.out.println( field.get(key) ); // Schnuppelhase field.set( key, "Schnuckibutzihasidrachelchen"); System.out.println( field.get(key) ); // Schnuckibutzihasidrachelchen } }
class java.lang.reflect.AccessibleObject
implements AnnotatedElement
- void setAccessible(boolean flag)
Nachfolgede Abfragen sollten die Java-Sichtbarkeiten ignorieren. Falls das nicht erlaubt ist, gibt es eine InaccessibleObjectException. - final boolean trySetAccessible()
Wie setAccessible(true), nur löst die Methode beim nicht gewährten Zugriff keine InaccessibleObjectException aus, sondern liefert false. Neu in Java 9.
Warnung: Mit dieser Technik lässt sich viel Unsinn anrichten. Es gibt Dinge, die in der Laufzeitumgebung einfach fest sein müssen. Dazu zählen einmal angelegte Strings oder Wrapper-Objekte. Strings sind immutable, weil sie intern in einem privaten char-Feld gehalten werden und es keine Modifikationsmöglichkeiten gibt. Auch Wrapper-Objekte sind, wenn sie einmal mit einem Konstruktor angelegt wurden, nicht über öffentliche Methoden veränderbar. Sie anschließend per Reflection zu modifizieren, bringt große Unordnung, insbesondere bei den gecachten Integer/Long-Wrapper-Objekten, die die statischen valueOf(…)-Methoden liefern.