Classe interne Java et classe imbriquée statique


1766

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'une d'entre elles?


65
La réponse de Joshua Bloch est en lecture efficace Javaitem 22 : Favor static member classes over non static
Raymond Chenon

4
Pour mémoire, c'est le point 24 de la 3e édition du même livre.
ZeroCool

Réponses:


1697

Depuis le tutoriel Java :

Les classes imbriquées sont divisées en deux catégories: statiques et non statiques. 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 à l'aide du nom de classe qui les entoure:

OuterClass.StaticNestedClass

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

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

Les objets qui sont des instances d'une classe interne existent 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 outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

voir: Tutoriel Java - Classes imbriquées

Pour être complet, notez qu'il existe également une classe interne sans 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.


130
N'oubliez pas que vous pouvez également importer directement une classe imbriquée statique, c'est-à-dire que vous pouvez le faire (en haut du fichier): import OuterClass.StaticNestedClass; puis référencer la classe tout comme OuterClass.
Camilo Díaz Repka

4
@Martin existe-t-il un nom technique spécifique pour cet idiome de création d'une classe interne OuterClass.InnerClass innerObject = outerObject.new InnerClass();?
Geek

7
Quelle est donc l'utilisation de la classe imbriquée statique privée? Je pense que nous ne pouvons pas l'instancier de l'extérieur comme OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass ();
RoboAlex

1
@Ilya Kogan: Je voulais dire que je sais que nous pouvons accéder aux champs de classe des parents statiques ou non statiques (si la classe enfant est une classe non statique), j'ai utilisé leurs fonctionnalités plusieurs fois, mais je me demandais quel type de modèle de mémoire ils suivent? les concepts POO les couvrent-ils comme un concept distinct? sinon où ils s'intègrent vraiment dans la POO. On dirait une classe d'amis pour moi :)
Mubashar

4
@martin, je sais que j'arrive à ce fil incroyablement tard mais: c'est votre variable, a, qui est un champ statique de la classe, A. Cela ne signifie pas la classe anonyme créée par 'new A () {int t () {retour 2; }} 'est statique plus que si j'attribuais simplement un autre objet au champ statique, a, comme dans: class B {static void main (string s) {Aa = new A ()}} (A & B in same package) Cela ne fait pas de A une classe statique. L'expression «contexte statique», dans la référence citée dans le fil auquel vous avez lié, est incroyablement vague. En fait, cela a été noté dans de nombreux commentaires dans ce fil.
GrantRobertson

599

Le tutoriel Java dit :

Terminologie: les classes imbriquées sont divisées en deux catégories: statiques et non statiques. 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.

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 intérieur et statique.

