Nest-Based Access Control
Nest-Based Access Control – dosł. Kontrola dostępu bazująca na gniazdach.
Zagnieżdżanie typów
W języku Java zagnieżdżone mogą być:
- członkowie statyczni: klasy statyczne, wyliczenia i interfejsy
- klasy (nie statyczne)
- klasy lokalne
- klasy anonimowe (wewnętrzne)
Pokazana niżej klasa pokazuje niektóre z możliwości zagnieżdżenia:
1 package java11zmiany; public class Klasa {//klasa główna (najwyższego poziomu) static class StaticClass { } //klasa statyczna interface Interf { } // iterfejs (statyczny) enum ENUM {} // wyliczenie (statyczne) class NonStaticClass { }// klasa wewnętrzna void metoda1() { } { class LocalClass { }// klasa lokalna (wewnętrzna) } static void metoda2() { class StaticLocalClass { }// klasa lokalna (wewnętrzna) w kontekście statycznym } StaticClass sc = new StaticClass() { }; // Klasa anonimowa (wewnętrzna) static Interf inf = new Interf() { }; // Klasa anonimowa (wewnętrzna) w kontekście statycznym }
Postawienie problemu
Zapoznajmy się z klasą:
package java11zmiany; import java.lang.reflect.Field; public class NestedMembers { public static class Nest1 { private int nest1; public void foo() throws IllegalAccessException { final Nest2 nest2a = new Nest2(); nest2a.nest2 = 2; try { final Field f2 = Nest2.class.getDeclaredField("nest2"); f2.setInt(nest2a, 2); } catch (NoSuchFieldException e) { e.printStackTrace();// } } } public static class Nest2 { private int nest2; } public static void main(String[] args) throws Exception { new Nest1().foo(); } }
Klasa Nest1 uzyskuje dostęp do zmiennych w klasie Nest2. Jednak, gdy w Java 10 i wcześniejszych spróbowalibyśmy
uzyskać informację o polu, jego zawartości i zmienić tę zawartość przy użyciu refleksji otrzymamy błąd:
Exception in thread "main" java.lang.IllegalAccessException: class java11zmiany.NestedMembers$Nest1 (in module java11zmiany) cannot access a member of class java11zmiany.NestedMembers$Nest2 (in module java11zmiany) with modifiers "private" at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:360) at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:589) at java.base/java.lang.reflect.Field.checkAccess(Field.java:1075) at java.base/java.lang.reflect.Field.setInt(Field.java:958) at java11zmiany/java11zmiany.NestedMembers$Nest1.foo(NestedMembers.java:18) at java11zmiany/java11zmiany.NestedMembers.main(NestedMembers.java:30)
Rozwiązanie problemu
Java 11 rozwiązuje powyższy problem. Klasa uruchomiona w Java 11 nie wyrzuca wyjątków.
Stworzono gniazda (nest) – kontekst kontroli dostępu umożliwiający mechanizmom refleksji dostęp do wszystkich, w tym prywatnych członków klas.
Szczegóły problemu i jego rozwiązanie opisane jest w https://openjdk.java.net/jeps/181
JEP – JDK Enhancement Proposals – dosł. Propozycje rozszerzenia JDK.
Przyjęte rozwiązania są wewnętrzne. Nie zmieniają one w żaden sposób dotychczasowych poziomów dostępu ani nie powodują zmian w organizacji modułów. Nie powodują też konieczności jakichkolwiek zmian w sposobie pisania kodu.