Classe interne Java et classe imbriquée statique


Quelle est la principale différence entre une classe interne et une classe imbriquée statique en Java? La conception / mise en œuvre joue-t-elle un rôle dans le choix de l'un d'entre eux?

Author: Micha Sprengers, 2008-09-16

24 answers

Du tutoriel Java :

Les classes imbriquées sont divisées en deux catégories: statique et non statique. Les classes imbriquées déclarées statiques sont simplement appelées classes imbriquées statiques. Les classes imbriquées non statiques sont appelées classes internes.

Les classes imbriquées statiques sont accessibles en utilisant le nom de classe englobant:

OuterClass.StaticNestedClass

Par exemple, pour créer un objet pour la classe imbriquée statique, utilisez cette syntaxe:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

Objets qui sont des instances d'un la classe interne existe dans une instance de la classe externe. Considérez les classes suivantes:

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

Une instance de InnerClass ne peut exister que dans une instance de OuterClass et a un accès direct aux méthodes et aux champs de son instance englobante.

Pour instancier une classe interne, vous devez d'abord instancier la classe externe. Ensuite, créez l'objet interne dans l'objet externe avec cette syntaxe:

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

Voir: Tutoriel Java-Classes imbriquées

Pour complétude notez qu'il existe également une classe interne sans une instance englobante :

class A {
  int t() { return 1; }
  static A a =  new A() { int t() { return 2; } };
}

Ici, new A() { ... } est une classe interne définie dans un contexte statique et n'a pas d'instance englobante.

 1511
Author: Martin, 2017-05-23 12:10:47

Le tutoriel Java dit :

Terminologie: Les classes imbriquées sont divisé en deux catégories: statique et non statique. Classes imbriquées qui sont déclarées statiques sont simplement appelés classes imbriquées statiques. Non statique les classes imbriquées sont appelées internes classe.

Dans le langage courant, les termes "imbriqué" et "intérieur" sont utilisés de manière interchangeable par la plupart des programmeurs, mais j'utiliserai le terme correct "classe imbriquée" qui couvre à la fois interne et statique.

Les classes peuvent être imbriquées ad infinitum , par exemple la classe A peut contenir la classe B qui contient la classe C qui contient la classe D, etc. Cependant, plus d'un niveau d'imbrication de classe est rare, car il s'agit généralement d'une mauvaise conception.