Les classes peuvent être imbriquées à l' infini , 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 existe trois raisons pour lesquelles vous pouvez créer une classe imbriquée:

  • organisation: il semble parfois plus judicieux de trier une classe dans l'espace de noms d'une autre classe, surtout lorsqu'elle ne sera pas utilisée dans un autre contexte
  • accès: les classes imbriquées ont un accès spécial aux variables / champs de leurs classes contenant (précisément quelles variables / champs dépendent du type de classe imbriquée, qu'elle soit interne ou statique).
  • commodité: devoir 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 existe quatre types de classes imbriquées en Java . En bref, ce sont:

  • classe statique : déclarée comme membre statique d'une autre classe
  • classe interne : déclarée comme membre d'instance d'une autre classe
  • classe interne locale : déclarée à l'intérieur d'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 en détail.


Classes statiques

Les classes statiques sont les plus faciles à comprendre car elles 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 en fait qu'un cintre qui utilise la classe conteneur 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 de pizza.Rhino.Goat .

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

Franchement, les classes statiques sont une fonctionnalité assez inutile car les classes sont déjà divisées en espaces de noms par des packages. La seule vraie raison concevable pour créer une classe statique est qu'une telle classe a accès aux membres statiques privés de sa classe contenante, mais je trouve que c'est une justification assez boiteuse pour que la fonction 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 une 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, elle peut être connue par son nom simple. Cependant, chaque instance d'une classe interne est liée à une instance particulière de sa classe conteneur: ci-dessus, le Goat créé dans jerry , est implicitement lié à l' instance de Rhino this dans jerry . Sinon, nous rendons l' instance Rhino associée explicite lorsque nous instancions Goat :

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

(Remarquez que vous faites référence au type interne comme simplement Goat dans la nouvelle syntaxe étrange : Java déduit le type contenant de la partie rhino . Et, oui, new rhino.Goat () aurait été plus logique pour moi aussi.)

Alors qu'est-ce que cela nous apporte? Eh bien, l'instance de classe interne a accès aux membres d'instance de l'instance de classe conteneur. Ces membres d'instance englobants sont référencés à l'intérieur de la classe interne via seulement leurs noms simples, pas via ceci ( ceci dans la classe interne fait référence à l'instance de classe interne, pas l'instance de classe contenant associée):

public class Rhino {

    private String barry;

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

Dans la classe interne, vous pouvez vous référer à cette de la classe contenant comme Rhino.this , et vous pouvez utiliser ce pour se référer à ses membres, par exemple Rhino.this.barry .


Classes internes locales

Une 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 conteneur, elle ne peut donc être instanciée et accéder à ses membres que dans sa méthode conteneur. 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 conteneur. Lorsque l'instance utilise un local final de sa méthode conteneur, la variable conserve la valeur qu'elle détenait au moment de la création de l'instance, même si la variable est hors de portée (il s'agit en fait de la version brute et limitée de fermetures de Java).

Parce qu'une classe interne locale n'est ni le membre d'une classe ou 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 conteneur this au moment de la création de l'instance, et ainsi les membres d'instance de la classe conteneur sont accessibles comme dans une instance classe intérieure. Une classe interne locale est instanciée simplement via son nom, par exemple la classe interne locale Cat est instanciée en tant que nouveau Cat () , pas nouveau 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, une classe interne locale est instanciée au plus une fois à chaque fois que sa méthode conteneur est exécutée. Ce serait bien, alors, si nous pouvions combiner la définition de la classe interne locale et sa seule instanciation en une seule forme de syntaxe pratique, et ce serait aussi bien si nous n'avions pas à trouver un nom pour la classe (le moins inutile noms que contient votre code, mieux c'est). Une classe interne anonyme permet les deux choses suivantes:

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 lieu de cela, 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 complexes qui ne vaut pas la peine d'être étudié en détail - faites juste attention à ce que NetBeans ou Eclipse vous disent.)

Alternativement, vous pouvez spécifier une interface à implémenter:

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'argument constructeur dans ce cas).

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

Soyez clair qu'une classe interne anonyme est tout simplement un moyen moins flexible de créer une classe interne locale avec une seule 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.


39
Grande histoire, merci. Il a cependant une erreur. Vous pouvez accéder aux champs d'une classe externe à partir d'une classe interne d'instance par Rhino.this.variableName.
Thirler

2
Bien que vous ne puissiez pas fournir votre propre constructeur pour les classes internes anonymes, vous pouvez utiliser l'initialisation à double accolade. c2.com/cgi/wiki?DoubleBraceInitialization
Casebash

30
Excellente explication, mais je ne suis pas d'accord avec le fait que les classes internes statiques ne valent rien. Voir rwhansen.blogspot.com/2007/07/… pour une grande variation du modèle de générateur qui dépend fortement de l'utilisation de classes internes statiques.
Mansoor Siddiqui

9
Je ne suis pas d'accord non plus sur le fait que la classe interne statique ne vaut rien: si vous voulez une énumération dans la classe interne, vous devrez rendre la classe interne statique.
Someone Somewhere

9
Les classes imbriquées statiques privées sont également très utiles: vous voulez les avoir, mais vous ne voulez pas les exposer. Comme l'entrée <T> dans une LinkedList <T>, ou AsyncTasks dans une activité (Android), etc ...
Lorenzo Dematté

150

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 le déclarez avec le modificateur statique .
  • Une classe imbriquée non statique est appelée classe interne. (Je reste avec une classe imbriquée non statique.)

Jusqu'à présent, la réponse de Martin est juste. Cependant, la vraie question est: quel est le but de déclarer une classe imbriquée statique ou non?

Vous utilisez des classes imbriquées statiques si vous souhaitez simplement conserver vos classes ensemble si elles appartiennent topiquement ensemble ou si la classe imbriquée est exclusivement utilisée 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. Semblables aux classes internes anonymes, ces classes imbriquées sont en fait des fermetures. Cela signifie qu'ils capturent leur portée environnante et leur instance englobante et la rendent 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 au conteneur parent. À l'aide d'une classe imbriquée non statique, cela fonctionne sans travail. Vous pouvez accéder à l'instance englobante de Container avec la syntaxe Container.this.

Plus d'explications hardcore suivantes:

Si vous regardez les bytecodes Java 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.

L'exemple de Martin

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

serait donc compilé à un appel de quelque chose comme (en bytecodes)

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 qui lui est associé et ne peut pas être référencée plus tard.


17
"Il n'y a pas de différence sémantique entre une classe imbriquée statique et toutes les autres classes." Sauf que la classe imbriquée peut voir les champs / méthodes privés du parent et la classe parent peut voir les champs / méthodes privés du nested.
Brad Cupit

La classe interne non statique ne provoquerait-elle pas potentiellement des fuites massives de mémoire? Comme dans, chaque fois que vous créez un auditeur, vous créez une fuite?
G_V

3
@G_V, il y a certainement un risque de fuites de mémoire car une instance de la classe interne conserve une référence à la classe externe. Que ce soit un problème réel dépend où et comment les références aux instances des classes externes et internes sont conservées.
jrudolph

94

Je pense qu'aucune des réponses ci-dessus ne vous explique la vraie différence 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 dans une autre classe . Une classe imbriquée ne doit exister que pour servir sa classe englobante , si une classe imbriquée est utile à d'autres classes (pas seulement l'enveloppe), elle doit être déclarée comme classe de niveau supérieur.

Différence

Classe imbriquée non statique : est implicitement associée à l'instance englobante de la classe conteneur , cela signifie qu'il est possible d'appeler des méthodes et d'accéder aux variables 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 : ne peut pas accéder à l'instance de classe englobante et invoquer des méthodes dessus, elle doit donc être utilisée lorsque la classe imbriquée n'a pas besoin d'accéder à 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

Ainsi, la principale différence entre les deux du point de vue de la conception est la suivante: la classe imbriquée non statique peut accéder à l'instance de la classe conteneur, contrairement à la statique .


: de votre conclusion "alors que statique ne peut pas", pas même des instances statiques du conteneur? Sûr?
VdeX

Une utilisation courante de la classe imbriquée statique est le modèle de conception ViewHolder dans RecyclerView et ListView.
Hamzeh Soboh

1
Dans de nombreux cas, la réponse courte est plus claire et meilleure. Ceci est un tel exemple.
Eric Wang

32

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 à l'intérieur du 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, vous pouvez donc 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 publicou package-private.

Les classes internes alias les classes sans pile 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 {
    }
}

Inner1est notre classe interne statique et Inner2est notre classe interne qui n'est pas statique. La principale différence entre eux, vous ne pouvez pas créer une Inner2instance sans Outer où vous pouvez créer un Inner1objet indépendamment.

Quand utiliseriez-vous la classe intérieure?

Pensez à une situation où Class Aet Class Bsont liés, Class Bdoit accéder aux Class Amembres et Class Bn'est liée qu'à Class A. Les classes internes entrent en jeu.

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 une 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 / classe supérieure englobante. Si votre classe interne n'utilise pas les méthodes ou les champs de la classe externe, c'est juste une perte d'espace, alors rendez-la 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 conteneur / classe supérieure pour fonctionner. Cela peut vous aider à réduire le nombre d'objets créés par votre application au moment de l'exécution.


3
tu voulais dire OuterClass.Inner2 inner = outer.new Inner2();?
Erik Kaplun

4
static innerest une contradiction en termes.
Marquis de Lorne

Et les classes internes ne sont pas également appelées «classes non empilées». N'utilisez pas la mise en forme de code pour du texte qui n'est pas du code, et utilisez-le pour du texte qui l'est.
Marquis de Lorne le

30

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

J'espère que cela aide!

Classe intérieure

  • Peut accéder à la classe externe à la fois aux méthodes et aux champs d' instance et statiques
  • Associé à l'instance de la classe englobante , pour l'instancier, il faut d'abord une instance de la classe externe (notez le nouveau mot-clé place):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
  • Impossible de définir un membre statique lui-même

  • Ne peut pas avoir de déclaration de classe ou d' interface

Classe imbriquée statique

  • Impossible d'accéder aux méthodes ou champs d' instance de classe externe

  • Pas associé à une instance de classe englobante Donc pour l'instancier:

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

Similitudes

  • Les deux classes internes peuvent accéder même aux champs privés et aux méthodes de classe externe
  • De plus, la classe externe a accès aux champs privés et aux méthodes des 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 existe plusieurs raisons ( documentation complète ):

  • C'est une façon de regrouper logiquement des classes qui ne sont utilisées qu'à 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 ces "classes d'assistance" rend leur package plus rationalisé.

  • Cela augmente l'encapsulation: considérez deux classes de niveau supérieur, A et B, où B a besoin d'accéder à des membres de A qui seraient autrement déclarés privés. En cachant la classe B dans la classe A, les membres de A peuvent être déclarés privés et B peut y accéder. De plus, B lui-même peut être caché du monde extérieur.

  • Cela peut conduire à un code plus lisible et plus facile à gérer: l' imbrication de petites classes dans des classes de niveau supérieur rapproche le code de son utilisation.


26

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

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

Cependant, quelques autres points à retenir 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 aux champs / méthodes statiques privés de sa classe [parent] externe et vice versa.

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

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

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

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


15

Classe imbriquée: classe à l'intérieur de la classe

Les types:

  1. Classe imbriquée statique
  2. Classe imbriquée non statique [classe intérieure]

Différence:

Classe imbriquée non statique [classe intérieure]

Dans la classe imbriquée non statique, l'objet de la classe interne existe dans l'objet de la classe externe. Ainsi, 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 d'abord créer un objet de classe externe.

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

Classe imbriquée statique

Dans la classe statique imbriquée, l'objet de la classe interne n'a pas besoin de l'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 interne suivante

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);

13

L'instance de la classe interne est créée lors de la création de l'instance de la classe externe. 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 statique imbriquée n'a pas d'instance concrète. Il est juste chargé lors de sa première utilisation (tout comme les méthodes statiques). C'est une 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 de tas / pile, car il n'est pas nécessaire de créer une instance de cette classe. Par conséquent, la règle de base est d'essayer de définir une classe imbriquée statique, avec une portée aussi limitée que possible (privé> = classe> = protégé> = public), puis de le convertir en classe interne (en supprimant l'identifiant "statique") et de desserrer la portée, si c'est vraiment nécessaire.


