class OuterClass {
class InnerClass {
static int i = 100; // compile error
static void f() { } // compile error
}
}
Aunque no es posible acceder al campo estático con OuterClass.InnerClass.i
, si quiero grabar algo que debería ser estático, por ejemplo, el número de objetos InnerClass creados, sería útil hacer que ese campo sea estático. Entonces, ¿ por qué Java prohíbe los campos / métodos estáticos en las clases internas?
EDITAR: Sé cómo hacer feliz al compilador con la clase anidada estática (o la clase interna estática), pero lo que quiero saber es por qué Java prohíbe los campos / métodos estáticos dentro de las clases internas (o la clase interna ordinaria) tanto del diseño del lenguaje como aspectos de implementación, si alguien sabe más al respecto.
java
inner-classes
static-members
Jichao
fuente
fuente
Respuestas:
La idea detrás de las clases internas es operar en el contexto de la instancia adjunta. De alguna manera, ¿permitir variables y métodos estáticos contradice esta motivación?
fuente
Porque esas clases internas son clases internas de "instancia". Es decir, son como un atributo de instancia del objeto adjunto.
Dado que son clases de "instancia", no tiene sentido permitir
static
características, ya questatic
está destinado a funcionar sin una instancia en primer lugar.Es como si intentaras crear un atributo estático / instancia al mismo tiempo.
Tome el siguiente ejemplo:
class Employee { public String name; }
Si crea dos instancias de empleado:
Employee a = new Employee(); a.name = "Oscar"; Employee b = new Employee(); b.name = "jcyang";
Está claro por qué cada uno tiene su propio valor para la propiedad
name
, ¿verdad?Lo mismo ocurre con la clase interior; cada instancia de clase interna es independiente de la otra instancia de clase interna.
Entonces, si intenta crear un
counter
atributo de clase, no hay forma de compartir ese valor entre dos instancias diferentes.class Employee { public String name; class InnerData { static count; // ??? count of which ? a or b? } }
Cuando crea la instancia
a
yb
en el ejemplo anterior, ¿cuál sería un valor correcto para la variable estáticacount
? No es posible determinarlo, porque la existencia de laInnerData
clase depende completamente de cada uno de los objetos que la encierran.Por eso, cuando la clase se declara como
static
, ya no necesita una instancia viva para vivir ella misma. Ahora que no hay dependencia, puede declarar libremente un atributo estático.Creo que esto suena reiterativo, pero si piensa en las diferencias entre los atributos de instancia y de clase, tendrá sentido.
fuente
final
, se permiten campos estáticos en la clase interna en java. ¿Cómo explica este escenario?InnerClass
no puede tenerstatic
miembros porque pertenece a una instancia (deOuterClass
). Si se declaraInnerClass
comostatic
para separarla de la instancia, el código se compila.class OuterClass { static class InnerClass { static int i = 100; // no compile error static void f() { } // no compile error } }
Por cierto: aún podrás crear instancias de
InnerClass
.static
en este contexto permite que eso suceda sin una instancia adjunta deOuterClass
.fuente
InnerClass
no no pertenecen aOuterClass
, los casos de que lo hacen. Las dos clases en sí mismas no tienen tal relación. La pregunta de por qué no puede tener métodos estáticosInnerClass
sigue en pie.En realidad, puede declarar campos estáticos si son constantes y están escritos en tiempo de compilación.
class OuterClass { void foo() { class Inner{ static final int a = 5; // fine static final String s = "hello"; // fine static final Object o = new Object(); // compile error, because cannot be written during compilation } } }
fuente
Como las clases internas dependen de la instancia de la clase envolvente / externa, la clase externa debe inicializarse antes de la inicialización de la clase interna.
Esto es lo que dice JLS sobre la inicialización de clases. El punto que necesitamos es que la clase T se inicializará si
Entonces, si la clase interna tiene acceso a un campo estático, eso provocará la inicialización de la clase interna, pero eso no garantizará que la clase circundante se inicialice.
Violaría algunas reglas básicas . puedes saltar a la última sección (a
two cases
) para evitar cosas de novatosUna cosa es que cuando alguna se comportará como una clase normal en todos los sentidos y está asociada con la clase Outer.
static nested
class
nested class
static
Pero el concepto de
Inner class
/ es se asociará con el de la clase exterior / envolvente. Tenga en cuenta asociado con la instancia, no la clase. Ahora asociar con instancia significa claramente que ( desde el concepto de variable de instancia ) existirá dentro de una instancia y será diferente entre instancias.non-static
nested class
instance
Ahora, cuando hacemos algo estático, esperamos que se inicialice cuando la clase se esté cargando y debería compartirse entre todas las instancias. Pero para ser no estáticos, incluso las clases internas en sí mismas ( definitivamente puede olvidarse de la instancia de la clase interna por ahora ) no se comparten con todas las instancias de la clase externa / envolvente ( al menos conceptualmente ), entonces, ¿cómo podemos esperar que alguna variable de la clase interna se compartirá entre todas las instancias de la clase interna.
Entonces, si Java nos permite usar una variable estática dentro de una clase anidada no estática. habrá dos casos .
context of instance
(variable de instancia). Entonces es un NO.fuente
Aquí está la motivación que encuentro más adecuada para este "límite": puede implementar el comportamiento de un campo estático de una clase interna como un campo de instancia del objeto externo; Por lo tanto, no necesita campos / métodos estáticos . El comportamiento al que me refiero es que todas las instancias de clase interna de algún objeto comparten un campo (o método).
Entonces, suponga que quisiera contar todas las instancias de clases internas, haría:
public class Outer{ int nofInner; //this will count the inner class //instances of this (Outer)object //(you know, they "belong" to an object) static int totalNofInner; //this will count all //inner class instances of all Outer objects class Inner { public Inner(){ nofInner++; totalNofInner++; } } }
fuente
final
entonces.En palabras simples, las clases internas no estáticas son variables de instancia para la clase externa, y se crean solo cuando se crea una clase externa y se crea un objeto de clase externa en tiempo de ejecución, mientras que las variables estáticas se crean en el momento de carga de la clase. Entonces, la clase interna no estática es algo en tiempo de ejecución, por eso la estática no es parte de una clase interna no estática.
NOTA: trate las clases internas siempre como una variable para una clase externa, pueden ser estáticas o no estáticas como cualquier otra variable.
fuente
static final
constantes.Porque causaría ambigüedad en el significado de "estático".
Tomado de "Core Java SE 9 for the Impatient" de Cay S. Horstmann. Pg 90 Capítulo 2.6.3
fuente
Supongo que es por coherencia. Si bien no parece haber ninguna limitación técnica, no podrá acceder a los miembros estáticos de la clase interna desde el exterior, es decir,
OuterClass.InnerClass.i
porque el paso intermedio no es estático.fuente
static final
constantes.