Clase interna 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?

Author: Micha Sprengers, 2008-09-16

24 answers

Del Tutorial de Java :

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

Se accede a las clases anidadas estáticas usando el nombre de clase adjunto:

OuterClass.StaticNestedClass

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

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

Objetos que son instancias de un la clase interna existe 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 que la encierra.

Para instanciar una clase interna, primero debe instanciar la clase externa. Luego, cree el objeto interno dentro del objeto externo con esta sintaxis:

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

Ver: Java Tutorial-Clases anidadas

Para completitud tenga en cuenta que también existe una cosa como una clase interna sin una instancia que encierra :

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

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

 1511
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:47

El tutorial de Java dice :

Terminología: Las clases anidadas son dividido en dos categorías: estática y no estático. Clases anidadas que se declaran estáticas se llaman simplemente clases anidadas estáticas. No estático las clases anidadas se llaman internas clase.

En el lenguaje común, los términos "anidado" e "interior" se utilizan indistintamente por la mayoría de los programadores, pero voy a utilizar el término correcto "clase anidada" que cubre tanto estática.

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, más de un nivel de anidamiento de clase es raro, ya que generalmente es un mal diseño.

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

  • organización: a veces parece más sensato ordenar una clase en el espacio de nombres de otra clase, especialmente cuando no se usará 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 utilizará en un contexto

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

  • clase estática : declarada como estática miembro 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 detallar más.


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, tal clase es realmente solo una suspensión que utiliza 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 por el nombre pizza.Rhino.Cabra.

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

, Francamente, estática las clases 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 tal clase tiene acceso a los miembros estáticos privados de la clase que la contiene, pero encuentro que esto es una justificación bastante patética para que exista la característica de la clase estática.


Clases internas

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

package pizza;

public class Rhino {

    public class Goat {
        ...
    }

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

Como con a clase estática, la clase interna es conocida como calificada por su nombre de clase contenedora, pizza.Rhino.Goat, pero dentro de la clase contenedora, puede ser conocida por su nombre simple. Sin embargo, cada instancia de una clase interna está ligada a una instancia en particular de su clase contenedora: arriba, el Cabra creado en jerry, está implícitamente ligado a la Rhino ejemplo este{[18] {} en[17]}jerry. De lo contrario, hacemos la instancia asociada Rhino explicit when we instanciate Goat :

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

(Observe que se refiere al tipo interno como solo Cabra en la sintaxis extraña nueva: Java infiere el tipo que lo contiene de la parte rhino. Y, sí nuevo rhino.Goat () habría tenido más sentido para mí también.)

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 de instancia que encierran se refieren dentro la clase interna vía solo sus nombres simples, no vía esto (esto en la clase interna se refiere a la instancia de clase interna, no a la instancia de clase contenedora asociada):

public class Rhino {

