Clase interna de Java y clase anidada estática

¿Cuál es la principal diferencia entre una clase interna y una clase anidada estática en Java? ¿El diseño / implementación juega un papel en la elección de uno de estos?

Del tutorial de Java :

Las clases anidadas se dividen en dos categorías: estáticas y no estáticas. Las clases anidadas que se declaran estáticas simplemente se llaman clases anidadas estáticas. Las clases anidadas no estáticas se llaman clases internas.

Se accede a las clases anidadas estáticas utilizando el nombre de la clase adjunta:

 OuterClass.StaticNestedClass 

Por ejemplo, para crear un objeto para la clase anidada estática, use esta syntax:

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

Los objetos que son instancias de una clase interna existen dentro de una instancia de la clase externa. Considere las siguientes clases:

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

Una instancia de InnerClass solo puede existir dentro de una instancia de OuterClass y tiene acceso directo a los métodos y campos de su instancia adjunta.

Para crear una instancia de una clase interna, primero debe crear una instancia de la clase externa. Luego, crea el objeto interno dentro del objeto externo con esta syntax:

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

ver: Tutorial de Java – Clases anidadas

Para mayor información, tenga en cuenta que también existe una clase interna sin una instancia adjunta :

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

Aquí, la new A() { ... } es una clase interna definida en un contexto estático y no tiene una instancia adjunta.

El tutorial de Java dice :

Terminología: las clases anidadas se dividen en dos categorías: estática y no estática. Las clases anidadas que se declaran estáticas simplemente se llaman clases anidadas estáticas. Las clases anidadas no estáticas se llaman clases internas.

En lenguaje común, los términos “nested” e “interno” son usados ​​indistintamente por la mayoría de los progtwigdores, pero usaré el término correcto “clase anidada” que abarca tanto interno como estático.

Las clases pueden anidarse ad infinitum , por ejemplo, la clase A puede contener la clase B que contiene la clase C que contiene la clase D, etc. Sin embargo, es raro encontrar más de un nivel de anidación de clase, ya que generalmente es un diseño incorrecto.

Hay tres razones por las que puede crear una clase anidada:

  • organización: a veces parece más sensato clasificar una clase en el espacio de nombres de otra clase, especialmente cuando no se utilizará en ningún otro contexto
  • acceso: las clases anidadas tienen acceso especial a las variables / campos de sus clases contenedoras (precisamente qué variables / campos dependen del tipo de clase anidada, ya sea interna o estática).
  • conveniencia: tener que crear un nuevo archivo para cada nuevo tipo es molesto, de nuevo, especialmente cuando el tipo solo se usará en un contexto

Hay cuatro tipos de clases anidadas en Java . En resumen, son:

  • clase estática : declarada como miembro estático de otra clase
  • clase interna : declarada como miembro de instancia de otra clase
  • clase interna local : declarada dentro de un método de instancia de otra clase
  • clase interna anónima : como una clase interna local, pero escrita como una expresión que devuelve un objeto único

Permítanme elaborar en más detalles.

Clases estáticas

Las clases estáticas son las más fáciles de entender porque no tienen nada que ver con instancias de la clase contenedora.

Una clase estática es una clase declarada como miembro estático de otra clase. Al igual que otros miembros estáticos, una clase así es simplemente una percha que usa la clase contenedora como su espacio de nombres, por ejemplo , la clase Goat declarada como un miembro estático de la clase Rhino en el paquete pizza es conocida con el nombre pizza.Rhino.Goat .

 package pizza; public class Rhino { ... public static class Goat { ... } } 

Francamente, las clases estáticas son una característica bastante inútil porque las clases ya están divididas en espacios de nombres por paquetes. La única razón real concebible para crear una clase estática es que dicha clase tenga acceso a los miembros estáticos privados de su clase contenedora, pero considero que esta es una justificación poco convincente para que exista la característica de clase estática.

Clases internas

