openclassroom Classe interne Java et classe imbriquée statique




static java (19)

Quelle est la principale différence entre une classe interne et une classe imbriquée statique en Java? Le design / la mise en œuvre jouent-ils un rôle dans le choix de l'un d'entre eux?


Je ne pense pas qu'il y ait beaucoup à ajouter ici, la plupart des réponses expliquent parfaitement les différences entre les classes imbriquées statiques et les classes Inner. Cependant, tenez compte du problème suivant lors de l'utilisation de classes imbriquées et de classes internes. Comme mention dans quelques réponses, les classes internes ne peuvent pas être instanciées sans et leur classe englobante, ce qui signifie qu'elles gardent un pointeur vers l'instance de leur classe qui peut entraîner un dépassement de mémoire ou une exception de dépassement de pile due au fait que le GC ne sera pas capable de ramasser les classes englobantes même si elles ne sont plus utilisées. Pour 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 sortira " Je suis détruit! ", Mais en gardant ceci commenté il 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 non plus collectée. Avoir assez de ces objets dans votre projet et peut manquer de mémoire.
Par rapport aux classes internes statiques qui ne tiennent pas de point à l'instance de classe interne car ce n'est pas lié à une instance mais à une classe. Le programme ci-dessus peut imprimer " Je suis détruit! " Si vous faites de la classe Inner statique et instancié avec Outer.Inner i = new Outer.Inner();


La classe imbriquée est un terme très général: chaque 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 premier niveau .


I think people here should notice to Poster that : Static Nest Class just only the first inner class. 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 !!!

 }

So, summarize, static class doesn't depend which class its contains. So, they cannot in normal class. (because normal class need an instance).


I have illustrated various possible correct and error scenario which can occur in java code.

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

Targeting learner, who are novice to Java and/or Nested Classes

Nested classes can be either:
1. Static Nested classes.
2. Non Static Nested classes. (also known as Inner classes ) =>Please remember this


1.Inner classes
Exemple:

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


Inner classes are subsets of nested classes:

  • inner class is a specific type of nested class
  • inner classes are subsets of nested classes
  • You can say that an inner class is also a nested class, but you can NOT say that a nested class is also an inner class .

Specialty of Inner class:

  • instance of an inner class has access to all of the members of the outer class, even those that are marked “private”


2.Static Nested Classes:
Exemple:

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

Case 1:Instantiating a static nested class from a non-enclosing class

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"
  }
}

Case 2:Instantiating a static nested class from an enclosing class

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"
  }

}

Specialty of Static classes:

  • Static inner class would only have access to the static members of the outer class, and have no access to non-static members.

Conclusion:
Question: What is the main difference between a inner class and a static nested class in Java?
Answer: just go through specifics of each class mentioned above.


The following is an example of static nested class and inner 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()); 

    }

}

First of all There is no such class called Static class.The Static modifier use with inner class (called as Nested Class) says that it is a static member of Outer Class which means we can access it as with other static members and without having any instance of Outer class. (Which is benefit of static originally.)

Difference between using Nested class and regular Inner class is:

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

First We can to instantiate Outerclass then we Can access Inner.

But if Class is Nested then syntax is:

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

Which uses the static Syntax as normal implementation of static keyword.


Inner class and nested static class in Java both are classes declared inside another class, known as top level class in Java. In Java terminology, If you declare a nested class static, it will called nested static class in Java while non static nested class are simply referred as Inner Class.

What is Inner Class in Java?

Any class which is not a top level or declared inside another class is known as nested class and out of those nested classes, class which are declared non static are known as Inner class in Java. there are three kinds of Inner class in Java:

1) Local inner class - is declared inside a code block or method.
2) Anonymous inner class - is a class which doesn't have name to reference and initialized at same place where it gets created.
3) Member inner class - is declared as non static member of outer class.

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");
        }
    }
}

What is nested static class in Java?

Nested static class is another class which is declared inside a class as member and made static. Nested static class is also declared as member of outer class and can be make private, public or protected like any other member. One of the main benefit of nested static class over inner class is that instance of nested static class is not attached to any enclosing instance of Outer class. You also don't need any instance of Outer class to create instance of nested static class in Java .

1) It can access static data members of outer class including private.
2) Static nested class cannot access non-static (instance) data member or method .

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: Inner class and nested Static Class in Java with Example


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 en tant que 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 public ou paquet-privé.

Classes internes aka Les classes non-stack ont ​​accès aux autres membres de la classe supérieure, même si elles sont déclarées privées alors 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 différence clé entre eux, vous ne pouvez pas créer une instance Inner2 sans un Outer où vous pouvez créer un objet Inner1 indépendamment.

Quand utiliseriez-vous la classe interne?

Pensez à une situation dans laquelle la Class A et la Class B sont liées, la Class B doit avoir accès aux membres de la Class A et la Class B est liée uniquement à la Class A Les classes intérieures entrent en scène.

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 devez définir une classe interne statique lorsque vous savez qu'elle n'a aucune relation avec l'instance de la classe / top class 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 faites-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 ou de la classe supérieure contenant pour fonctionner. Cela peut vous aider à réduire le nombre d'objets créés par votre application lors de l'exécution.


When we declare static member class inside a class, it is known as top level nested class or a static nested class. It can be demonstrated as below :

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());
    }
}

When we declare non-static member class inside a class it is known as inner class. Inner class can be demonstrated as below :

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

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