Il y a trois raisons pour lesquelles vous pouvez créer une classe imbriquée:

  • organisation: parfois, il semble plus judicieux de trier une classe dans l'espace de noms d'une autre classe, surtout quand elle ne sera utilisée dans aucun autre contexte
  • accès: les classes imbriquées ont un accès spécial aux variables/champs de leurs classes contenant (précisément les variables / champs dépendent du type de classe imbriquée, qu'elle soit interne ou statique).
  • commodité: avoir à créer un nouveau fichier pour chaque nouveau type est gênant, encore une fois, surtout lorsque le type ne sera utilisé que dans un seul contexte

Il ya , quatre types de classe imbriquée dans Java. En bref, ils sont:

  • classe statique : déclarée comme statique membre d'une autre classe
  • inner class : déclaré en tant que membre d'instance d'une autre classe
  • classe interne locale : déclarée dans une méthode d'instance d'une autre classe
  • classe interne anonyme : comme une classe interne locale, mais écrite comme une expression qui renvoie un objet unique

Permettez-moi de développer plus de détails.


Classes statiques

Les classes statiques sont les plus faciles à comprendre parce qu'ils n'ont rien à voir avec les instances de la classe conteneur.

Une classe statique est une classe déclarée comme membre statique d'une autre classe. Tout comme les autres membres statiques, une telle classe n'est vraiment qu'un cintre qui utilise la classe containing comme espace de noms, par exemple la classe Goat déclarée comme membre statique de la classe Rhino dans le paquet pizza est connue sous le nom pizza.Rhino.Chèvre .

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

Franchement, statique les classes sont une fonctionnalité assez inutile car les classes sont déjà divisées en espaces de noms par packages. La seule vraie raison concevable de créer une classe statique est qu'une telle classe a accès aux membres statiques privés de sa classe contenant, mais je trouve que c'est une justification assez boiteuse pour que la fonctionnalité de classe statique existe.


Classes intérieures

Une classe interne est une classe déclarée comme membre non statique d'une autre classe:

package pizza;

public class Rhino {

    public class Goat {
        ...
    }

    private void jerry() {
        Goat g = new Goat();
    }
}

Comme avec un classe statique, la classe interne est connue comme qualifiée par son nom de classe contenant, pizza.Rhino.Goat , mais à l'intérieur de la classe contenant, il peut être connu par son nom simple. Cependant, chaque instance d'une inner classe est lié à une instance de sa classe contenante: ci-dessus, la Chèvre créé dans jerry, est implicitement liée à la Rhino occurrence ce dans jerry. Sinon, nous créons l'instance Rhino associée explicite lorsque nous instancions Chèvre:

Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();

(Avis de vous reporter à l'intérieure de type juste Chèvre dans le bizarre nouveaux syntaxe: Java déduit le type contenant de la rhino partie. Et, oui nouveau rhinocéros.Goat () aurait eu plus de sens pour moi aussi.)

Alors qu'est-ce que cela nous gagne? Eh bien, l'instance de classe interne a accès aux membres de l'instance de l'instance de classe contenant. Ces membres d'instance englobants sont référencés à l'intérieur l'intérieur de la classe par juste leurs noms simples, pas via cette (ce dans l'intérieur de la classe se réfère à l'intérieur de la classe, par exemple, pas les associés contenant de l'instance de classe):

public class Rhino {

    private String barry;

    public class Goat {
        public void colin() {
            System.out.println(barry);
        }
    }
}

Dans la classe interne, vous pouvez faire référence à cede la classe contenant comme Rhino.ce, et vous pouvez utiliser ce pour désigner ses membres, par exemple Rhino.ce.barry.


Classes internes locales

Un la classe interne locale est une classe déclarée dans le corps d'une méthode. Une telle classe n'est connue que dans sa méthode containing, elle ne peut donc être instanciée et ses membres accessibles dans sa méthode containing. Le gain est qu'une instance de classe interne locale est liée et peut accéder aux variables locales finales de sa méthode contenant. Lorsque l'instance utilise un local final de sa méthode containing, la variable conserve la valeur qu'elle détenait au moment de la création de l'instance, même si la variable est sorti de sa portée (il s'agit en fait de la version brute et limitée de fermetures de Java).

Comme une classe interne locale n'est ni membre d'une classe ni d'un package, elle n'est pas déclarée avec un niveau d'accès. (Soyez clair, cependant, que ses propres membres ont des niveaux d'accès comme dans une classe normale.)

Si une classe interne locale est déclarée dans une méthode d'instance, une instanciation de la classe interne est liée à l'instance détenue par la méthode contenant this au moment de la la création de l'instance, et donc les membres de l'instance de la classe contenant sont accessibles comme dans une classe interne d'instance. Une classe interne locale est instanciée simplement via son nom, par exemple classe interne locale Catest instanciée comme new Cat(), pas new this.Cat () comme vous pouvez vous y attendre.


Classes internes anonymes

Une classe interne anonyme est un moyen syntaxiquement pratique d'écrire une classe interne locale. Le plus souvent, un local la classe interne est instanciée au plus une fois à chaque fois que sa méthode containing est exécutée. Ce serait bien, alors, si nous pouvions combiner la définition de classe interne locale et son instanciation unique en une seule forme de syntaxe pratique, et ce serait aussi bien si nous n'avions pas à imaginer un nom pour la classe (moins votre code contient de noms inutiles, mieux c'est). Une classe interne anonyme permet ces deux choses:

new *ParentClassName*(*constructorArgs*) {*members*}

Il s'agit d'une expression renvoyant une nouvelle instance d'une classe sans nom qui étend ParentClassName. Vous ne pouvez pas fournir votre propre constructeur; au contraire, on est implicitement fourni qui appelle simplement le super constructeur, donc les arguments fournis doivent correspondre au super constructeur. (Si le parent contient plusieurs constructeurs, le "plus simple" est appelé, le "plus simple" tel que déterminé par un ensemble de règles assez complexe ne vaut pas la peine d'apprendre en détail-faites simplement attention à ce que NetBeans ou Eclipse vous disent.)

Alternativement, vous pouvez spécifier un interface à mettre en œuvre:

new *InterfaceName*() {*members*}

Une telle déclaration crée une nouvelle instance d'une classe sans nom qui étend Object et implémente InterfaceName. Encore une fois, vous ne pouvez pas fournir votre propre constructeur; dans ce cas, Java fournit implicitement un constructeur no-arg, do-nothing (il n'y aura donc jamais d'arguments de constructeur dans ce cas).

Même si vous ne pouvez pas donner à une classe interne anonyme un constructeur, vous pouvez toujours effectuer n'importe quelle configuration à l'aide d'un bloc d'initialisation (a {} bloc placé en dehors de toute méthode).

Soyez clair qu'une classe interne anonyme est simplement un moyen moins flexible de créer une classe interne locale avec une instance. Si vous voulez une classe interne locale qui implémente plusieurs interfaces ou qui implémente des interfaces tout en étendant une classe autre que Object ou qui spécifie son propre constructeur, vous êtes bloqué en créant une classe interne locale nommée régulière.

 531
Author: Jegschemesch, 2017-08-04 08:40:03

Je ne pense pas que la vraie différence soit devenue claire dans les réponses ci-dessus.

D'abord pour obtenir les bons termes:

  • Une classe imbriquée est une classe qui est contenue dans une autre classe au niveau du code source.
  • , Il est statique si vous déclarez avec le static modificateur.
  • Une classe imbriquée non statique est appelée classe interne. (Je reste avec une classe imbriquée non statique.)

La réponse de Martin est juste jusqu'à présent. Cependant, la question réelle est: Qu'est-ce que le but de déclarer une classe imbriquée statique ou non?

Vous utilisez static classes imbriquées si vous voulez garder vos classes si elles appartiennent topique ensemble, ou si la classe imbriquée est exclusivement utilisé dans la classe englobante. Il n'y a pas de différence sémantique entre une classe imbriquée statique et toutes les autres classes.

Les classes imbriquées non statiques sont une bête différente. Similaires aux classes internes anonymes, ces classes imbriquées sont en fait des fermetures. Que signifie qu'ils capturent leur portée environnante et leur instance englobante et rendent cela accessible. Peut-être qu'un exemple clarifiera cela. Voir ce talon d'un Conteneur:

public class Container {
    public class Item{
        Object data;
        public Container getContainer(){
            return Container.this;
        }
        public Item(Object data) {
            super();
            this.data = data;
        }

    }

    public static Item create(Object data){
        // does not compile since no instance of Container is available
        return new Item(data);
    }
    public Item createSubItem(Object data){
        // compiles, since 'this' Container is available
        return new Item(data);
    }
}

Dans ce cas, vous souhaitez avoir une référence d'un élément enfant vers le conteneur parent. En utilisant une classe imbriquée non statique, cela fonctionne sans travail. Vous pouvez accéder à l'instance englobante du conteneur avec la syntaxe Container.this.

Explications plus hardcore suivantes:

Si vous regardez le Java bytecodes que le compilateur génère pour une classe imbriquée (non statique), cela pourrait devenir encore plus clair:

// class version 49.0 (49)
// access flags 33
public class Container$Item {

  // compiled from: Container.java
  // access flags 1
  public INNERCLASS Container$Item Container Item

  // access flags 0
  Object data

  // access flags 4112
  final Container this$0

  // access flags 1
  public getContainer() : Container
   L0
    LINENUMBER 7 L0
    ALOAD 0: this
    GETFIELD Container$Item.this$0 : Container
    ARETURN
   L1
    LOCALVARIABLE this Container$Item L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 1
  public <init>(Container,Object) : void
   L0
    LINENUMBER 12 L0
    ALOAD 0: this
    ALOAD 1
    PUTFIELD Container$Item.this$0 : Container
   L1
    LINENUMBER 10 L1
    ALOAD 0: this
    INVOKESPECIAL Object.<init>() : void
   L2
    LINENUMBER 11 L2
    ALOAD 0: this
    ALOAD 2: data
    PUTFIELD Container$Item.data : Object
    RETURN
   L3
    LOCALVARIABLE this Container$Item L0 L3 0
    LOCALVARIABLE data Object L0 L3 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

Comme vous pouvez le voir, le compilateur crée un champ caché Container this$0. Ceci est défini dans le constructeur qui a un paramètre supplémentaire de type Container pour spécifier l'instance englobante. Vous ne pouvez pas voir ce paramètre dans la source mais le compilateur le génère implicitement pour une classe imbriquée.

Exemple de Martin

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

Serait donc compilé en un appel de quelque chose comme (dans code-barres)

new InnerClass(outerObject)

, Par souci d'exhaustivité:

Une classe anonyme est un exemple parfait d'une classe imbriquée non statique qui n'a tout simplement aucun nom associé et ne peut pas être référencée plus tard.

 126
Author: jrudolph, 2013-08-27 07:53:39

Je pense qu'aucune des réponses ci-dessus ne vous explique la différence réelle entre une classe imbriquée et une classe imbriquée statique en termes de conception d'application:

Aperçu

Une classe imbriquée peut être non statique ou statique, et dans chaque cas, est une classe définie à l'intérieur d'une autre classe. Une classe imbriquée ne devrait exister que pour servir à enfermer la classe , si une classe imbriquée est utile par d'autres classes (pas seulement l'enfermant), devrait être déclarée comme niveau supérieur classe.

Différence

Classe imbriquée non statique : est implicitement associée à l'instance englobante de la classe contenant, cela signifie qu'il est possible d'invoquer des méthodes et des variables d'accès de l'instance englobante. Une utilisation courante d'une classe imbriquée non statique consiste à définir une classe d'adaptateur.

Classe imbriquée statique: impossible d'accéder à l'instance de classe englobante et d'y invoquer des méthodes, elle doit donc être utilisée lorsque la classe imbriquée ne nécessite pas d'accès à une instance de la classe englobante . Une utilisation courante de la classe imbriquée statique consiste à implémenter un composant de l'objet externe.

Conclusion

Donc, la principale différence entre les deux du point de vue de la conception est: la classe imbriquée non statique peut accéder à l'instance de la classe container, tandis que la statique ne peut pas .

 83
Author: aleroot, 2015-02-28 23:47:23

En termes simples, nous avons besoin de classes imbriquées principalement parce que Java ne fournit pas de fermetures.

Les classes imbriquées sont des classes définies dans le corps d'une autre classe englobante. Ils sont de deux types statiques et non statiques.

Ils sont traités comme des membres de la classe englobante, d'où vous pouvez spécifier l'un des quatre spécificateurs d'accès - private, package, protected, public. Nous n'avons pas ce luxe avec des classes de haut niveau, qui ne peuvent être déclarées public ou package-private.

Classes intérieures les classes aka Non-stack ont accès aux autres membres de la classe supérieure, même si elles sont déclarées privées tandis que les classes imbriquées statiques n'ont pas accès aux autres membres de la classe supérieure.

public class OuterClass {
    public static class Inner1 {
    }
    public class Inner2 {
    }
}

Inner1 est notre classe interne statique et Inner2 est notre classe interne qui n'est pas statique. La principale différence entre eux, vous ne pouvez pas créer une instance Inner2 sans un Outer where car vous pouvez créer un objet Inner1 indépendamment.

Quand utiliseriez-vous Inner class?

Pensez à un situation où Class A et Class B sont liées, Class B besoin d'accéder Class A membres, et Class B est lié uniquement à Class A. Les classes internes entrent dans l'image.

Pour créer une instance de classe interne, vous devez créer une instance de votre classe externe.

OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();

Ou

OuterClass.Inner2 inner = new OuterClass().new Inner2();

Quand utiliseriez-vous la classe interne statique?

Vous définiriez une classe interne statique lorsque vous savez qu'elle n'a aucune relation avec l'instance de la classe/top englobante classe. Si votre classe interne n'utilise pas de méthodes ou de champs de la classe externe, c'est juste un gaspillage d'espace, alors rendez-le statique.

Par exemple, pour créer un objet pour la classe imbriquée statique, utilisez cette syntaxe:

OuterClass.Inner1 nestedObject = new OuterClass.Inner1();

L'avantage d'une classe imbriquée statique est qu'elle n'a pas besoin d'un objet de la classe contenant/classe supérieure pour fonctionner. Cela peut vous aider à réduire le nombre d'objets créés par votre application lors de l'exécution.

 29
Author: Thalaivar, 2017-01-02 05:15:01

Je pense que la convention qui est généralement suivie est la suivante:

  • classe statique {[9] } dans une classe de niveau supérieur est une classe imbriquée
  • classe non statique dans une classe de niveau supérieur est une classe interne, qui en outre a deux plus de forme:
    • classe locale - classes nommées déclarées à l'intérieur d'un bloc comme une méthode ou un corps de constructeur
    • classe anonyme - classes sans nom dont les instances sont créées dans des expressions et déclarations

Cependant, peu d'autres points pour se souvenir de sont:

  • Les classes de niveau supérieur et la classe imbriquée statique sont sémantiquement les mêmes sauf que dans le cas d'une classe imbriquée statique, elle peut faire référence statique à des champs/méthodes statiques privés de sa classe externe [parent] et vice versa.

  • Les classes internes ont accès aux variables d'instance de l'instance englobante de la classe externe [parent]. Cependant, toutes les classes internes n'ont pas enfermer des instances, par exemple des classes internes dans des contextes statiques, comme une classe anonyme utilisée dans un bloc d'initialisation statique, ne le fait pas.

  • La classe anonyme par défaut étend la classe parente ou implémente l'interface parente et il n'y a pas de clause supplémentaire pour étendre une autre classe ou implémenter d'autres interfaces. Donc,

    • new YourClass(){}; signifie class [Anonymous] extends YourClass {}
    • new YourInterface(){}; signifie class [Anonymous] implements YourInterface {}

Je pense que la plus grande question qui reste ouvert lequel utiliser et quand? Eh bien, cela dépend principalement du scénario auquel vous avez affaire, mais la lecture de la réponse donnée par @jrudolph peut vous aider à prendre une décision.

 24
Author: sactiw, 2013-01-24 05:40:10

Voici les principales différences et similitudes entre la classe interne Java et la classe imbriquée statique.

J'espère que ça aide!

Classe intérieure

  • Peut accéder à à la classe externe à la fois instance et statique méthodes et champs
  • Associé à l'instance de la classe englobante, donc instancier il a d'abord besoin d'une instance de l'extérieur de la classe (note nouveaux clé endroit):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • Ne peut pas définir le tout membres statiques lui

  • Ne ont Classe ou Interface déclaration de

Classe imbriquée statique

  • Ne peut pas accéder extérieur de la classe occurrence méthodes ou des champs

  • Non associé à une instance de la classe englobante Afin de l'instancier:

    OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
    

Similitudes

  • Les deux classes internes peuvent accéder même à privé champs et méthodes de classe externe
  • Aussi Extérieur de la classe ont accès à private champs et les méthodes de les classes internes
  • Les deux classes peuvent avoir un modificateur d'accès privé, protégé ou public

Pourquoi Utiliser des Classes Imbriquées?

Selon la documentation Oracle, il y a plusieurs raisons (documentation complète):

  • C'est un moyen de regrouper logiquement des classes qui ne sont que utilisé en un seul endroit: Si une classe n'est utile qu'à une autre classe, il est logique de l'intégrer dans cette classe et de garder les deux ensemble. L'imbrication de telles" classes auxiliaires " rend leur package plus simplifié.

  • Cela augmente l'encapsulation: Considérons deux classes de niveau supérieur, A et B, où B a besoin d'un accès aux membres de A qui seraient autrement déclarés privés. En masquant la classe B dans la classe A, les membres de A peuvent être déclarés privés et B peut y accéder. Dans en outre, B lui-même peut être caché du monde extérieur.

  • Cela peut conduire à un code plus lisible et maintenable: L'imbrication de petites classes dans des classes de niveau supérieur rapproche le code de l'endroit où il est utilisé.

 23
Author: Behzad Bahmanyar, 2017-04-26 07:39:52

Classe imbriquée: classe dans la classe

Types:

  1. Classe imbriquée statique
  2. Classe imbriquée non statique [Classe interne]

Différence:

Classe imbriquée non statique [Classe interne]

Dans la classe imbriquée non statique, l'objet de la classe interne existe dans l'objet de la classe externe. Donc, ce membre de données de la classe externe est accessible à la classe interne. Donc pour créer un objet de classe interne nous devons créer un objet de classe externe premier.

outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass(); 

Classe imbriquée statique

Dans la classe imbriquée statique, l'objet de la classe interne n'a pas besoin d'objet de la classe externe, car le mot "statique" indique qu'il n'est pas nécessaire de créer un objet.

class outerclass A {
    static class nestedclass B {
        static int x = 10;
    }
}

Si vous souhaitez accéder à x, écrivez la méthode intérieure suivante

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);
 13