Una clase interna es una clase declarada como miembro no estático de otra clase:

 package pizza; public class Rhino { public class Goat { ... } private void jerry() { Goat g = new Goat(); } } 

Al igual que con una clase estática, la clase interna se conoce como calificada por su nombre de clase que contiene, pizza.Rhino.Goat , pero dentro de la clase contenedora, se la puede conocer por su nombre simple. Sin embargo, cada instancia de una clase interna está vinculada a una instancia particular de su clase contenedora: arriba, la Cabra creada en jerry , está implícitamente ligada a la instancia de Rhino , esto en jerry . De lo contrario, hacemos que la instancia de Rhino asociada sea explícita cuando instanciamos Goat :

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

(Observe que se refiere al tipo interno como simplemente Goat en la nueva syntax extraña: Java deduce el tipo que contiene de la parte de rinoceronte . Y, sí, el nuevo rhino.Goat () también tendría más sentido para mí).

Entonces, ¿qué nos gana esto? Bueno, la instancia de clase interna tiene acceso a los miembros de instancia de la instancia de clase contenedora. Estos miembros adjuntos de la instancia son referidos dentro de la clase interna solo a través de sus nombres simples, no a través de esto ( esto en la clase interna se refiere a la instancia de clase interna, no a la instancia de clase que contiene asociada):

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

En la clase interna, puede referirse a esta clase contenedora como Rhino.this , y puede usar esto para referirse a sus miembros, por ejemplo , Rhino.this.barry .

Clases internas locales

Una clase interna local es una clase declarada en el cuerpo de un método. Dicha clase solo se conoce dentro de su método contenedor, por lo que solo se puede instanciar y se puede acceder a sus miembros dentro de su método contenedor. La ganancia es que una instancia de clase interna local está vinculada y puede acceder a las variables locales finales de su método contenedor. Cuando la instancia utiliza un local final de su método contenedor, la variable conserva el valor que tenía en el momento de la creación de la instancia, incluso si la variable se ha salido del scope (esta es efectivamente la versión limitada de cierres de Java).

Debido a que una clase interna local no es miembro de una clase o paquete, no se declara con un nivel de acceso. (Tenga en claro, sin embargo, que sus propios miembros tienen niveles de acceso como en una clase normal).

Si se declara una clase interna local en un método de instancia, una instanciación de la clase interna está vinculada a la instancia que contiene el método contenedora al momento de la creación de la instancia, y así los miembros de la instancia de la clase contenedora son accesibles como en una instancia clase interna Se crea una instancia de una clase interna local simplemente a través de su nombre, por ejemplo , la clase interna local Cat se instancia como nuevo Cat () , no es nuevo esto. Cat () como cabría esperar.

Clases internas anónimas

Una clase interna anónima es una manera sintácticamente conveniente de escribir una clase interna local. Lo más común es que una clase interna local se instancia como máximo una vez cada vez que se ejecuta su método contenedor. Sería bueno, entonces, si pudiéramos combinar la definición de la clase interna local y su instanciación única en una forma de syntax conveniente, y también sería bueno si no tuviéramos que inventar un nombre para la clase (los menos inútiles) nombres que contiene tu código, mejor). Una clase interna anónima permite ambas cosas:

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

Esta es una expresión que devuelve una nueva instancia de una clase sin nombre que extiende ParentClassName . No puedes suministrar tu propio constructor; más bien, se proporciona implícitamente uno que simplemente llama al superconstructor, por lo que los argumentos suministrados deben ajustarse al superconstructor. (Si el padre contiene múltiples constructores, el más simple se llama “más simple”, como lo determina un conjunto bastante complejo de reglas que no vale la pena preocuparse por aprender en detalle; solo preste atención a lo que NetBeans o Eclipse le dicen).

Alternativamente, puede especificar una interfaz para implementar:

 new *InterfaceName*() {*members*} 