2
La première phrase est incorrecte. Il n'y a rien de tel que « l' instance de la classe interne», et des instances de celle-ci peuvent être créées à tout moment après que la classe externe a été instanciée. La deuxième phrase ne découle pas de la première phrase.
Marquis de Lorne

11

Il existe une subtilité dans l'utilisation des classes statiques imbriquées qui pourraient être utiles 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 tant que le constructeur de la classe n'est pas appelé, ou du moins pas après que les attributs sont référencés pour la première fois, même si ils sont marqués comme «définitifs».

Considérez cet 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 'nested' et 'innerItem' sont tous deux déclarés comme 'final statique'. le paramètre nested.innerItem n'a lieu qu'après l'instanciation de la classe (ou du moins pas après le premier référencement de l'élément statique imbriqué), comme vous pouvez le constater par vous-même en commentant et en décommentant les lignes auxquelles je me réfère, au dessus de. Il n'en va pas de même pour «externalItem».

C'est du moins ce que je vois dans Java 6.0.


10

Les termes sont utilisés de manière interchangeable. Si vous voulez être vraiment pédant à ce sujet, vous pouvez 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.


2
«intérieur statique» est une contradiction dans les termes.
Marquis de Lorne

5
Ce n'est pas la convention qui définit la classe interne comme une classe imbriquée non statique, mais le JLS. docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3
Lew Bloch