Author: tejas, 2015-05-10 23:57:03

L'instance de la classe interne est créée lorsque l'instance de la classe externe est créée. Par conséquent, les membres et les méthodes de la classe interne ont accès aux membres et aux méthodes de l'instance (objet) de la classe externe. Lorsque l'instance de la classe externe sort de la portée, les instances de classe interne cessent également d'exister.

La classe imbriquée statique n'a pas d'instance concrète. C'est juste chargé lorsqu'il est utilisé pour la première fois (tout comme les méthodes statiques). C'est un entité complètement indépendante, dont les méthodes et les variables n'ont aucun accès aux instances de la classe externe.

Les classes imbriquées statiques ne sont pas couplées à l'objet externe, elles sont plus rapides et ne prennent pas de mémoire tas/pile, car il n'est pas nécessaire de créer une instance d'une telle classe. Par conséquent, la règle empirique est d'essayer de définir une classe imbriquée statique, avec une portée aussi limitée que possible (private >= class >= protected >= public), puis de la convertir en classe interne (par retrait "statique" identifiant) et desserrer la portée, si c'est vraiment nécessaire.

 10
Author: rmaruszewski, 2008-09-16 08:58:40

Il y a une subtilité sur l'utilisation de classes statiques imbriquées qui pourrait être utile dans certaines situations.