Tal statement crea una nueva instancia de una clase sin nombre que extiende Object e implementa InterfaceName . Nuevamente, no puedes suministrar tu propio constructor; en este caso, Java proporciona implícitamente un constructor no-arg, do-nothing (por lo que nunca habrá argumentos de constructor en este caso).

Aunque no puede dar un constructor a una clase interna anónima, aún puede hacer la configuración que desee utilizando un bloque de inicialización (un {} bloque colocado fuera de cualquier método).

Tenga en claro que una clase interna anónima es simplemente una forma menos flexible de crear una clase interna local con una instancia. Si quieres una clase interna local que implemente múltiples interfaces o implemente interfaces mientras extiendes alguna clase que no sea Object o que especifique su propio constructor, estás atascado creando una clase interna local con nombre.

No creo que la diferencia real se haya aclarado en las respuestas anteriores.

Primero para obtener los términos correctos:

  • Una clase anidada es una clase que está contenida en otra clase en el nivel del código fuente.
  • Es estático si lo declaras con el modificador estático .
  • Una clase anidada no estática se llama clase interna. (Me quedo con una clase anidada no estática).

La respuesta de Martin es correcta hasta ahora. Sin embargo, la pregunta real es: ¿Cuál es el propósito de declarar estática o no una clase anidada?

Utiliza clases anidadas estáticas si solo desea mantener sus clases juntas si pertenecen tópicamente juntas o si la clase anidada se utiliza exclusivamente en la clase adjunta. No hay diferencia semántica entre una clase anidada estática y cualquier otra clase.

Las clases anidadas no estáticas son una bestia diferente. Similar a las clases internas anónimas, estas clases anidadas son realmente cierres. Eso significa que capturan su scope circundante y su instancia adjunta y la hacen accesible. Quizás un ejemplo aclarará eso. Ver este trozo de un contenedor:

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

En este caso, desea tener una referencia de un elemento secundario al contenedor principal. Usando una clase anidada no estática, esto funciona sin algún trabajo. Puede acceder a la instancia adjunta de Container con la syntax Container.this .

Explicaciones más duras siguientes:

Si nos fijamos en los códigos de byte de Java que el comstackdor genera para una clase anidada (no estática), podría ser incluso más clara:

 // 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 (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.() : 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 } 

Como puede ver, el comstackdor crea un campo oculto. Container this$0 . Esto se establece en el constructor que tiene un parámetro adicional de tipo Container para especificar la instancia adjunta. No puede ver este parámetro en la fuente pero el comstackdor lo genera implícitamente para una clase anidada.

El ejemplo de Martin

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

sería comstackdo a una llamada de algo así como (en bytecodes)

 new InnerClass(outerObject) 

En aras de la exhaustividad:

Una clase anónima es un ejemplo perfecto de una clase anidada no estática que simplemente no tiene ningún nombre asociado y no puede referenciarse más adelante.

Creo que ninguna de las respuestas anteriores explica la diferencia real entre una clase anidada y una clase anidada estática en términos del diseño de la aplicación:

Visión de conjunto

Una clase anidada puede ser no estática o estática y en cada caso es una clase definida dentro de otra clase . Una clase anidada debe existir solo para servir. La clase que lo incluye , si una clase anidada es útil para otras clases (no solo el adjunto), debe declararse como una clase de nivel superior.

Diferencia

Clase anidada no estática : está implícitamente asociada con la instancia adjunta de la clase contenedora, esto significa que es posible invocar métodos y acceder a variables de la instancia envolvente. Un uso común de una clase anidada no estática es definir una clase de Adaptador.

Clase estática anidada : no se puede acceder a la instancia de la clase adjunta e invocar métodos en ella, por lo que se debe usar cuando la clase anidada no requiere acceso a una instancia de la clase adjunta. Un uso común de la clase anidada estática es implementar componentes del objeto externo.

Conclusión