1
Et les termes ne sont pas «utilisés de manière interchangeable».
Marquis de Lorne

pourquoi statique dans l'exemple ci-dessus donnant une erreur dans ide
DeV

10

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

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….
  }
}

1
«intérieur statique» est une contradiction dans les termes. Une classe imbriquée est statique ou interne.
Marquis de Lorne

9

Je ne pense pas qu'il y ait beaucoup à 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 lorsque vous utilisez des 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 l'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épassement de mémoire ou une exception de dépassement de pile en raison du fait que le GC ne pourra pas récupérer les classes englobantes même si elles ne sont plus utilisées. Pour que cela soit clair, 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 affichera " Je suis détruit! ", Mais ce commentaire ne le 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 référence (a un pointeur vers) l'instance externe, elle n'est pas collectée également. Avoir suffisamment de ces objets dans votre projet et manquer de mémoire.
Comparé aux classes internes statiques qui ne contiennent pas de point sur l'instance de classe interne car elle n'est pas liée à l'instance mais à la classe. Le programme ci-dessus peut imprimer " Je suis détruit! " Si vous rendez la classe intérieure statique et instanciée avecOuter.Inner i = new Outer.Inner();




8

Ummm ... une classe interne EST une classe imbriquée ... voulez-vous dire classe anonyme et classe interne?

