Classe nestede statique en Java, pourquoi?

Je regardais le code Java de LinkedList et remarquais qu’il utilisait une classe statique nestede, Entry .

 public class LinkedList ... { ... private static class Entry { ... } } 

Quelle est la raison d’utiliser une classe nestede statique, plutôt qu’une classe interne normale?

La seule raison pour laquelle je pouvais penser était que Entry n’a pas access aux variables d’instance, donc du sharepoint vue de la POO, il a une meilleure encapsulation.

Mais je pensais qu’il pourrait y avoir d’autres raisons, peut-être la performance. Que pourrait-il être?

Remarque. J’espère que mes termes sont corrects, je l’aurais appelé une classe interne statique, mais je pense que c’est faux: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html

La page Sun à laquelle vous accédez contient des différences clés entre les deux:

Une classe nestede est membre de sa classe englobante. Les classes nestedes non statiques (classes internes) ont access aux autres membres de la classe englobante, même si elles sont déclarées privées. Les classes nestedes statiques n’ont pas access aux autres membres de la classe englobante.

Remarque: Une classe nestede statique interagit avec les membres d’instance de sa classe externe (et d’autres classes), comme toute autre classe de niveau supérieur. En fait, une classe nestede statique est une classe de niveau comportemental qui a été nestede dans une autre classe de niveau supérieur pour la commodité de l’emballage.

Il n’est pas nécessaire que LinkedList.Entry soit une classe de niveau supérieur car elle est uniquement utilisée par LinkedList (il existe d’autres interfaces qui ont également des classes nestedes statiques nommées Entry , telles que Map.Entry – même concept). Et comme il n’a pas besoin d’accéder aux membres de LinkedList, il est logique que ce soit statique – c’est une approche beaucoup plus propre.

Comme Jon Skeet l’a fait remarquer , je pense que c’est une meilleure idée si vous utilisez une classe nestede que de commencer par être statique, puis de décider si elle doit vraiment être non statique en fonction de votre utilisation.

À mon avis, la question devrait être inversée chaque fois que vous voyez une classe interne – doit-elle vraiment être une classe interne, avec la complexité supplémentaire et la référence implicite (plutôt qu’explicite et plus claire) à une instance de la classe contenant?

Attention, je suis partial en tant que fan C # – C # n’a pas l’équivalent des classes internes, bien qu’il comporte des types nesteds. Je ne peux pas dire que j’ai encore manqué des cours internes 🙂

Il y a des problèmes de rétention de mémoire non évidents à prendre en compte ici. Étant donné qu’une classe interne non statique conserve une référence implicite à sa classe «externe», si une instance de la classe interne est fortement référencée, l’instance externe est également fortement référencée. Cela peut conduire à une certaine égratignure lorsque la classe externe n’est pas collectée, même s’il semble que rien n’y fait référence.

Eh bien, d’une part, les classes internes non statiques ont un champ supplémentaire caché qui pointe vers l’instance de la classe externe. Donc, si la classe Entry n’était pas statique, en plus d’avoir un access dont elle n’a pas besoin, elle contiendrait environ quatre pointeurs au lieu de trois.

En règle générale, je dirais que si vous définissez une classe qui sert essentiellement à rassembler des membres de données, comme une “structure” en C, envisagez de la rendre statique.

La classe nestede statique est comme toute autre classe externe, car elle n’a pas access aux membres de classe externes.

Juste pour la commodité de l’emballage, nous pouvons regrouper les classes nestedes statiques en une seule classe externe à des fins de lisibilité. En dehors de cela, il n’y a pas d’autre cas d’utilisation de la classe nestede statique.

Exemple pour un tel type d’utilisation, vous pouvez trouver dans le fichier Android R.java (ressources). Le dossier Res d’android contient des dispositions (contenant des conceptions d’écran), un dossier pouvant être dessiné (contenant des images utilisées pour le projet), un dossier de valeurs (qui contient des constantes de chaîne), etc.

Sine tous les dossiers font partie du dossier Res, l’outil Android génère un fichier R.java (resources) qui contient en interne beaucoup de classes nestedes statiques pour chacun de leurs dossiers internes.

Voici l’apparence du fichier R.java généré dans Android: Ici, ils ne sont utilisés que pour la commodité de l’emballage.

 /* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * aapt tool from the resource data it found. It * should not be modified by hand. */ package com.techpalle.b17_testthird; public final class R { public static final class drawable { public static final int ic_launcher=0x7f020000; } public static final class layout { public static final int activity_main=0x7f030000; } public static final class menu { public static final int main=0x7f070000; } public static final class ssortingng { public static final int action_settings=0x7f050001; public static final int app_name=0x7f050000; public static final int hello_world=0x7f050002; } } 