Entonces, la principal diferencia entre los dos desde el punto de vista del diseño es: la clase anidada no estática puede acceder a la instancia de la clase contenedor, mientras que la estática no puede .

En términos simples, necesitamos clases anidadas principalmente porque Java no proporciona cierres.

Las clases anidadas son clases definidas dentro del cuerpo de otra clase adjunta. Son de dos tipos: estáticos y no estáticos.

Se tratan como miembros de la clase adjunta, por lo tanto, puede especificar cualquiera de los cuatro especificadores de acceso: private, package, protected, public . No tenemos este lujo con las clases de nivel superior, que solo pueden declararse public o privadas de paquetes.

Las clases internas, también conocidas como clases no astackdas, tienen acceso a otros miembros de la clase superior, incluso si se declaran privadas, mientras que las clases anidadas estáticas no tienen acceso a otros miembros de la clase superior.

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

Inner1 es nuestra clase interna estática e Inner2 es nuestra clase interna que no es estática. La diferencia clave entre ellos es que no se puede crear una instancia de Inner2 sin un Outer donde se pueda crear un objeto Inner1 independiente.

¿Cuándo usarías la clase interna?

Piense en una situación en la que la Class A y la Class B están relacionadas, la Class B necesita acceder a Class A miembros de la Class A , y la Class B está relacionada solo con la Class A Las clases internas entran en escena

Para crear una instancia de clase interna, necesita crear una instancia de su clase externa.

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

o

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

¿Cuándo usarías la clase interna estática?

Definiría una clase interna estática cuando sepa que no tiene ninguna relación con la instancia de la clase / clase superior adjunta. Si su clase interna no utiliza métodos o campos de la clase externa, es solo una pérdida de espacio, por lo que es estático.

Por ejemplo, para crear un objeto para la clase anidada estática, use esta syntax:

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

La ventaja de una clase anidada estática es que no necesita un objeto de la clase contenedora / clase superior para funcionar. Esto puede ayudarlo a reducir el número de objetos que crea su aplicación en tiempo de ejecución.

Creo que la convención que generalmente se sigue es la siguiente:

  • clase estática dentro de una clase de nivel superior es una clase anidada
  • clase no estática dentro de una clase de nivel superior es una clase interna , que además tiene dos formas más:
    • clase local – clases nombradas declaradas dentro de un bloque como un método o cuerpo constructor
    • clase anónima : clases sin nombre cuyas instancias se crean en expresiones y enunciados

Sin embargo, algunos otros puntos para recordar son:

  • Las clases de nivel superior y las clases estáticas estáticas son semánticamente las mismas, excepto que en el caso de una clase anidada estática puede hacer referencia estática a campos / métodos estáticos privados de su clase Outer [parent] y viceversa.

  • Las clases internas tienen acceso a variables de instancia de la instancia adjunta de la clase Outer [parent]. Sin embargo, no todas las clases internas tienen instancias adjuntas, por ejemplo, las clases internas en contextos estáticos, como una clase anónima utilizada en un bloque de inicializador estático, no lo hacen.

  • La clase anónima de forma predeterminada amplía la clase padre o implementa la interfaz padre y no hay ninguna cláusula adicional para extender cualquier otra clase o implementar más interfaces. Asi que,

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

Siento que la pregunta más grande que permanece abierta ¿cuál usar y cuándo? Bueno, eso depende principalmente de la situación con la que estés lidiando, pero leer la respuesta dada por @jrudolph puede ayudarte a tomar una decisión.

Aquí hay diferencias clave y similitudes entre la clase interna de Java y la clase anidada estática.

¡Espero eso ayude!

Clase interna

  • Puede acceder a la clase externa tanto de instancia como de métodos y campos estáticos
  • Asociado con la instancia de clase adjunta, por lo que para instanciarla primero se necesita una instancia de clase externa (tenga en cuenta el lugar de la nueva palabra clave):

     Outerclass.InnerClass innerObject = outerObject.new Innerclass(); 
  • No se puede definir ningún miembro estático en sí mismo

  • No puede haber statement de clase o interfaz