Alors que les attributs statiques sont instanciés avant que la classe ne soit instanciée via son constructeur, les attributs statiques à l'intérieur des classes statiques imbriquées ne semblent pas être instanciés avant le le constructeur de la classe est invoqué, ou du moins pas avant que les attributs ne soient référencés pour la première fois, même si elles sont marquées comme "finales".

Considérez ceci exemple:

public class C0 {

    static C0 instance = null;

    // Uncomment the following line and a null pointer exception will be
    // generated before anything gets printed.
    //public static final String outerItem = instance.makeString(98.6);

    public C0() {
        instance = this;
    }

    public String makeString(int i) {
        return ((new Integer(i)).toString());
    }

    public String makeString(double d) {
        return ((new Double(d)).toString());
    }

    public static final class nested {
        public static final String innerItem = instance.makeString(42);
    }

    static public void main(String[] argv) {
        System.out.println("start");
        // Comment out this line and a null pointer exception will be
        // generated after "start" prints and before the following
        // try/catch block even gets entered.
        new C0();
        try {
            System.out.println("retrieve item: " + nested.innerItem);
        }
        catch (Exception e) {
            System.out.println("failed to retrieve item: " + e.toString());
        }
        System.out.println("finish");
    }
}

Même si 'imbriqué' et 'innerItem' sont tous deux déclarés comme 'static final'. paramètre de imbriqués.innerItem n'a lieu qu'après l'instanciation de la classe (ou du moins pas avant que l'élément statique imbriqué soit référencé pour la première fois), comme vous pouvez le voir par vous - même en commentant et décommentant les lignes auxquelles je me réfère, ci-dessus. La même chose ne tient pas vrai pour "outerItem".