    private String barry;

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

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


Clases Internas locales

A la clase interna local es una clase declarada en el cuerpo de un método. Tal clase solo se conoce dentro de su método contenedor, por lo que solo puede ser instanciada y tener acceso 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 que contiene. 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 ha salido de su alcance (esto es efectivamente la versión cruda y 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 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 mantenida por el método que contiene this en el momento del creación de la instancia, por lo que los miembros de la instancia de la clase contenedora son accesibles como en una clase interna de instancia. Una clase interna local se crea una instancia simplemente a través de su nombre, por ejemplo, la clase interna local Cat se crea una instancia como new Cat () , this.Cat () como era de esperar.


Clases Internas anónimas

Una clase interna anónima es una forma sintácticamente conveniente de escribir una clase interna local. Más comúnmente, un local la clase interna se crea una instancia como máximo solo una vez cada vez que se ejecuta su método que contiene. Sería bueno, entonces, si pudiéramos combinar la definición de clase interna local y su única instanciación en una forma de sintaxis conveniente, y también sería bueno si no tuviéramos que idear un nombre para la clase (cuantos menos nombres inútiles contenga su 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 puede suministrar su propio constructor; más bien, se suministra implícitamente uno que simplemente llama al super constructor, por lo que los argumentos suministrados deben ajustarse al super constructor. (Si el padre contiene varios constructores, el " más simple "se llama," más simple " según lo determinado por un conjunto bastante complejo de reglas que no vale la pena molestarse en aprender en detalle just solo preste atención a lo que NetBeans o Eclipse le dicen.)

Alternativamente, puede especificar un interfaz a implementar:

new *InterfaceName*() {*members*}

Tal declaración crea una nueva instancia de una clase sin nombre que extiende Object e implementa InterfaceName. Una vez más, no puede proporcionar su propio constructor; en este caso, Java suministra implícitamente un constructor no-arg, do-nothing (por lo que nunca habrá argumentos de constructor en este caso).

Aunque no puedes darle un constructor a una clase interna anónima, aún puedes hacer cualquier configuración que quieras usando un bloque inicializador (a {} bloque colocado fuera de cualquier método).

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

 531
Author: Jegschemesch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-04 08:40:03

No creo que la verdadera diferencia quede clara en las respuestas anteriores.

Primero en obtener los términos correctos:

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

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

Usa clases anidadas estáticas si solo desea mantener sus clases juntas si pertenecen tópicamente juntas o si la clase anidada se usa exclusivamente en la clase que las encierra. 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, tales clases anidadas son en realidad cierres. Que significa que capturan su ámbito circundante y su instancia envolvente y la hacen accesible. Tal vez un ejemplo lo aclare. 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 hijo al contenedor padre. Usando una clase anidada no estática, esto funciona sin algún trabajo. Puede acceder a la instancia de contenedor con la sintaxis Container.this.

Más explicaciones hardcore siguientes:

Si nos fijamos en el Java bytecodes que genera el compilador para una clase anidada (no estática) podría ser aún más claro:

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

Como puede ver, el compilador 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 que encierra. No puede ver este parámetro en la fuente, pero el compilador lo genera implícitamente para una clase anidada.

El ejemplo de Martin

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

Así se compilaría a una llamada de algo como (en bytecodes)

new InnerClass(outerObject)

En aras de la integridad:

Una clase anónima es un ejemplo perfecto de una clase anidada no estática que simplemente no tiene un nombre asociado y no se puede hacer referencia a ella más tarde.

 126
Author: jrudolph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-27 07:53:39

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

Descripción general

Una clase anidada podría ser estático o estática y en cada caso es una clase definida dentro de otra. Una clase anidada debe existir solo para servir es encerrar la clase, si una clase anidada es útil para otras clases (no solo la que encierra), debe declararse como un nivel superior clase.

Diferencia

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

Clase anidada estática: no se puede acceder a la instancia de clase encerrada 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 que encierra . Un uso común de la clase anidada estática es implementar componentes del objeto externo.

Conclusión

Así que 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.

 83
Author: aleroot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-28 23:47:23

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 que las encierra. Son de dos tipos: estáticos y no estáticos.

Se tratan como miembros de la clase que encierra, 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 se pueden declarar public o paquete-privado.

Clases internas aka No de la pila de clases tienen acceso a los otros miembros de la clase superior, incluso si se declaran privado, mientras que la Estática de las clases anidadas 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 y Inner2 es nuestra clase interna que no es estático. La diferencia clave entre ellos, no se puede crear una instancia Inner2 sin un Exterior donde como se puede crear un objeto Inner1 de forma independiente.

¿Cuándo usarías la clase interna?

Piense en un situación en la que Class A y Class B están relacionados, Class B necesita acceder a Class A miembros, y Class B está relacionado solo con 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/top que la encierra clase. Si tu clase interna no usa métodos o campos de la clase externa, es solo una pérdida de espacio, así que hazlo estático.

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

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 ayudarle a reducir el número de objetos que su aplicación crea en tiempo de ejecución.

 29
Author: Thalaivar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-02 05:15:01

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

  • clase estática dentro de una clase de nivel superior hay una clase anidada
  • clase no estática dentro de una clase de nivel superior hay una clase interna , que además tiene dos formas más:
    • clase local - clases con nombre 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 declaraciones

Sin embargo, pocos otros puntos para recordar son:

  • Las clases de nivel superior y la clase anidada estática son semánticamente iguales, excepto que en el caso de la clase anidada estática puede hacer referencia estática a campos/métodos estáticos privados de su clase externa [padre] y viceversa.

  • Las clases internas tienen acceso a las variables de instancia de la instancia que encierra la clase [padre] externa. Sin embargo, no todas las clases internas tienen encerrar instancias, por ejemplo clases internas en contextos estáticos, como una clase anónima utilizada en un bloque inicializador estático, no lo hace.

  • La clase anónima por defecto extiende 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. Así,

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

Siento que la pregunta más grande que permanece abierto cuál usar y cuándo? Bueno, eso depende principalmente del escenario con el que estés tratando, pero leer la respuesta dada por @jrudolph puede ayudarte a tomar alguna decisión.

 24
Author: sactiw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-24 05:40:10

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

Espero que ayude!

Clase interna

  • Puede acceder a a la clase externa tanto métodos y campos de instancia como estáticos
  • Asociado con la instancia de la clase que encierra así que para instanciar primero necesita una instancia de la clase externa (nota nuevo lugar de la palabra clave):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • No se puede definir ninguna miembros estáticos a sí mismos

  • No tiene Class o Interface declaración

Clase anidada estática

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

  • No asociado con ninguna instancia de la clase que encierra Así que para instanciarla:

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

Similitudes

  • Ambas Clases internas pueden acceder incluso a privadas campos y métodos de la clase externa
  • También los Clase externa tienen acceso a campos privados y métodos de clases internas
  • Ambas clases pueden tener modificador de acceso privado, protegido o público

¿Por Qué Usar Clases Anidadas?

De acuerdo con la documentación de Oracle hay varias razones ( documentación completa):

  • Es una forma de agrupar lógicamente las clases que son usado en un lugar: Si una clase es útil solo para otra clase, entonces es lógico incrustarla en esa clase y mantener las dos juntas. Anidando tales "clases de ayuda" hace que su paquete sea más ágil.

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

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

 23
Author: Behzad Bahmanyar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-26 07:39:52

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. Por lo que el miembro de datos de la clase externa es accesible a la clase interna. Así que para crear un objeto de clase interna debemos crear un objeto de clase externa primero.

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 hay necesidad de crear un 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;  i.e. System.out.prinltn( outerclass.nestedclass.x);
 13
Author: tejas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-10 23:57:03

La instancia de la clase interna se crea cuando se crea la 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 ámbito, también las instancias de la clase interna dejan de existir.

La clase anidada estática no tiene una instancia concreta. Solo se carga cuando se usa por primera vez (al igual que los métodos estáticos). Es un entidad completamente independiente, cuyos métodos y variables no tienen 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 memoria de montón/pila, porque no es necesario crear instancia de dicha clase. Por lo tanto, la regla general es tratar de definir la clase anidada estática, con el alcance más limitado posible (privado > = clase > = protegido > = público), y luego convertirla en clase interna (por eliminar el identificador "estático") y aflojar el alcance, si es realmente necesario.

 10
Author: rmaruszewski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 08:58:40

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

Mientras que los atributos estáticos se instancian antes de que la clase se instancie a través de su constructor, los atributos estáticos dentro de las clases estáticas anidadas no parecen ser instanciados hasta después del el constructor de la clase se invoca, o al menos no hasta después de que se haga referencia por primera vez a los atributos, incluso si están marcados como 'final'.

Considere esto 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 'anidado' y 'innerItem' se declaran como 'static final'. configuración de anidados.innerItem no se lleva a cabo hasta después de que se instancie la clase (o al menos no hasta después de que se haga referencia por primera vez al elemento estático anidado), como puede ver por sí mismo comentando y descomentando las líneas a las que me refiero, arriba. Lo mismo no se sostiene cierto para 'outerItem'.

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

 10
Author: HippoMan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-26 12:48:47

En el caso de crear instancia, la instancia de non clase interna estática se crea con la referencia de objeto de la clase externa en la que se define. Este significa que tiene incluyendo la instancia. 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 incluyendo la 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();
    A.B obj1 =o.new B();//need of inclosing instance

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

    // not need of reference of object of outer class….
  }
}
 9
Author: Ankit Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-14 12:43:57

No creo que haya mucho que añadir aquí, la mayoría de las respuestas explican perfectamente las diferencias entre las clases anidadas estáticas 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 que las encierra, lo que significa que SOSTIENEN un puntero a la instancia de su clase que las encierra, lo que puede conducir a un desbordamiento de memoria o excepción debido al hecho de que el GC no será capaz de recoger basura las clases que encierran incluso si no se utilizan más. Para aclarar esto, compruebe 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 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 eliminas el comentario en // inner = null; El programa saldrá "estoy destruido !", pero manteniendo esto comentado no lo hará.
La razón es que la instancia interna blanca todavía está referenciada GC no puede recopilarla y porque hace referencia (tiene un puntero a) a la instancia externa no se recopila demasiado. Tener suficiente de estos objetos en su proyecto y puede quedarse sin memoria.
En comparación con las clases internas estáticas que no mantienen un punto a la instancia de clase interna porque no está relacionada con la instancia sino con la clase. El programa anterior puede imprimir " ¡Estoy destruido ! " si haces que la clase interna sea estática e instanciada con Outer.Inner i = new Outer.Inner();

