Uw zoekopdracht heeft geen resultaten opgeleverd.
We raden u aan het volgende te proberen om te vinden wat u zoekt:
Wat dat zijn en hoe we ze gebruiken
Door Paul Deitel
Paul Deitel
In dit artikel introduceer ik het Java 9 Platform Module System (JPMS), de belangrijkste nieuwe software engineering technologie in het bestaan van Java. Modulariteit, het resultaat van Project Jigsaw, helpt ontwikkelaars op alle niveaus productiever te zijn bij het bouwen, onderhouden en ontwikkelen van met name grote softwaresystemen.
Modulariteit voegt een hoger aggregatieniveau toe boven de pakketten. Het belangrijkste nieuwe taalelement is de module: een herbruikbare groep gerelateerde pakketten met een unieke naam, maar ook resources (zoals afbeeldingen en XML-bestanden) en een module-descriptor voor de specificatie van
Het Java SE-platform bestaat al sinds 1995. Er zijn nu ongeveer 10 miljoen ontwikkelaars die het gebruiken om van alles te bouwen, van kleine apps voor apparaten met beperkte middelen, zoals in het Internet of Things (IoT) en andere ingebouwde apparaten, tot omvangrijke systemen, essentieel voor bedrijfsvoering en missie. Er zijn enorme hoeveelheden bestaande code beschikbaar, maar tot nu toe was het Java-platform vooral een monolithische one-size-fits-all oplossing. In de loop der jaren zijn er diverse inspanningen gedaan om Java modulair te maken, maar die zijn niet populair en geen enkele kan werkelijk dienen om het Java-platform te modulariseren.
Het modulariseren van het Java SE-platform was een uitdaging en we hebben er heel wat jaren aan gewerkt. JSR 277: Java Module System verscheen oorspronkelijk in 2005 voor Java 7. Dit JSR is later vervangen door JSR 376: Java Platform Module System, dat bedoeld was voor Java 8. Het Java SE-platform is nu modulair in Java 9, maar pas nadat Java 9 was uitgesteld tot september 2017.
Elke module moet expliciet zijn afhankelijkheden vermelden.
Volgens JSR 376 heeft het modulariseren van het Java SE-platform de volgende hoofddoelen
JEP 200: MODULAIRE JDK
JEP 201: MODULAIRE BRONCODE
JEP 220: MODULAIRE RUNTIME-IMAGES
JEP 260: MEEST INTERNE API'S INKAPSELEN
JEP 261: MODULESYSTEEM
JEP 275: MODULAIRE JAVA-APPLICATIEPAKKETTEN
JEP 282: JLINK: DE JAVA LINKER
JSR 376: JAVA PLATFORM MODULESYSTEEM
JSR 379: JAVA SE 9
Tabel 1. JEP's en JSR's voor Java-modulariteit
Een cruciaal aspect van Java 9 is dat JDK in modules wordt verdeeld om verschillende configuraties te ondersteunen. (Raadpleeg "JEP 200: Modulaire JDK." Alle JEP's en JSR's voor Java-modulariteit worden getoond in tabel 1.) Gebruik het Java-commando uit JDK's binmap met de optie --list-modules
, zoals in:
java --list-modules
Toont een lijst met JDK's moduleset, met de standaardmodules voor de implementatie van de Java Language SE Specification (namen beginnend met java
), JavaFX-modules (namen beginnend met javafx
), JDK-specifieke modules (namen beginnend met jdk
) en Oracle-specifieke modules (namen beginnend met oracle
). Elke modulenaam wordt gevolgd door een versie-string. @9
geeft aan dat de module tot Java 9 behoort.
Zoals we al zeiden, moet een module een module-descriptor bieden: metadata die de afhankelijkheden van de module specificeert, de pakketten die de module beschikbaar stelt voor andere modules etc. Een module-descriptor is de gecompileerde versie van een moduleverklaring, die is gedefinieerd in een bestand met de naam module-info.java
. Elke moduleverklaring begint met het sleutelwoord module
, gevolgd door een unieke modulenaam en een modulebody tussen accolades, zoals in:
Een belangrijke reden voor het modulesysteem is een sterke inkapseling.
module modulenaam {
}
De hoofdtekst van de moduleverklaring kan leeg zijn of verschillende module-instructies bevatten, waaronder requires
, exports
, provides…with
, uses
en opens
(die we allemaal bespreken). Zoals u later zult zien, wordt bij het compileren van de moduleverklaring de module-descriptor aangemaakt, die wordt opgeslagen in een bestand met de naam module-info.class
in de hoofdmap van de module. Hier introduceren we kort elke module-instructie. Daarna presenteren we de eigenlijke moduleverklaringen.
De sleutelwoorden exports
, module
, open
, opens
, provides
, requires
, uses
, with
, evenals to
en transitive
, die we later introduceren, zijn beperkte sleutelwoorden. Het zijn sleutelwoorden alleen in moduleverklaringen en ze kunnen overal in uw code als ID's worden gebruikt.
requires. Een module-instructie requires
geeft aan dat deze module afhankelijk is van een andere module. Deze relatie wordt een module-afhankelijkheid genoemd. Elke module moet expliciet zijn afhankelijkheden vermelden. Als module A module B vereist
, zeggen we dat module A module B leest en dat module B wordt gelezen door module A. Als u een afhankelijkheid van een andere module wilt aangeven, gebruikt u requires
, zoals in:
requires modulename;
Er is ook een instructie requires static
om aan te geven dat een module vereist is tijdens het compileren, maar optioneel is tijdens runtime. Dit noemen we een optionele afhankelijkheid, die we niet bespreken in deze inleiding.
vereist transitief - impliciete leesbaarheid. Als u een afhankelijkheid van een andere module wilt aangeven, zodat andere modules die uw module lezen ook die afhankelijkheid lezen (ook wel impliciete leesbaarheid genoemd), gebruikt u requires transitive
, zoals in:
requires transitive modulename;
Bekijk de volgende instructie uit de moduleverklaring van java.desktop
:
requires transitive java.xml
;
In dit geval leest elke module die java.desktop
leest impliciet ook java.xml
. Als een methode van de module java.desktop
bijv. een type van de module java.xml
retourneert, wordt de code in modules die java.desktop
lezen afhankelijk van java.xml
. Zonder de instructie requires transitive
in de moduleverklaring van java.desktop
worden zulke afhankelijke modules niet gecompileerd tenzij ze expliciet java.xml
lezen.
Volgens JSR 379 moeten Java SE's standaardmodules in alle gevallen impliciete leesbaarheid verlenen, zoals hier beschreven. Een Java SE-standaardmodule kan ook afhankelijk zijn van niet-standaardmodules, maar mag er geen impliciete leesbaarheid aan toekennen. Hierdoor kan code alleen op basis van Java SE-standaardmodules worden overgedragen aan Java SE-implementaties.
exports and exports…to. Een module-instructie exports
specificeert één van de pakketten van de module waarvan het type public
(en het geneste type public
en protected
) toegankelijk moet zijn voor code in alle andere modules. Met een instructie exports…to
kunt u in een door komma's gescheiden lijst precies opgeven welke module of modulecode toegang heeft tot het geëxporteerde pakket, de zogenaamde gekwalificeerde export.
uses. Een module-instructie uses
specificeert een service die door deze module wordt gebruikt, waardoor de module een servicegebruiker wordt. Een service is een object van een klasse die de interface implementeert of de klasse abstract
uitbreidt die is opgegeven in de instructie uses
.
provides…with. Een module-instructie provides…with
-geeft aan dat een module een service-implementatie biedt, waardoor de module een serviceprovider wordt. Het gedeelte provides
van de instructie specificeert een interface- of abstract
-klasse die wordt vermeld in de instructie uses
van een module en het gedeelte with
van de instructie specificeert de naam van de serviceprovider-klasse die de interface implementeert
of die de abstract
-klasse uitbreidt
.
open, opens, and opens…to. Vóór Java 9 kon reflectie worden gebruikt om meer te weten te komen over alle typen in een pakket en alle leden van een type, zelfs de private
-leden, of u deze mogelijkheid nu wel of niet wilde toelaten. Niets was dus echt ingekapseld.
Een belangrijke reden voor het modulesysteem is een sterke inkapseling. Een type in een module is standaard niet toegankelijk voor andere modules, tenzij het een openbaar type is en u zijn pakket exporteert. U toont alleen de pakketten die u wilt weergeven. Bij Java 9 geldt dit ook voor reflectie.
Alleen runtime-toegang tot pakket toestaan. Opent module-instructie van het formulier
opent pakket
geeft aan dat de public
-typen (en de geneste public
- en protected
-typen) van een specifiek pakket alleen tijdens runtime toegankelijk zijn voor code in andere modules. Ook zijn alle typen in het opgegeven pakket (en alle leden van het type) toegankelijk via reflectie.
Verlening van runtime-toegang tot een pakket door specifieke modules. Een opens…to
module-instructie van het formulier
opent pakket naar door komma's gescheiden lijst met modules
geeft aan dat de typen public
van een specifiek pakket (en de geneste typen public
en protected
) alleen tijdens runtime toegankelijk zijn voor code in de vermelde modules. Alle typen in het opgegeven pakket (en alle leden van het type) zijn via reflectie toegankelijk voor code in de opgegeven modules.
Alleen runtime-toegang toestaan tot alle pakketten in een module. Als alle pakketten in een bepaalde module tijdens runtime en via reflectie toegankelijk moeten zijn voor alle andere modules, kunt u de volledige module openen
, zoals in:
open module modulename {
// module directives
}
Standaard kan een module met runtime-reflectieve toegang tot een pakket de typen public
van het pakket zien (en de geneste typen public
en protected
). De code in andere modules heeft echter toegang tot alle typen in het weergegeven pakket en alle leden binnen die typen, inclusief private
leden via setAccessible
, zoals in eerdere Java-versies.
Zie Oracle's documentatie voor meer informatie over setAccessible
en reflectie.
Paul Deitel, CEO en Chief Technical Officer bij Deitel & Associates, is afgestudeerd aan het MIT met 35 jaar ervaring in computing Hij is een voorvechter van Java en programmeert al ruim 22 jaar in deze taal. Hij en zijn coauteur, Dr. Harvey M. Deitel is wereldwijd de best verkochte auteur op het gebied van programmeertaal. Paul heeft Java-, Android-, iOS-, C#-, C++-, C- en internet-programmeercursussen verzorgd voor internationale klanten in de industrie, overheid en academische wereld.
OPMERKING: Dit artikel bevat delen van Java Magazine september/oktober 2017.