Au moins c'est ce que je vois dans Java 6.0.

 10
Author: HippoMan, 2010-03-26 12:48:47

Dans le cas de la création d'une instance, l'instance de non la classe interne statique est créée avec la référence de objet de la classe externe dans laquelle il est défini. Ce signifie qu'il a une instance inclosante. Mais l'instance de la classe interne statique est créé avec la référence de la classe externe, pas avec la référence de l'objet de la classe externe. Cela signifie qu'il n'avez pas d'instance inclosante.

Par exemple:

class A
{
  class B
  {
    // static int x; not allowed here…..    
  }
  static class C
  {
    static int x; // allowed here
  }
}

class Test
{
  public static void main(String… str)
  {
    A o=new A();
    A.B obj1 =o.new B();//need of inclosing instance

    A.C obj2 =new A.C();

    // not need of reference of object of outer class….
  }
}
 9
Author: Ankit Jain, 2013-11-14 12:43:57

Je ne pense pas qu'il y ait grand-chose à ajouter ici, la plupart des réponses expliquent parfaitement les différences entre la classe imbriquée statique et les classes internes. Cependant, considérez le problème suivant lors de l'utilisation de classes imbriquées par rapport aux classes internes. Comme mentionné dans quelques réponses, les classes internes ne peuvent pas être instanciées sans et instance de leur classe englobante, ce qui signifie qu'elles DÉTIENNENT un pointeur vers l'instance de leur classe englobante, ce qui peut entraîner un débordement de mémoire ou un débordement de pile exception due au fait que le GC ne pourra pas récupérer les classes englobantes même si elles ne sont plus utilisées. Pour clarifier cela, vérifiez le code suivant:

public class Outer {


    public  class Inner {

    }


    public Inner inner(){
        return new Inner();
    }

    @Override
    protected void finalize() throws Throwable {
    // as you know finalize is called by the garbage collector due to destroying an object instance
        System.out.println("I am destroyed !");
    }
}