Clase anidada estática

  • No se puede acceder a los métodos o campos de instancia de clase externa

  • No está asociado con ninguna instancia de clase adjunta. Por lo tanto, para instanciarlo:

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

Similitudes

  • Ambas clases internas pueden acceder incluso a campos privados y métodos de clase externa
  • También la clase Outer tiene acceso a campos privados y métodos de clases internas
  • Ambas clases pueden tener un modificador privado, protegido o de acceso público

¿Por qué usar clases anidadas?

Según la documentación de Oracle, existen varios motivos ( documentación completa ):

  • Es una forma de agrupar lógicamente clases que solo se usan en un solo lugar: si una clase es útil solo para otra clase, entonces es lógico incluirla en esa clase y mantener las dos juntas. Anidar tales “clases de ayuda” hace que su paquete sea más eficiente.

  • Aumenta la encapsulación: Considere dos clases de nivel superior, A y B, donde B necesita acceso a los miembros de A que, de lo contrario, serían declarados privados. Al ocultar la clase B dentro de la clase A, los miembros de A pueden declararse privados y B puede acceder a ellos. Además, B puede ocultarse del mundo exterior.

  • Puede conducir a un código más legible y mantenible: anidar pequeñas clases dentro de las clases de nivel superior coloca el código más cerca de donde se usa.

Clase anidada: clase dentro de clase

Tipos:

  1. Clase anidada estática
  2. Clase anidada no estática [Clase interna]

Diferencia:

Clase anidada no estática [Clase interna]

En la clase anidada no estática, el objeto de la clase interna existe dentro del objeto de la clase externa. Entonces ese miembro de datos de la clase externa es accesible a la clase interna. Entonces, para crear el objeto de la clase interna primero debemos crear el objeto de la clase externa.

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

Clase anidada estática

En la clase anidada estática, el objeto de la clase interna no necesita el objeto de la clase externa, porque la palabra “estática” indica que no es necesario crear el objeto.

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

Si desea acceder a x, escriba el siguiente método interno

  outerclass.nestedclass.x; ie System.out.prinltn( outerclass.nestedclass.x); 

La instancia de la clase interna se crea cuando se crea una instancia de la clase externa. Por lo tanto, los miembros y métodos de la clase interna tienen acceso a los miembros y métodos de la instancia (objeto) de la clase externa. Cuando la instancia de la clase externa sale del scope, también las instancias de la clase interna dejan de existir.

La clase anidada estática no tiene una instancia concreta. Acaba de cargarse cuando se usa por primera vez (al igual que los métodos estáticos). Es una entidad completamente independiente, cuyos métodos y variables no tienen ningún acceso a las instancias de la clase externa.

Las clases anidadas estáticas no están acopladas con el objeto externo, son más rápidas y no toman la memoria de montón / stack, porque no es necesario crear una instancia de dicha clase. Por lo tanto, la regla general es tratar de definir la clase anidada estática, con un scope lo más limitado posible (privado> = clase> = protegido> = público), y luego convertirlo a clase interna (eliminando el identificador “estático”) y aflojar el scope, si es realmente necesario.

Hay una sutileza sobre el uso de clases estáticas anidadas que pueden ser útiles en ciertas situaciones.

Mientras que los atributos estáticos se instancian antes de que la clase sea instanciada a través de su constructor, los atributos estáticos dentro de las clases estáticas anidadas no parecen ser instanciados hasta después de invocar el constructor de la clase, o al menos no hasta después de que los atributos sean referenciados por primera vez, incluso si están marcados como ‘final’.

Considera este ejemplo:

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