 9
Author: Adelin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-15 09:27:24

Los términos se usan indistintamente. Si desea ser realmente pedante al respecto, entonces podría definir "clase anidada" para referirse a una clase interna estática, una que no tiene instancia de encierro. En código, usted podría tener algo como esto:

public class Outer {
    public class Inner {}

    public static class Nested {}
}

Esa no es realmente una definición ampliamente aceptada.

 7
Author: Daniel Spiewak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 08:25:42

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, Miembros y de Alto Nivel.

 7
Author: Wouter Coekaerts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-03 02:31:14

Ummm... una clase interna ES una clase anidada... ¿te refieres a la clase anónima y a la clase interna?

Editar: Si en realidad se refería interno vs anónimo... una clase interna es solo una clase definida dentro de una clase como:

public class A {
    public class B {
    }
}

Considerando que una clase anónima es una extensión de una clase definida anónimamente, por lo que no se define ninguna clase "real, como en:

public class A {
}

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

Edición adicional:

Wikipedia afirma que hay una diferencia en Java, pero he estado trabajando con Java durante 8 años, y es la primera vez que escucho tal distinción... sin mencionar que no hay referencias que respalden la afirmación... en pocas palabras, una clase interna es una clase definida dentro de una clase (estática o no), y anidado es solo otro término para significar lo mismo.

Hay una diferencia sutil entre la clase anidada estática y no estática... básicamente, las clases internas no estáticas tienen acceso implícito a los campos de instancia y métodos de la clase envolvente (por lo tanto, no se pueden construir en un contexto estático, será un error del compilador). Las clases anidadas estáticas, por otro lado, no tienen acceso implícito a los campos y métodos de instancia, y SE PUEDEN construir en un contexto estático.