public static void main(String arg[]) {

    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();

    // out instance is no more used and should be garbage collected !!!
    // However this will not happen as inner instance is still alive i.e used, not null !
    // and outer will be kept in memory until inner is destroyed
    outer = null;

    //
    // inner = null;

    //kick out garbage collector
    System.gc();

}

Si vous supprimez le commentaire sur // inner = null; Le programme sera mis "je suis détruit !", mais en gardant cela commenté, il ne sera pas.
La raison en est que l'instance interne blanche est toujours référencée GC ne peut pas la collecter et parce qu'elle fait référence (a un pointeur vers) à l'instance externe, elle n'est pas collectée trop. Avoir assez de ces objets dans votre projet et peut manquer de mémoire.
Par rapport aux classes internes statiques qui ne contiennent pas de point à l'instance de classe interne car ce n'est pas lié à l'instance mais à la classe. Le programme ci-dessus peut imprimer "je suis détruit ! " si vous rendez la classe interne statique et instanciée avec Outer.Inner i = new Outer.Inner();

 9
Author: Adelin, 2016-11-15 09:27:24

Les termes sont utilisés de manière interchangeable. Si vous voulez être vraiment pédant à ce sujet, alors vous pourriez définir "classe imbriquée" pour faire référence à une classe interne statique, qui n'a pas d'instance englobante. Dans le code, vous pourriez avoir quelque chose comme ceci:

public class Outer {
    public class Inner {}

    public static class Nested {}
}

Ce n'est pas vraiment une définition largement acceptée cependant.

 7
Author: Daniel Spiewak, 2008-09-16 08:25:42

La classe imbriquée est un terme très général: toute classe qui n'est pas de niveau supérieur est une classe imbriquée. Une classe interne est une classe imbriquée non statique. Joseph Darcy a écrit une très belle explication sur Les classes imbriquées, Internes, Membres et de haut Niveau .

 7
Author: Wouter Coekaerts, 2012-08-03 02:31:14

{[2] }mM... une classe interne EST une classe imbriquée... voulez-vous dire classe anonyme et classe intérieure?

Edit: Si vous vouliez dire inner vs anonymous... une classe interne est juste une classe définie dans une classe telle que:

public class A {
    public class B {
    }
}

Alors qu'une classe anonyme est une extension d'une classe définie anonymement, donc aucune " classe réelle n'est définie, comme dans:

public class A {
}

A anon = new A() { /* you could change behavior of A here */ };

Modifier davantage:

Wikipedia prétend qu'il y a une différence en Java, mais je travaille avec Java depuis 8 des années, et c'est la première fois que j'entends une telle distinction... sans oublier qu'il n'y a aucune référence pour étayer la réclamation... en bout de ligne, une classe interne est une classe définie dans une classe (statique ou non), et imbriquée est juste un autre terme pour signifier la même chose.

Il existe une différence subtile entre les classes imbriquées statiques et non statiques... fondamentalement, les classes internes non statiques ont un accès implicite aux champs d'instance et aux méthodes de la classe englobante (elles ne peuvent donc pas être construites dans un contexte statique, ce sera une erreur du compilateur). Les classes imbriquées statiques, en revanche, n'ont pas d'accès implicite aux champs et méthodes d'instance et PEUVENT être construites dans un contexte statique.

 6
Author: Mike Stone, 2014-11-28 03:49:57

Ciblage des apprenants novices en Java et / ou en Classes imbriquées

Les classes imbriquées peuvent être soit:
1. Classes imbriquées statiques.
2. Classes imbriquées non statiques. (aussi connu sous le nom de Inner classes) = > Veuillez vous souvenir de ceci


1.Classes internes
Exemple:

class OuterClass  {
/*  some code here...*/
     class InnerClass  {  }
/*  some code here...*/
}


les classes internes sont des sous-ensembles de classes imbriquées:

  • la classe interne est un type spécifique de classe imbriquée
  • les classes internes sont sous-ensembles de classes imbriquées
  • , Vous pouvez dire qu'un intérieur de la classe est aussi une classe imbriquée, mais vous pouvez PAS dire qu'une classe imbriquée est également un intérieur classe.

Spécialité de la classe intérieure:

  • instance d'une classe interne a accès à tous les des membres de la classe externe, même ceux qui sont marqués "privé"


2.Classes imbriquées statiques:
Exemple:

class EnclosingClass {
  static class Nested {
    void someMethod() { System.out.println("hello SO"); }
  }
}

Cas 1: Instancier une classe imbriquée statique à partir d'une classe non englobante

class NonEnclosingClass {

  public static void main(String[] args) {
    /*instantiate the Nested class that is a static
      member of the EnclosingClass class:
    */

    EnclosingClass.Nested n = new EnclosingClass.Nested(); 
    n.someMethod();  //prints out "hello"
  }
}

Cas 2: Instancier une classe imbriquée statique à partir d'une classe englobante

class EnclosingClass {

  static class Nested {
    void anotherMethod() { System.out.println("hi again"); } 
  }

  public static void main(String[] args) {
    //access enclosed class:

    Nested n = new Nested(); 
    n.anotherMethod();  //prints out "hi again"
  }

}

Spécialité des classes statiques:

  • La classe interne statique n'aurait accès qu'aux membres statiques de la classe externe et n'aurait pas accès aux membres non statiques.

