Comment fonctionne la visibilité pour les classes nestedes Java?

J’essaie d’apprendre quelle visibilité atsortingbuer aux classes nestedes, en plus de ce que mon IDE me crie de dire. Cela peut devenir arbitrairement compliqué, il faut donc que je comprenne les règles générales.

public class A { private static class B { public int foo; // accessible in A? private int bar; // accessible in A? public static class C { // accessible in A? everywhere? } private static class D { // accessible in A? } } } 

Autant que je sache, les modificateurs semblent résoudre au niveau “fichier”, pas au niveau de la classe encapsulante. Une fois qu’une chose est privée, tout ce qui s’y trouve est privé.

Quel est le mécanisme réel de cette explication technique? Est-ce documenté quelque part ou dois-je simplement lire le JLS?

L’un des meilleurs résumés de la visibilité des access que j’ai vus se trouve dans les tutoriels Java> Contrôle de l’access aux membres d’une classe , mais il dissimule certains des détails clés. La question que je pense que vous posez est traitée au § 6.6.1 du JLS pour SE 7: “Détermination de l’accessibilité”

Si … public … Sinon, si … protégé … Sinon, si … access au package …

Sinon, le membre ou le constructeur est déclaré privé et l’ access est autorisé si, et seulement si, il se produit dans le corps de la classe de niveau supérieur (§7.6) qui inclut la déclaration du membre ou du constructeur .

Si vous lisez cela attentivement:

  1. tout access
  2. dans le corps de la classe de premier niveau
  3. à un autre membre private (pas package-private – c’est différent)
  4. quelle que soit sa profondeur nestede
  5. est autorisé

Donc: tout membre à l’intérieur de n’importe quelle profondeur de classes nestedes privées est accessible n’importe où dans le corps de la classe de niveau supérieur (y compris dans d’autres classes nestedes). Cependant, une classe nestede privée et tout membre de celle-ci ne sont pas visibles par les autres classes de niveau supérieur.

Par exemple:

 public class A { private static class B { public int foo; // accessible in A and P private int bar; // accessible in A and P public static void test(){ P p = new P(); p.foo = 1; p.bar = 1; } } private static class P { public int foo; // accessible in A and B private int bar; // accessible in A and B public static void test(){ B b = new B(); b.foo = 1; b.bar = 1; } } public static void test(){ B b = new B(); b.foo = 1; b.bar = 1; P p = new P(); p.foo = 1; p.bar = 1; } } 

Note: Ce n’est pas “niveau de fichier” cependant. Déclarez une autre classe de niveau supérieur dans ce fichier (qui ne peut pas être public – une seule de celles autorisées par fichier) et ne peut pas voir ces mêmes membres private nesteds.

 class X { public static void test() { // all of these statements fail ... AB b = new AB(); b.foo = 1; b.bar = 1; b.test(); AP p = new AP(); p.foo = 1; p.bar = 1; p.test(); } } 

L’accessibilité est relative à la source d’access. Premier

Sinon, le membre ou le constructeur est déclaré private et l’access est autorisé si et seulement si il se produit dans le corps de la classe de niveau supérieur (§7.6) qui inclut la déclaration du membre ou du constructeur.

Ainsi, tous les membres que vous avez déclarés en A ou nesteds dans la classe en A sont accessibles en A

Si vous n’êtes pas dans A , private membres private de A ne sont pas accessibles. Cela signifie que B n’est pas accessible. Puisque foo , bar , C et D sont membres de B , vous avez besoin de B pour y accéder. Mais comme B n’est pas accessible, vous ne pouvez pas y accéder non plus.

 public class Unrelated { { B b; // nope AB b; // nope ABC c; // nope } } 

Ces règles sont plus ou moins toutes définies dans cette section du JLS.