Quelle est la différence entrerequiertetrequiert des instructions transitivesmodule dans la déclaration de module?
Par exemple:
module foo {
requires Java.base;
requires transitive Java.compiler;
}
Si module barrequires
module boire _, le système de module ...
Il en va exactement de même si barrerequires transitive drink
- boisson doit être présent, lisible et accessible. En fait, pour bar _ et boire, le mot clé transitive
ne change rien.
Les modules dépendants de bar sont ceux affectés par transitive
: Tout module qui lit bar peut également lire boire. En d’autres termes, la lisibilité de boire est implicite (c’est pourquoi on l’appelle lisibilité implicite ). Une conséquence est que (client} _ peut accéder aux types de boire.
Donc, si bar requires transitive drink
et customer requires bar
, alors client peut lire boire même si cela n'en dépend pas explicitement.
Mais pourquoi? Imaginez que vous ayez un module dont l'API publique accepte ou retourne le type d'un autre module. Supposons que le module bar renvoie publiquement des instances de Drink
, une interface du module drink:
// in module _bar_
public class Bar {
// `Drink` comes from the module _drink_,
// which _bar_ requires
public Drink buyDrink() { /* ... */ }
}
Dans cet exemple, bar utilise une constante requires
pour boire. Maintenant, disons que client dépend de bar, de sorte que tout son code peut appeler Bar::buyDrink
. Mais que se passe-t-il quand cela se produit?
Le système de module se plaint que client ne lit pas boit et ne peut donc pas accéder à Drink
. Pour résoudre ce problème, client devrait également dépendre de boire. Quelle corvée! Combien inutile est un bar que vous ne pouvez pas utiliser tout de suite?
Pour cette raison, la lisibilité implicite a été introduite: pour rendre un module qui utilise les types d’un autre module dans sa propre API publique immédiatement utilisable sans obligeant l’appelant à rechercher et à exiger tous les modules impliqués.
Donc, si bar requires transitive drink
, client peut commencer à acheter des boissons sans avoir à require drink
- require bar
suffire. Comme il se doit.
La principale différence entre les deux est l'accès d'un module dépendant d'un module à un autre.
Si un module exporte un package contenant un type dont la signature fait référence à un paquet dans un second module puis à la déclaration du Le premier module devrait inclure une dépendance
requires transitive
sur la deuxième. Cecifera en sorte que les autres modules qui dépendent du le premier module sera automatiquement capable de lire le second moduleet, accédez donc à tous les types des packages exportés de ce module.
Alors disons pour votre cas d'utilisation: -
module foo {
requires Java.base;
requires transitive Java.compiler;
}
~> Tout module dépendant du module foo
lira automatiquement le module Java.compiler
~> D'autre part, pour accéder au module Java.base
, ils doivent spécifier à nouveau une clause requires
.
module bar {
requires foo; // Java.compiler is available to read
requires Java.base; // still required
}
requires
décrit le processus de résolution de la dépendance des modules.
(Une directive 'requiert' (indépendamment de 'transitive') indique que Un module dépend d'un autre module. L'effet du le modificateur 'transitif' doit faire en sorte que des modules supplémentaires dépendent également de l'autre module. Si le module M 'nécessite un transitif N', alors pas seulement M dépend-il de N, mais tout module dépendant de M dépend également de N. Cela permet à M d’être refactorisé de sorte que tout ou partie de son contenu peut être déplacé vers un nouveau module N sans casser les modules qui ont un 'nécessite M' directive.
En bref :
requires
- Le module M dépend d'un autre module N.
requires transitive
- les modules supplémentaires dépendent implicitement de l'autre module. Par exemple, si M module dépend de N et que l'autre module P dépend de M. Il dépend alors implicitement de N.
Nicolai a expliqué en détail. Je donne juste un exemple spécifique du code JDK ici. Considérons le module jdk.scripting.nashorn. Le module-info de ce module est le suivant:
Il a cette ligne:
requires transitive Java.scripting;
Ceci est dû au fait que jdk.scripting.nashorn propre API du module dans jdk.scripting.api.scripting package accepte/renvoie les types de javax.script package du Java.scripting module. Ainsi, jdk.scripting.nashorn indique à JMPS que tout module dépendant de jdk.scripting.nashorn dépend automatiquement du module Java.scripting!
Maintenant, le même module jdk.scripting.nashorn utilise cette ligne:
requires jdk.dynalink;
pour un autre module jdk.dynalink . En effet, none des packages exportés ("API") du module jdk.scripting.nashorn utilise les types du module jdk.dynalink. L'utilisation de jdk.dynalink par jdk.scripting.nashorn est purement un détail d'implémentation.
La spécification du langage Java pour Java 9 l'explique en termes très simples. Dans la section Dépendances des modules :
La directive
requires
spécifie le nom d'un module sur lequel le module actuel a une dépendance....
Le mot clé
requires
peut être suivi du modificateurtransitive
. Ceci fait que tout module dont le paramètrerequires
du module actuel a une dépendance implicite déclarée par rapport au module spécifié par la directiverequires transitive
En d'autres termes:
requires
module Y,requires transitive
module Z,requires
module Z.Le terme accessibility est ambigu: vous pouvez accéder à des objets sans accéder à leur type. Si un objet de type T réside dans un package non exporté et si un code "exporté" a une méthode qui renvoie un T ... Ensuite, lors de l'appel de cette méthode, vous obtenez un descripteur sur cet objet invoquer dessus toutes les méthodes qui appartiennent à tout type connu de votre code).
readability est également ambigu: cela ne signifie pas que votre ClassLoader sera toujours incapable de charger la classe T (non exportée).