Conclusion:
Question: Quelle est la principale différence entre un intérieur classe et un classe imbriquée statique en Java?
Réponse: il suffit de passer en revue les spécificités de chaque classe mentionnée ci-dessus.

 6
Author: VedX, 2015-11-06 21:47:56

La classe interne et la classe statique imbriquée en Java sont toutes deux des classes déclarées dans une autre classe, connue sous le nom de classe de niveau supérieur en Java. Dans la terminologie Java, Si vous déclarez une classe imbriquée statique, elle sera appelée classe statique imbriquée en Java tandis que les classes imbriquées non statiques sont simplement appelées classe interne.

Qu'est-ce que la classe interne en Java?

Toute classe qui n'est pas un niveau supérieur ou déclarée dans une autre classe est connue sous le nom de classe imbriquée et hors de celles-ci les classes imbriquées, les classes déclarées non statiques sont connues sous le nom de classe interne en Java. il existe trois types de classe interne en Java:

1) Classe interne locale - est déclarée dans un bloc de code ou une méthode.
2) Classe interne anonyme - est une classe qui n'a pas de nom à référencer et initialisée au même endroit où elle est créée.
3) Classe interne membre - est déclaré comme membre non statique de la classe externe.

public class InnerClassTest {
    public static void main(String args[]) {      
        //creating local inner class inside method i.e. main() 
        class Local {
            public void name() {
                System.out.println("Example of Local class in Java");

            }
        }      
        //creating instance of local inner class
        Local local = new Local();
        local.name(); //calling method from local inner class

        //Creating anonymous inner class in Java for implementing thread
        Thread anonymous = new Thread(){
            @Override
            public void run(){
                System.out.println("Anonymous class example in java");
            }
        };
        anonymous.start();

        //example of creating instance of inner class
        InnerClassTest test = new InnerClassTest();
        InnerClassTest.Inner inner = test.new Inner();
        inner.name(); //calling method of inner class
    }

     //Creating Inner class in Java
    private class Inner{
        public void name(){
            System.out.println("Inner class example in java");
        }
    }
}

Qu'est-ce que la classe statique imbriquée Java?

La classe statique imbriquée est une autre classe qui est déclarée dans une classe en tant que membre et rendue statique. La classe statique imbriquée est également déclarée comme membre de la classe externe et peut être rendue privée, publique ou protégée comme tout autre membre. L'un des principaux avantages de la classe statique imbriquée par rapport à la classe interne est que l'instance de la classe statique imbriquée n'est attachée à aucune instance englobante de la classe externe. Vous n'avez également besoin d'aucune instance de classe externe pour créer une instance de imbriquée classe statique en Java.

1) Il peut accéder aux membres de données statiques de la classe externe, y compris private.
2) La classe imbriquée statique ne peut pas accéder à membre de données non statique (instance) ou méthode .

public class NestedStaticExample {
    public static void main(String args[]){  
        StaticNested nested = new StaticNested();
        nested.name();
    }  
    //static nested class in java
    private static class StaticNested{
        public void name(){
            System.out.println("static nested class example in java");
        }
    }
}

Ref: Classe interne et classe statique imbriquée en Java avec Exemple

 5
Author: roottraveller, 2017-03-22 10:39:26

Je pense que les gens ici devraient remarquer que : Classe Nest statique seulement la première classe interne. Par exemple:

 public static class A {} //ERROR

 public class A {
     public class B {
         public static class C {} //ERROR
     }
 }

 public class A {
     public static class B {} //COMPILE !!!

 }

Donc, résumez, la classe statique ne dépend pas de la classe qu'elle contient. Donc, ils ne peuvent pas en classe normale. (parce que la classe normale a besoin d'une instance).

 4
Author: hqt, 2013-08-21 18:10:14

Lorsque nous déclarons une classe membre statique à l'intérieur d'une classe, elle est appelée classe imbriquée de niveau supérieur ou classe imbriquée statique. Il peut être démontré comme ci-dessous :

class Test{
    private static int x = 1;
        static class A{
        private static int y = 2;
        public static int getZ(){
            return B.z+x;
        }
    }
    static class B{
        private static int z = 3;
        public static int getY(){
            return A.y;
        }
    }
}

class TestDemo{
     public static void main(String[] args){
        Test t = new Test();
        System.out.println(Test.A.getZ());
        System.out.println(Test.B.getY());
    }
}

Lorsque nous déclarons une classe membre non statique à l'intérieur d'une classe, elle est connue sous le nom de classe interne. La classe intérieure peut être démontrée comme ci-dessous:

    class Test{
        private int i = 10;
        class A{
            private int i =20;
            void display(){
            int i = 30;
            System.out.println(i);
            System.out.println(this.i);
            System.out.println(Test.this.i);
        }
    }
}
 4
Author: Pankti, 2016-12-02 17:00:09

Voici un exemple de static nested class et inner class:

Classe externe.java

public class OuterClass {
     private String someVariable = "Non Static";

     private static String anotherStaticVariable = "Static";  

     OuterClass(){

     }

     //Nested classes are static
     static class StaticNestedClass{
        private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable"; 

        //can access private variables declared in the outer class
        public static void getPrivateVariableofOuterClass(){
            System.out.println(anotherStaticVariable);
        }
     }

     //non static
     class InnerClass{

         //can access private variables of outer class
         public String getPrivateNonStaticVariableOfOuterClass(){
             return someVariable;
         }
     }