Edit: Si vous vouliez vraiment dire interne vs anonyme ... 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 de manière anonyme, 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:

Wikipédia prétend qu'il y a une différence dans Java, mais je travaille avec Java depuis 8 ans, et c'est la première fois que j'entends une telle distinction ... sans mentionner qu'il n'y a aucune référence pour sauvegarder la revendication ... bas 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 y a 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 (donc elles ne peuvent pas être construites dans un contexte statique, ce sera un compilateur Erreur). 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.


3
Selon la documentation Java, il existe une différence entre une classe interne et une classe imbriquée statique - les classes imbriquées statiques n'ont pas de référence à leur classe englobante et sont utilisées principalement à des fins d'organisation. Vous devriez voir la réponse de Jegschemesch pour une description plus approfondie.
mipadi

1
Je pense que la différence sémantique est surtout historique. Lorsque j'ai écrit un compilateur C # -> Java 1.1, la référence du langage Java était très explicite: la classe imbriquée est statique, la classe interne ne l'est pas (et a donc ce $ 0). En tout cas, c'est déroutant et je suis content que ce ne soit plus un problème.
Tomer Gabel

2
Le JLS définit la "classe interne" dans docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3 et c'est pourquoi il est impossible d'avoir une "interne" non statique classe "en Java. "Nested" n'est PAS "juste un autre terme pour signifier la même chose", et il n'est PAS VRAI "qu'une classe interne soit une classe définie dans une classe (statique ou non)". Ce sont des informations INCORRECTES.
Lew Bloch

6

Cibler l'apprenant, novice en Java et / ou en classes imbriquées

Les classes imbriquées peuvent être:
1. Classes imbriquées statiques.
2. Classes imbriquées non statiques. (également connu sous le nom de classes internes ) => S'il vous plaît rappelez-vous 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 des sous-ensembles de classes imbriquées
  • Vous pouvez dire qu'une classe interne est également une classe imbriquée, mais vous ne pouvez PAS dire qu'une classe imbriquée est également une classe interne .

Spécialité de classe intérieure:

  • instance d'une classe interne a accès à tous les 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: Instanciation d'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: Instanciation d'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 une classe interne et une classe imbriquée statique en Java?
Réponse: passez simplement en revue les spécificités de chaque classe mentionnée ci-dessus.



6

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 la classe imbriquée non statique est simplement appelée classe interne.

Qu'est-ce que la classe intérieure en Java?