La classe interne statique est utilisée dans le modèle de générateur. La classe interne statique peut instancier sa classe externe qui n’a qu’un constructeur privé. Vous pouvez donc utiliser une classe interne statique pour instancier la classe externe qui ne possède qu’un constructeur privé. Vous ne pouvez pas faire la même chose avec la classe interne car vous devez créer un object de la classe externe avant d’accéder à la classe interne.

 class OuterClass { private OuterClass(int x) { System.out.println("x: " + x); } static class InnerClass { public static void test() { OuterClass outer = new OuterClass(1); } } } public class Test { public static void main(Ssortingng[] args) { OuterClass.InnerClass.test(); // OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside. } } 

Cela produira x: 1

Exemple simple:

 package test; public class UpperClass { public static class StaticInnerClass {} public class InnerClass {} public static void main(Ssortingng[] args) { // works StaticInnerClass stat = new StaticInnerClass(); // doesn't comstack InnerClass inner = new InnerClass(); } } 

Si non-statique, la classe ne peut pas être instanciée, sauf dans une instance de la classe supérieure (donc pas dans l’exemple où main est une fonction statique)

De http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html :

Utilisez une classe nestede (ou une classe interne) non statique si vous avez besoin d’accéder aux champs et méthodes non publiques d’une instance d’enceinte. Utilisez une classe nestede statique si vous n’avez pas besoin de cet access.

L’une des raisons de la statique par rapport à la normale est liée au chargement de classe. Vous ne pouvez pas instancier une classe interne dans le constructeur de son parent.

PS: J’ai toujours compris que «nested» et «intérieur» étaient interchangeables. Il y a peut-être des nuances subtiles dans les termes, mais la plupart des développeurs Java comprendraient non plus.

Les classes internes non statiques peuvent entraîner des memory leaks alors que les classes internes statiques les protègent. Si la classe externe contient des données considérables, elle peut réduire les performances de l’application.

L’utilisation d’une classe nestede statique plutôt que non statique peut, dans certains cas, économiser des espaces. Par exemple: implémenter un Comparator dans une classe, par exemple Student.

 public class Student { public static final Comparator BY_NAME = new ByName(); private final Ssortingng name; ... private static class ByName implements Comparator { public int compare() {...} } } 

Ensuite, le static garantit que la classe Student ne possède qu’un seul comparateur, plutôt que d’instancier un nouveau à chaque fois qu’une nouvelle instance d’élève est créée.

Je ne connais pas la différence de performance, mais comme vous le dites, la classe nestede statique ne fait pas partie d’une instance de la classe englobante. Cela semble plus simple de créer une classe nestede statique, à moins que vous en ayez vraiment besoin pour être une classe interne.

C’est un peu comme pourquoi je fais toujours mes variables en Java – si elles ne sont pas définitives, je sais qu’il y a quelque chose de marrant avec elles. Si vous utilisez une classe interne au lieu d’une classe nestede statique, il devrait y avoir une bonne raison.

Avantage de classe interne–

  1. une seule utilisation
  2. soutient et améliore l’encapsulation
  3. lisibilité
  4. access sur le terrain privé

Sans l’existant de classe externe, la classe interne n’existera pas.

 class car{ class wheel{ } } 

Il existe quatre types de classe interne.

  1. classe interne normale
  2. Méthode Classe Interne Local
  3. Classe interne anonyme
  4. classe interne statique

point —

  1. à partir de la classe interne statique, nous ne pouvons accéder qu’au membre statique de la classe externe.
  2. Au sein de la classe interne, nous ne pouvons pas déclarer membre statique.
  3. pour invoquer la classe interne normale dans la zone statique de la classe externe.

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  4. pour invoquer la classe interne normale dans la zone d’instance de la classe externe.

    Inner i=new Inner();

  5. pour invoquer la classe interne normale en dehors de la classe externe.

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  6. inside Classe interne Ce pointeur sur la classe interne.

    this.member-current inner class outerclassname.this--outer class

  7. pour la classe interne, le modificateur applicable est – public, par défaut,

    final,abstract,ssortingctfp,+private,protected,static

  8. outer $ inner est le nom du nom de la classe interne.

  9. classe interne à l’intérieur de la méthode d’instance alors nous pouvons accéder aux champs statiques et d’instance de la classe externe.

Classe 10.inner à l’intérieur de la méthode statique alors nous pouvons accéder uniquement au champ statique de

classe externe.

 class outer{ int x=10; static int y-20; public void m1() { int i=30; final j=40; class inner{ public void m2() { // have accees x,y and j } } } }