     public static void accessStaticClass(){
         //can access any variable declared inside the Static Nested Class 
         //even if it private
         String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable; 
         System.out.println(var);
     }

}

OuterClassTest:

public class OuterClassTest {
    public static void main(String[] args) {

        //access the Static Nested Class
        OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();

        //test the private variable declared inside the static nested class
        OuterClass.accessStaticClass();
        /*
         * Inner Class Test
         * */

        //Declaration

        //first instantiate the outer class
        OuterClass outerClass = new OuterClass();

        //then instantiate the inner class
        OuterClass.InnerClass innerClassExample =  outerClass. new InnerClass();

        //test the non static private variable
        System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass()); 

    }

}
 2
Author: Pritam Banerjee, 2017-01-03 23:10:14

La différence est qu'une déclaration de classe imbriquée qui est également statique peut être instanciée en dehors de la classe englobante.

Lorsque vous avez une déclaration de classe imbriquée qui estpas statique, également connue sous le nom deinner class , Java ne vous laissera pas l'instancier sauf via la classe englobante. L'objet créé à partir de la classe interne est lié à l'objet créé à partir de la classe externe, de sorte que la classe interne peut référencer les champs de la classe externe.

Mais si c'est statique, alors le lien n'existe pas, les champs externes ne sont pas accessibles (sauf via une référence ordinaire comme tout autre objet) et vous pouvez donc instancier la classe imbriquée par elle-même.

 0
Author: DigitalRoss, 2016-09-23 21:40:09

Tout d'abord, il n'y a pas une telle classe appelée classe statique.Le modificateur Static use with inner class (appelé Classe imbriquée) indique qu'il s'agit d'un membre statique de la classe Externe, ce qui signifie que nous pouvons y accéder comme avec d'autres membres statiques et sans avoir d'instance de classe externe. (Ce qui est l'avantage de statique à l'origine.)

La différence entre l'utilisation de la classe imbriquée et de la classe interne régulière est:

OuterClass.InnerClass inner = new OuterClass().new InnerClass();

D'abord, nous pouvons instancier Outerclass puis nous pouvons accéder à Inner.

Mais si la classe est imbriquée, la syntaxe est:

OuterClass.InnerClass inner = new OuterClass.InnerClass();

Qui utilise la syntaxe statique comme implémentation normale du mot-clé statique.

 0
Author: Sohi, 2017-06-01 19:18:01

J'ai illustré divers scénarios corrects et d'erreur possibles qui peuvent se produire dans le code java.

    class Outter1 {

        String OutStr;

        Outter1(String str) {
            OutStr = str;
        }

        public void NonStaticMethod(String st)  {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            //  below static attribute not permitted
            // static String tempStatic1 = "static";    

            //  below static with final attribute not permitted         
            // static final String  tempStatic1 = "ashish";  

            // synchronized keyword is not permitted below          
            class localInnerNonStatic1 {            

                synchronized    public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /* 
        //  static method with final not permitted
          public static void innerStaticMethod(String str11) { 

                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }                            

        }

        public static  void StaticMethod(String st)     {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            // static attribute not permitted below
            //static String tempStatic1 = "static";     

            //  static with final attribute not permitted below
            // static final String  tempStatic1 = "ashish";                         

            class localInnerNonStatic1 {
                public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /*
    // static method with final not permitted
    public static void innerStaticMethod(String str11) {  
                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }    

        }

        // synchronized keyword is not permitted
        static  class inner1 {          

            static String  temp1 = "ashish";
            String  tempNonStatic = "ashish";
            // class localInner1 {

            public void innerMethod(String str11) {
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            public static void innerStaticMethod(String str11) {
                //  error in below step
                str11 = temp1 +" india";    
                //str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }
            //}
        }

        //synchronized keyword is not permitted below
        class innerNonStatic1 {             

//This is important we have to keep final with static modifier in non
// static innerclass below
            static final String  temp1 = "ashish";  
            String  tempNonStatic = "ashish";
            // class localInner1 {

            synchronized    public void innerMethod(String str11) {
                tempNonStatic = tempNonStatic +" ...";
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            /*
            //  error in below step
            public static void innerStaticMethod(String str11) {   
                            //  error in below step
                            // str11 = tempNonStatic +" india";                     
                            str11 = temp1 +" india";
                            System.out.println("innerMethod ===> "+str11);
                        }*/
                    //}
                }
    }
 0
Author: Ashish Sharma, 2017-10-11 06:50:50

Juste quelques ajouts après avoir lu le tutoriel java d'oracle dans les classes et les objets. Cela peut aider si vous connaissez le modèle de mémoire de Java pour la classe interne et la classe imbriquée statique. Veuillez lire les trois questions suivantes pour comprendre pourquoi la classe interne et la classe imbriquée statique sont conçues par Java de cette manière. Et puis vous savez peut-être quand utiliser la classe interne et quand utiliser la classe imbriquée statique.

Comment l'objet de classe interne réside - t-il en mémoire?

De Mémoire gestion-Classe statique interne en Java

Quand une classe imbriquée statique (et ses membres statiques) est-elle chargée en mémoire?

Lisez ensuite ceci pour comparer la classe interne et la classe imbriquée statique.

Quel est l'avantage de rendre une classe interne statique avec Java?

 0
Author: Han XIAO, 2018-07-24 04:33:32