Aunque ‘nested’ e ‘innerItem’ se declaran como ‘estático final’. la configuración de nested.innerItem no tiene lugar hasta después de la creación de una instancia de la clase (o al menos no hasta que se haga referencia por primera vez al elemento estático nested), como puede ver por usted comentando y descomentando las líneas a las que me refiero, encima. Lo mismo no es cierto para ‘outerItem’.

Al menos esto es lo que estoy viendo en Java 6.0.

En el caso de crear una instancia, la instancia de la clase interna no estática se crea con la referencia del objeto de la clase externa en la que está definida. Esto significa que tiene una instancia de inclusión. Pero la instancia de la clase interna estática se crea con la referencia de la clase externa, no con la referencia del objeto de la clase externa. Esto significa que no ha incluido una instancia.

Por ejemplo:

 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(); AB obj1 =o.new B();//need of inclosing instance AC obj2 =new AC(); // not need of reference of object of outer class…. } } 

No creo que haya mucho que agregar aquí, la mayoría de las respuestas explican perfectamente las diferencias entre la clase anidada estática y las clases internas. Sin embargo, considere el siguiente problema al usar clases anidadas vs clases internas. Como se menciona en un par de respuestas, las clases internas no se pueden instanciar sin una instancia de su clase adjunta, lo que significa que MANTENER un puntero a la instancia de su clase adjunta que puede provocar un desbordamiento de memoria o una excepción de desbordamiento de stack debido al hecho de que no podrá recoger basura en las clases adjuntas aunque ya no se usen. Para que quede claro, verifique el siguiente código:

 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 ie 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 elimina el comentario en // inner = null; El progtwig lanzará ” ¡Estoy destruido! “, Pero mantener esto comentado no lo hará.
El motivo es que todavía se hace referencia a la instancia interna blanca. GC no puede recostackrla y, como hace referencia (tiene un puntero) a la instancia externa, no se recostack también. Tener suficiente de estos objetos en su proyecto y puede quedarse sin memoria.
En comparación con las clases internas estáticas que no tienen una instancia de punto a clase interna porque no está relacionada con la instancia, sino que está relacionada con la clase. El progtwig anterior puede imprimir ” ¡Estoy destruido! ” Si haces que la clase interna esté estática e instanciada con Outer.Inner i = new Outer.Inner();

Los términos se usan indistintamente. Si quieres ser realmente pedante al respecto, entonces puedes definir “clase anidada” para referirse a una clase interna estática, que no tiene instancia adjunta. En el código, puede tener algo como esto:

 public class Outer { public class Inner {} public static class Nested {} } 

Sin embargo, esa no es una definición ampliamente aceptada.

Clase anidada es un término muy general: cada clase que no es de nivel superior es una clase anidada. Una clase interna es una clase anidada no estática. Joseph Darcy escribió una muy buena explicación sobre las clases anidadas, internas, de miembros y de nivel superior .

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.

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
Ejemplo:

 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:
Ejemplo:

 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.

Conclusión:
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.

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 ie 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

I think people here should notice to Poster that : Static Nest Class just only the first inner class. Por ejemplo:

  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).

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

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

The difference is that a nested class declaration that is also static can be instantiated outside of the enclosing class.

When you have a nested class declaration that is not static, also known as an inner class , Java won’t let you instantiate it except via the enclosing class. The object created out of the inner class is linked to the object created from the outer class, so the inner class can reference the fields of the outer.

But if it’s static, then the link does not exist, the outer fields cannot be accessed (except via an ordinary reference like any other object) and you can therefore instantiate the nested class by itself.

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.

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

Just some add-ups after you having read the oracle’s java tutorial in classes and objects. It may help if you know Java’s memory model for inner class and static nested class. Please read the following three questions to get the philosophy of why inner class and static nested class are designed by Java in this way. And then you may know when to use inner class and when to use static nested class.

How inner class object resides in memory?

Memory management-Inner static class in Java

When is a static nested class (and static members therein) loaded into memory?

Then read this to compare inner class and static nested class.

What’s the advantage of making an inner class as static with Java?