2016-08-11 2 views
11

Da der Kern des Jigsaw Projekts Java Module System ist, wäre es schön, eine Möglichkeit zu haben, den Zugriff auf bestimmte Programmelemente (Klassen, Methoden und Felder) nur innerhalb bestimmter Module einzuschränken."Modul lokal" Zugriffsverhalten in Java 9

Es kann hilfreich sein, wenn einige Elemente im Modul für dieses Modul im Wesentlichen öffentlich sind, aber außerhalb dieses Moduls nicht zugänglich sein sollten.

Also ich spreche über die nächste Ebene des Zugriffs nach "Paket-local", die "Modul-local" genannt werden könnte.

Allerdings ein kurzer Blick auf Jigsaw rules und frühen Spezifikationen half mir nicht, solche Art von Funktionalität zu finden. Genauer gesagt enthält this Modifier specification keine neuen Elemente.

So ist jede andere Möglichkeit, es in Zukunft Java 9 zu tun?

+0

Zu meinem Verständnis sind Module standardmäßig genagelt geschlossen. Sie müssen Dinge explizit exportieren, um sie von außen anforderbar zu machen. http://openjdk.java.net/projects/jigsaw/quick-start und https://en.wikipedia.org/wiki/Java_Module_System. Versteh ich nur falsch, worüber du hier fragst? – Gimby

+0

Gemäß [Der Status des Modulsystems] (http://openjdk.java.net/projects/jigsaw/spec/sotms/) sind nur Pakete, die exportiert werden, außerhalb des Moduls verfügbar. Siehe auch [diese Tabelle] (http://stackoverflow.com/questions/215497/in-java-difference-between-default-public-protected-and-private/33627846#33627846) zum Beispiel. – aioobe

+0

@Gimby Sie haben recht: Es ist möglich, bestimmte Pakete zu exportieren. Aber was ist mit Methoden und Feldern? Ja, ich denke du verstehst meine Frage richtig. – Andremoniy

Antwort

10

A public Element (dh, eine Klasse, Schnittstelle, Methode oder Feld) in einem nicht ausgeführten Paket wird in der Tat „-Modul lokale“. Es wird in der zugänglich für alle anderen Code sein Modul, aber nicht von außerhalb des Moduls .

Es gibt keine Möglichkeit, ein Modul-lokales Element in einem exportierten Paket zu deklarieren. Ein public Element eines exportierten Pakets ist von außerhalb des Moduls zugänglich, ein package-private Element ist noch paket-privat, und es gibt keinen Element-Level-Zugriffsmodus zwischen diesen beiden Modi. Wir könnten einen neuen solchen Modus definieren , aber wir haben einige überzeugende Anwendungsfälle für sie gesehen, und darüber hinaus implementieren modulare modulare Zugriffskontrolle in der JVM mit einer Granularität feiner als die der exportierten Pakete würden erhebliche Kosten auferlegen .

+0

"aber wir haben einige überzeugende Anwendungsfälle dafür gesehen" - nicht in der Java-Welt, da bin ich mir sicher. Hast du woanders nachgesehen? Nachdem ich ein nicht-triviales Stück von Swift gebaut habe, besiegt mich der Mangel an "internem" die meisten der potenziellen Vorteile von Modulen in Bezug auf Modellierung/Design. Unser Anwendungsfall: Eine "Benutzer" -Ressource, die über kryptografische Schlüssel verfügt. Während "Benutzer" öffentlich ist, sollten die Schlüssel modul-privat sein, aber nicht unbedingt paket-privat. Ich nehme an, Sie müssten arbeiten, indem Sie nur Schnittstellen offenlegen - aber dann müssten Sie mit Benutzern umgehen, die sie möglicherweise auf eine Weise implementieren, die Sie nicht erwarten. – Raphael

+0

Ähnliche Probleme ergeben sich mit Unterklassen. 'final' verhindert Unterklassen * überall *, so dass ich keinen Typ deklarieren kann, den ich innerhalb des Moduls ableiten kann, aber ich kann sicher sein, dass er nicht außerhalb der Klasse subclassiert wird. (Oder kann ich?) – Raphael

+0

"Zugriffssteuerung in der JVM mit einer Granularität feiner als die der exportierten Pakete" - Sind Module _coarser_ nicht als Pakete? Habe ich missverstanden? – Raphael

5

Kurzantwort

Es kann hilfreich sein, wenn es einige Elemente in dem Modul sind die für dieses Modul im Wesentlichen öffentlich sind, sollte aber nicht außerhalb dieses Moduls zugänglich sein.

Das ist nicht möglich. (Mit Hilfe des Modulsystem allein - es gibt eine Abhilfe.)

Lange Antwort

Die Erklärung innerhalb der Frist liegt Accessibility:

der Java-Compiler und virtuelle Maschine die öffentlichen Typen betrachten in ein Paket in einem Modul zu zugänglich durch Code in einem anderen Modul nur dann, wenn das erste Modul von dem zweiten Modul in dem oben definierten Sinne gelesen werden kann, und das erste Modul dieses Paket exportiert. [...]

Ein über Modulgrenzen hinweg referenzierter Typ, auf den nicht zugegriffen werden kann, ist auf die gleiche Weise wie eine private Methode oder ein Feld unbrauchbar: Jeder Versuch, sie zu verwenden, führt zu einem Fehler der Compiler oder ein IllegalAccessError, der von der Java Virtual Machine ausgelöst werden soll, oder ein IllegalAccessException, der von den reflektiven Laufzeit-APIs ausgelöst wird. [...]

Eine Methode oder ein Feld, auf das über Modulgrenzen hinweg verwiesen wird, ist zugänglich, wenn der einschließende Typ in diesem Sinne zugänglich ist und wenn die Deklaration des Elements selbst auch den Zugriff erlaubt.

Zwar gibt es verschiedene Möglichkeiten, wie genau und ein Paket, die exportiert werden kann, wenn der Compiler/JVM eine Art zugänglich kein zusätzlicher Mechanismus gilt hält. Seine Mitglieder sind so zugänglich wie vor Jigsaw.

Dies bedeutet, dass es keine Möglichkeit gibt, die Mitglieder eines zugänglichen Typs innerhalb des Moduls sichtbar zu machen (das würde public erfordern), aber nicht außerhalb (weil ein öffentliches Mitglied eines zugänglichen Typs zugänglich ist).

Umgehung

So ist eine andere Möglichkeit, es in Zukunft Java 9 zu tun?

Ja. :)

Sie können eine öffentliche Schnittstelle Global in einem exportierten Paket haben, das die Methoden definiert, die Sie in die Welt exportieren möchten. Dann haben Sie entweder eine Schnittstelle oder eine Klasse Local extend Global und fügen Sie alle gewünschten Mitglieder hinzu. Schlüssel ist, dass Localnicht in einem exportierten Paket sein muss!

Wenn nun die API Ihres Moduls nur Global -s zurückgibt, sie aber nie als Argument für die Methode akzeptiert, können Sie loslegen. Stellen Sie nur sicher, dass intern Sie immer verwenden - und möglicherweise zu Local werfen.

Wenn Sie auch Global -s akzeptieren, müssen Sie eindeutig dokumentieren, dass dies nur Instanzen sein können, die Ihre API zurückgegeben hat (d. H. Der Benutzer darf keine eigene Implementierung erstellen). Das hört sich vielleicht unerschwinglich an, aber wenn Sie über Ihre ursprüngliche Anfrage nachdenken, würde es dieselben Eigenschaften haben.

Verwandte Themen