 6
Author: Mike Stone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-28 03:49:57

Dirigido al alumno, que es principiante en Java y / o Clases Anidadas

Las clases anidadas pueden ser:
1. Clases anidadas estáticas.
2. Clases anidadas No estáticas. (también conocido como Clases internas ) = > Por favor recuerde esto


1.Clases internas
Ejemplo:

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


las clases Internas son subconjuntos de clases anidadas:

  • la clase interna es un tipo específico de clase anidada
  • las clases internas son subconjuntos de clases anidadas
  • Se puede decir que un clase interna es también una clase anidada, pero usted puede NO decir que una clase anidada es también una clase interna.

Especialidad de la clase interna:

  • la instancia de una clase interna tiene acceso a todos los miembros de la clase externa, incluso aquellos que están marcados como "privados"{[28]]}


2.Clases Anidadas estáticas:
Ejemplo:

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

Caso 1: Instanciar una clase anidada estática desde una clase no encerrante

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

Caso 2: Instanciación de una clase anidada estática desde una clase envolvente

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

}

Especialidad de clases estáticas:

  • La clase interna estática solo tendría acceso a los miembros estáticos de la clase externa, y no tendría acceso a los miembros no estáticos.

Conclusión:
Pregunta: ¿Cuál es la principal diferencia entre una clase interna y una ¿clase anidada estática en Java?
Respuesta: simplemente repasa los detalles de cada clase mencionada anteriormente.

 6
Author: VedX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-06 21:47:56

La clase interna y la clase estática anidada en Java son clases declaradas dentro de otra clase, conocida como clase de nivel superior en Java. En terminología Java, si declara una clase anidada estática, se llamará clase estática anidada en Java, mientras que las clases anidadas no estáticas se denominan simplemente Clase Interna.

¿Qué es la Clase Interna en Java?

Cualquier clase que no es un nivel superior o declarada dentro de otra clase se conoce como clase anidada y fuera de ellas las clases anidadas, que son declaradas no estáticas, se conocen como clase interna en Java. hay tres tipos de clase interna en Java:

1) Clase interna local - se declara dentro de un bloque de código o método.
2) Clase interna anónima - es una clase que no tiene nombre para hacer referencia e inicializada en el mismo lugar donde se crea.
3) Clase interna del miembro - se declara como miembro no estático de la clase externa.

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é es la clase estática anidada en ¿Java?

La clase estática anidada es otra clase que se declara dentro de una clase como miembro y se hace estática. La clase estática anidada también se declara como miembro de la clase externa y puede hacerse privada, pública o protegida como cualquier otro miembro. Uno de los principales beneficios de la clase estática anidada sobre la clase interna es que la instancia de la clase estática anidada no se adjunta a ninguna instancia de la clase externa. Tampoco necesita ninguna instancia de clase externa para crear una instancia de anidada clase estática en Java .

