Question

Je regardais le code Java pour LinkedList et remarquais qu'il utilisait une classe imbriquée statique, Entrée .

public class LinkedList<E> ... {
...

 private static class Entry<E> { ... }

}

Quelle est la raison d'utiliser une classe imbriquée statique plutôt qu'une classe interne normale?

La seule raison à laquelle je pouvais penser, c’est que Entry n’a pas accès aux variables d’instance, ce qui lui confère une meilleure encapsulation du point de vue de la programmation orientée objet.

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. J'aurais appelé cela une classe interne statique, mais je pense que cela ne va pas: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html

Était-ce utile?

La solution

La page Sun à laquelle vous créez un lien présente des différences essentielles entre les deux:

  

Une classe imbriquée est membre de sa classe englobante. Les classes imbriquées non statiques (classes internes) ont accès aux autres membres de la classe englobante, même s'ils sont déclarés privés. Les classes imbriquées statiques n'ont pas accès aux autres membres de la classe englobante.
  ...

     

Remarque: une classe imbriquée statique interagit avec les membres d'instance de sa classe externe (et d'autres classes) comme toute autre classe de niveau supérieur. En effet, une classe imbriquée statique est comportementalement une classe de niveau supérieur qui a été imbriquée dans une autre classe de niveau supérieur pour des raisons pratiques de packaging.

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

Comme souligne Jon Skeet , il est préférable de commencer par utiliser une classe imbriquée. avec elle étant statique, puis décidez si elle doit vraiment être non statique en fonction de votre utilisation.

Autres conseils

À mon avis, la question doit être l’inverse chaque fois que vous voyez une classe interne - faut-il vraiment être une classe interne, avec la complexité supplémentaire et l'implicite (plutôt que explicite et plus claire, OMI) référence à une instance de la classe contenante?

Remarquez, je suis partial en tant que fan de C # - C # n'a pas l'équivalent des classes internes, bien qu'il ait des types imbriqués. Je ne peux pas dire que j'ai encore raté les classes intérieures:)

Il convient de prendre en compte ici les problèmes de rétention de mémoire non évidents. Puisqu'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 entraîner des problèmes lorsque la classe externe n'est pas récupérée, même si il semble que rien ne la mentionne.

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

En règle générale, je dirais que si vous définissez une classe qui est fondamentalement là pour agir comme une collection de membres de données, comme un "struct". en C, envisagez de le rendre statique.

La classe imbriquée statique est comme n'importe quelle autre classe externe, car elle n'a pas accès aux membres de la classe externe.

Pour des raisons de commodité, nous pouvons regrouper les classes statiques imbriquées dans une classe externe à des fins de lisibilité. En dehors de cela, il n’existe aucun autre cas d’utilisation de la classe imbriquée statique.

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

Si tous les dossiers font partie du dossier Res, l’outil Android génère un fichier R.java (ressources) qui contient en interne un grand nombre de classes imbriquées statiques pour chacun de leurs dossiers internes.

Voici l'aspect et la convivialité du fichier R.java généré sous Android: Ici, ils utilisent uniquement 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 string {
        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 la classe interne statique pour instancier la classe externe qui n'a qu'un constructeur privé. Vous ne pouvez pas faire la même chose avec la classe interne car vous devez créer un objet 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(String[] args) {
        OuterClass.InnerClass.test();
        // OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside.
    }
}

Ceci produira x: 1

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

  

Utilisez une classe imbriquée (ou une classe interne) non statique si vous avez besoin d'un accès.   aux champs et méthodes non publics d'une instance englobante. Utilisez un statique   classe imbriquée si vous n'avez pas besoin de cet accès.

Exemple simple:

package test;

public class UpperClass {
public static class StaticInnerClass {}

public class InnerClass {}

public static void main(String[] args) {
    // works
    StaticInnerClass stat = new StaticInnerClass();
    // doesn't compile
    InnerClass inner = new InnerClass();
}
}

Si elle n'est pas statique, la classe ne peut être instanciée que dans une instance de la classe supérieure (donc pas dans l'exemple où main est une fonction statique)

L’une des raisons de l’opposition statique et normale est liée au chargement de classes. Vous ne pouvez pas instancier une classe interne dans le constructeur de son parent.

PS: J'ai toujours compris que "imbriqué" et "intérieur" étaient interchangeables. Il peut y avoir des nuances subtiles dans les termes, mais la plupart des développeurs Java comprendraient cela non plus.

Les classes internes non statiques peuvent entraîner des fuites de mémoire, tandis que les classes internes statiques les protègent. Si la classe externe contient beaucoup de données, cela peut réduire les performances de l'application.

Je ne connais pas les différences de performances, mais comme vous le dites, la classe imbriquée statique ne fait pas partie d'une instance de la classe englobante. Cela semble plus simple de créer une classe imbriquée statique, sauf si vous en avez vraiment besoin.

C'est un peu comme pourquoi je fais toujours mes variables définitives en Java - si elles ne le sont pas, je sais qu'il se passe quelque chose de drôle. Si vous utilisez une classe interne au lieu d'une classe imbriquée statique, il devrait y avoir une bonne raison.

L'utilisation d'une classe imbriquée statique plutôt que non statique peut économiser des espaces dans certains cas. Par exemple: implémenter un comparateur dans une classe, dites étudiant.

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

Ensuite, le static garantit que la classe Student n'a qu'un seul comparateur, au lieu d'instancier un nouveau à chaque fois qu'une nouvelle instance d'étudiant est créée.

Avantages de la classe interne -

  1. utilisation unique
  2. prend en charge et améliore l'encapsulation
  3. lisibilité
  4. accès au champ privé

Sans la 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 Local Inner class
  3. Classe interne anonyme
  4. classe interne statique

point ---

  1. de la classe interne statique, nous pouvons uniquement accéder au membre statique de la classe externe.
  2. Dans la classe interne, nous ne pouvons pas déclarer de membre statique.
  3. pour appeler la classe interne normale dans la zone statique de la classe externe.

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

  4. pour appeler la classe interne normale dans la zone d'instance de la classe externe.

    Inner i = new Inner ();

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

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

  6. dans la classe intérieure Ce pointeur sur la classe intérieure.

    la classe interne this.member-current outerclassname.this - classe externe

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

    final, résumé, strictfp, + privé, protégé, statique

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

  9. une classe interne dans une méthode d'instance, nous pouvons accéder au champ d'instance et statique d'une classe externe.

Classe 10.inner dans la méthode statique, nous ne pouvons accéder qu'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
            }
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top