Premier à obtenir les termes corrects:

  • Une classe imbriquée est une classe 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.)

La réponse de Martin est juste pour le moment. Cependant, la vraie question est la suivante: 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 si elles appartiennent 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 à des classes internes anonymes, ces classes imbriquées sont en réalité des fermetures. Cela signifie qu'ils capturent leur portée environnante et leur instance englobante et la rendent accessible. Peut-être qu'un exemple éclaircira 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 voulez avoir une référence d'un élément enfant au conteneur parent. En utilisant 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 peut 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 aucun nom associé et ne peut pas être référencée plus tard.


Il y a une subtilité à propos de l'utilisation de classes statiques imbriquées qui pourraient être utiles dans certaines situations.

Alors que les attributs statiques sont instanciés avant que la classe soit instanciée via son constructeur, les attributs statiques des classes statiques imbriquées ne semblent pas être instanciés avant que le constructeur de la classe ne soit invoqué, ou du moins après que les attributs aient été référencés. 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 les deux déclarés comme 'static final'. le paramètre de nested.innerItem n'a pas lieu tant que la classe n'est pas instanciée (ou du moins pas avant que l'élément statique imbriqué ne soit référencé), comme vous pouvez le constater en commentant et en décommentant les lignes auxquelles je me réfère, au dessus. La même chose n'est pas vraie pour 'outerItem'.

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


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 aux méthodes et aux champs statiques de la classe externe
  • Associé à l'instance de la classe englobante pour l'instancier, il faut d'abord une instance de classe externe (notez le nouveau mot-clé):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • Impossible de définir les membres statiques eux- mêmes

  • Impossible d' avoir une 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

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

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

Similitudes

  • Les deux classes Inner peuvent accéder même aux champs privés et aux méthodes de classe externe
  • Aussi la classe Outer a accès à des champs privés et des méthodes de 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 un moyen de grouper logiquement des classes qui ne sont utilisées que dans un seul endroit: Si une classe n'est utile qu'à une autre classe, il est logique de l'incorporer dans cette classe et de garder les deux ensemble. L'imbrication de ces "classes auxiliaires" rend leur paquet plus simple.

  • Cela augmente l'encapsulation: Considérons deux classes de niveau supérieur, A et B, où B doit avoir 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 A peuvent être déclarés privés et B peut y accéder. 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 premier niveau place le code plus près de l'endroit où il est utilisé.


Dans le cas de création d'instance, l'instance de 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 inclinant. Mais l'instance de classe interne statique est créée avec la référence de classe externe, pas avec la référence d'objet de classe externe. Cela signifie qu'il n'a pas d'instance en instance.

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

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

Les types:

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

Différence:

Classe imbriquée non statique [Classe interne]

Dans l'objet de classe imbriqué non statique 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 d'abord créer un objet de classe externe.

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

Classe imbriquée statique

Dans l'objet de classe imbriqué statique de classe interne n'a pas besoin d'objet de classe externe, parce que le mot "statique" n'indique pas besoin de créer l'objet.

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

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

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

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 est hors de portée, les instances internes de classe cessent également d'exister.

La classe imbriquée statique n'a pas d'instance concrète. C'est juste chargé quand il est utilisé pour la première fois (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 avec l'objet externe, elles sont plus rapides, et elles ne prennent pas de mémoire tas / pile, car il n'est pas nécessaire de créer une instance de telle classe. Par conséquent, la règle empirique consiste à 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 (en supprimant l'identificateur "static") la portée, si c'est vraiment nécessaire.


Ummm... an inner class IS a nested class... do you mean anonymous class and inner class?

Edit: If you actually meant inner vs anonymous... an inner class is just a class defined within a class such as:

public class A {
    public class B {
    }
}

Whereas an anonymous class is an extension of a class defined anonymously, so no actual "class is defined, as in:

public class A {
}

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

Further Edit:

Wikipedia claims there is a difference in Java, but I've been working with Java for 8 years, and it's the first I heard such a distinction... not to mention there are no references there to back up the claim... bottom line, an inner class is a class defined within a class (static or not), and nested is just another term to mean the same thing.

There is a subtle difference between static and non-static nested class... basically non-static inner classes have implicit access to instance fields and methods of the enclosing class (thus they cannot be constructed in a static context, it will be a compiler error). Static nested classes, on the other hand, don't have implicit access to instance fields and methods, and CAN be constructed in a static context.


Je pense que la convention généralement suivie est celle-ci:

  • classe statique 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 a en outre deux autres forme:
    • classes class - class locales 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 des instructions

Cependant, peu d'autres points à retenir sont:

  • Les classes de niveau supérieur et les classes imbriquées statiques sont sémantiquement identiques sauf que dans le cas d'une classe imbriquée statique, elle peut faire une référence statique aux champs / méthodes statiques privés de sa classe Outer [parent] 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 des classes internes dans des contextes statiques, comme une classe anonyme utilisée dans un bloc d'initialisation statique.

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

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

Je sens que la plus grande question qui reste ouverte à utiliser et quand? Cela dépend surtout du scénario auquel vous avez affaire, mais lire la réponse donnée par @jrudolph peut vous aider à prendre une décision.


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 des 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 la classe englobante:

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 peut exister uniquement dans une instance de OuterClass et a un accès direct aux méthodes et 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 être complet, notez qu'il existe aussi 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.







inner-classes