Toute classe qui n'est pas un niveau supérieur ou déclarée dans une autre classe est connue comme classe imbriquée et parmi ces classes imbriquées, les classes déclarées non statiques sont appelées classe interne en Java. il existe trois types de classe Inner en Java:

1) Classe interne locale - est déclarée à l'intérieur d'un bloc de code ou d'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) Membre classe interne - 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 qu'une classe statique imbriquée en Java?

La classe statique imbriquée est une autre classe qui est déclarée dans une classe comme 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 classe statique imbriquée en Java .

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

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


2
"La classe imbriquée statique ne peut pas accéder au membre ou à la méthode de données non statiques (instance)." est incorrect et crée de la confusion . Ils ont absolument accès aux informations d'instance privées - à condition de créer une instance pour accéder à ces informations d'instance. Ils n'ont pas d'instance englobante comme les classes internes, mais ils ont accès aux membres privés de l'instance de leur classe englobante.
TJ Crowder du

5

Je pense que les gens ici devraient remarquer à Poster que: Static Nest Class uniquement la première classe intérieure. 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. (car la classe normale a besoin d'une instance).


2
C'est tout non-sens. Tout cela montre qu'une classe interne ne peut pas contenir de classe statique. La partie sur «ne dépend pas de la classe qu'elle contient» n'a pas de sens, tout comme la phrase suivante.
Marquis de Lorne

5

Lorsque nous déclarons une classe membre statique à l'intérieur d'une classe, elle est connue comme classe imbriquée de niveau supérieur ou classe imbriquée statique. Cela 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 appelée 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);
        }
    }
}

"Lorsque nous déclarons une classe membre statique à l'intérieur d'une classe, elle est connue comme classe imbriquée de niveau supérieur" Cela n'a pas de sens. "Une classe de niveau supérieur est une classe qui n'est pas une classe imbriquée." Une «classe imbriquée de niveau supérieur» n'existe pas.
Radiodef

3

Ce qui suit est un exemple de static nested classetinner class :

OuterClass.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()); 

    }

}

3

Je pense qu'aucune des réponses ci-dessus ne vous donne le véritable exemple de la différence entre une classe imbriquée et une classe imbriquée statique en termes de conception d'application. Et la principale différence entre la classe imbriquée statique et la classe interne est la possibilité d'accéder au champ d'instance de classe externe.

Jetons un coup d'œil aux deux exemples suivants.

Classe d'imbrication statique: un bon exemple d'utilisation de classes imbriquées statiques est le modèle de générateur ( https://dzone.com/articles/design-patterns-the-builder-pattern ).

Pour BankAccount, nous utilisons une classe imbriquée statique, principalement parce que

  1. Une instance de classe d'imbrication statique peut être créée avant la classe externe.

  2. Dans le modèle de générateur, le générateur est une classe d'assistance qui est utilisée pour créer le BankAccount.

  3. BankAccount.Builder est uniquement associé à BankAccount. Aucune autre classe n'est liée à BankAccount.Builder. il est donc préférable de les organiser ensemble sans utiliser la convention de nom.
public class BankAccount {

    private long accountNumber;
    private String owner;
    ...

    public static class Builder {

    private long accountNumber;
    private String owner;
    ...

    static public Builder(long accountNumber) {
        this.accountNumber = accountNumber;
    }

    public Builder withOwner(String owner){
        this.owner = owner;
        return this; 
    }

    ...
    public BankAccount build(){
            BankAccount account = new BankAccount(); 
            account.accountNumber = this.accountNumber;
            account.owner = this.owner;
            ...
            return account;
        }
    }
}

Classe interne: une utilisation courante des classes internes consiste à définir un gestionnaire d'événements. https://docs.oracle.com/javase/tutorial/uiswing/events/generalrules.html

Pour MyClass, nous utilisons la classe interne, principalement parce que:

  1. La classe interne MyAdapter doit accéder au membre de classe externe.

  2. Dans l'exemple, MyAdapter est uniquement associé à MyClass. Aucune autre classe n'est liée à MyAdapter. il est donc préférable de les organiser ensemble sans utiliser de convention de nom

public class MyClass extends Applet {
    ...
        someObject.addMouseListener(new MyAdapter());
    ...
    class MyAdapter extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            ...// Event listener implementation goes here...
            ...// change some outer class instance property depend on the event
        }
    }
}