1) Puede acceder a miembros de datos estáticos de clase externa incluyendo privado.
2) La clase anidada estática no puede acceder a miembro de datos no estático (instancia) o método.

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: Clase interna y Clase Estática anidada en Java con Ejemplo

 5
Author: roottraveller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-22 10:39:26

Creo que la gente aquí debería notar a Poster que : Clase de Nido estático solo la primera clase interna. 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 !!!

 }

Así que, en resumen, la clase estática no depende de qué clase contiene. Por lo tanto, no pueden en clase normal. (porque la clase normal necesita una instancia).

 4
Author: hqt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-21 18:10:14

Cuando declaramos clase miembro estática dentro de una clase, se conoce como clase anidada de nivel superior o clase anidada estática. Se puede demostrar de la siguiente manera :

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

Cuando declaramos clase miembro no estática dentro de una clase se conoce como clase interna. La clase interna se puede demostrar de la siguiente manera:

    class Test{
        private int i = 10;
        class A{
            private int i =20;
            void display(){
            int i = 30;
            System.out.println(i);
            System.out.println(this.i);
            System.out.println(Test.this.i);
        }
    }
}
 4
Author: Pankti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-02 17:00:09

El siguiente es un ejemplo de static nested class y inner class:

Clase externa.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);
     }

}

Prueba más externa:

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

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

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

        //Declaration

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

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

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

    }

}
 2
Author: Pritam Banerjee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-03 23:10:14

La diferencia es que una declaración de clase anidada que también es estática puede ser instanciada fuera de la clase que la encierra.

Cuando tiene una declaración de clase anidada que es no estática, también conocida como una clase interna , Java no le permitirá instanciarla excepto a través de la clase que la encierra. El objeto creado a partir de la clase interna está vinculado al objeto creado a partir de la clase externa, por lo que la clase interna puede hacer referencia a los campos de la clase externa.

Pero si es estático, entonces el enlace no existe, no se puede acceder a los campos externos (excepto a través de una referencia ordinaria como cualquier otro objeto) y, por lo tanto, puede crear una instancia de la clase anidada por sí misma.

 0
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-23 21:40:09

En primer lugar no existe tal clase llamada clase estática.El modificador estático use with inner class (llamado como Clase Anidada) dice que es un miembro estático de la Clase Externa, lo que significa que podemos acceder a él como con otros miembros estáticos y sin tener ninguna instancia de la clase externa. (Que es el beneficio de la estática originalmente.)

La diferencia entre usar la clase anidada y la clase interna regular es:

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

Primero podemos instanciar Outerclass luego podemos acceder a Inner.

Pero si la clase está anidada, la sintaxis es:

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

Que utiliza la sintaxis estática como implementación normal de la palabra clave estática.

 0
Author: Sohi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-01 19:18:01

He ilustrado varios posibles escenarios correctos y de error que pueden ocurrir en el código java.

    class Outter1 {

        String OutStr;

        Outter1(String str) {
            OutStr = str;
        }

        public void NonStaticMethod(String st)  {

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

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

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

            // synchronized keyword is not permitted below          
            class localInnerNonStatic1 {            

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

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

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

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

        }

        public static  void StaticMethod(String st)     {

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

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

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

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

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

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

        }

        // synchronized keyword is not permitted
        static  class inner1 {          

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

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

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

        //synchronized keyword is not permitted below
        class innerNonStatic1 {             

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

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

            /*
            //  error in below step
            public static void innerStaticMethod(String str11) {   
                            //  error in below step
                            // str11 = tempNonStatic +" india";                     
                            str11 = temp1 +" india";
                            System.out.println("innerMethod ===> "+str11);
                        }*/
                    //}
                }
    }
 0
Author: Ashish Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-11 06:50:50

Solo algunos complementos después de haber leído el tutorial java de oracle en clases y objetos. Puede ayudar si conoce el modelo de memoria de Java para la clase interna y la clase anidada estática. Lea las siguientes tres preguntas para obtener la filosofía de por qué la clase interna y la clase anidada estática están diseñadas por Java de esta manera. Y entonces usted puede saber cuándo usar clase interna y cuándo usar clase anidada estática.

¿Cómo reside el objeto de clase interna en la memoria?

Memoria gestión-Clase estática interna en Java

¿Cuándo se carga una clase anidada estática (y sus miembros estáticos) en la memoria?

Entonces lea esto para comparar la clase interna y la clase anidada estática.

¿Cuál es la ventaja de hacer que una clase interna sea estática con Java?

 0
Author: Han XIAO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-24 04:33:32