2

Un diagramme

entrez la description de l'image ici

La principale différence entre les classes static nestedet non-static nestedest qu'elles static nested n'ont pas accès aux membres de classe externes non statiques


0

Tout d'abord, il n'y a pas de classe appelée classe statique.Le modificateur statique utilisé avec la classe interne (appelée 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 en avoir instance de la classe Outer. (Ce qui est à l'origine de l'électricité statique.)

La différence entre l'utilisation de la classe Nested et de la classe Inner standard 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 la suivante:

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

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


1
"... dit qu'il s'agit d'un membre statique de la classe externe, ce qui signifie ....": Il n'est pas incorrect de considérer une classe imbriquée statique comme une "classe membre" de la classe externe, mais les similitudes avec les champs statiques et les méthodes s'arrêtent là. Une classe imbriquée statique n'appartient pas à la classe externe. Dans presque tous les domaines qui importent, une classe imbriquée statique est une classe de niveau supérieur autonome dont la définition de classe a été imbriquée dans celle de la classe externe pour la commodité de l'emballage (et, espérons-le, car il existe une association logique entre la classe imbriquée et la classe externe ... bien qu'il n'y en ait pas besoin).
scottb

1
«intérieur statique» est une contradiction dans les termes. Les classes statiques existent, au premier niveau d'imbrication, et ce ne sont pas des classes internes, par définition. Très confus.
Marquis de Lorne

0

Le langage de programmation Java vous permet de définir une classe dans une autre classe. Une telle classe est appelée une classe imbriquée et est illustrée ici:

class OuterClass {
...
class NestedClass {
    ...
    }
}

Les classes imbriquées sont divisées en deux catégories: statiques et non statiques. Les classes imbriquées déclarées statiques sont appelées classes imbriquées statiques. Les classes imbriquées non statiques sont appelées classes internes. Une chose que nous devons garder à l'esprit est que les classes imbriquées non statiques (classes internes) ont accès aux autres membres de la classe englobante, même si elles sont déclarées privées. Les classes imbriquées statiques n'ont accès aux autres membres de la classe englobante que si elles sont statiques. Il ne peut pas accéder aux membres non statiques de la classe externe. Comme pour les méthodes et variables de classe, une classe imbriquée statique est associée à sa classe externe. Par exemple, pour créer un objet pour la classe imbriquée statique, utilisez cette syntaxe:

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

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 = new OuterClass().new InnerClass();

Pourquoi nous utilisons des classes imbriquées

  1. C'est une façon de regrouper logiquement des classes qui ne sont utilisées qu'en un seul endroit.
  2. Il augmente l'encapsulation.
  3. Cela peut conduire à un code plus lisible et plus facile à gérer.

Source: Tutoriels Java ™ - Classes imbriquées


-1

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 n'est pas statique, également connue sous le nom de classe interne , Java ne vous permet pas de 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, afin que la classe interne puisse référencer les champs de la classe externe.

Mais s'il est statique, 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.


1
C'est faux. Il existe une syntaxe spéciale pour créer une classe interne en dehors de la portée de la classe englobante.
Marquis de Lorne

-1

C'est assez simple, en comparant les classes locales statiques et les classes internes non statiques.
Différences:
Classe locale statique:
ne peut accéder qu'aux membres statiques de la classe externe.
Impossible d'avoir des initialiseurs statiques
Impossible d'accéder directement à l'extérieur de la fonction où son déclaré


-2

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);
                        }*/
                    //}
                }
    }

1
Évidemment, la partie code. Et au cas où vous ne l'auriez pas remarqué: votre exemple de code est super difficile à lire. Même sur mon immense moniteur de bureau, j'ai une barre de défilement horizontale. Pensez à placer vos commentaires au-dessus ou au-dessous de la chose qu'ils commentent - plutôt que derrière .
GhostCat
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.