usar - public static java
¿Por qué Java prohíbe campos estáticos en clases internas? (8)
lo que quiero saber es por qué java prohíbe los campos / métodos estáticos dentro de las clases internas
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 funciones static
, ya que la static
debe funcionar sin una instancia en primer lugar.
Es como si intentara crear un atributo estático / instancia al mismo tiempo.
Toma 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 el name
de la propiedad, ¿verdad?
Lo mismo sucede con la clase interna; cada instancia de clase interna es independiente de la otra instancia de clase interna.
Por lo tanto, si intenta crear un atributo de clase de counter
, no hay forma de compartir ese valor en dos instancias diferentes.
class Employee {
public String name;
class InnerData {
static count; // ??? count of which ? a or b?
}
}
Cuando crea la instancia a
y b
en el ejemplo anterior, ¿cuál sería el valor correcto para el count
variables estáticas? No es posible determinarlo, porque la existencia de la clase InnerData
depende completamente de cada uno de los objetos InnerData
.
Por eso, cuando la clase se declara como static
, ya no necesita una instancia viviente para vivirla. Ahora que no hay dependencia, puede declarar libremente un atributo estático.
Creo que esto suena reiterativo, pero si piensas en las diferencias entre los atributos instancia vs. clase, tendrá sentido.
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 deseo registrar algo que debería ser estático, por ejemplo, el número de objetos InnerClass creados, sería útil mantener ese campo estático. Entonces, ¿ por qué Java prohíbe campos / métodos estáticos en clases internas?
EDITAR: Sé cómo hacer feliz al compilador con la clase anidada estática (o clase interna estática), pero lo que quiero saber es por qué java prohíbe campos / métodos estáticos dentro de las clases internas (o clase interna ordinaria) tanto del diseño del lenguaje como aspectos de implementación, si alguien sabe más al respecto.
- clase La secuencia de inicialización es una razón crítica.
Como las clases internas dependen de la instancia de inclusión / clase externa, entonces la clase externa debe inicializarse antes de la inicialización de la clase interna.
Esto es JLS dice sobre Inicialización de clase. El punto que necesitamos es que la clase T se inicialice si
- Se utiliza un campo estático declarado por T y el campo no es una variable constante.
Entonces, si la clase interna tiene un acceso de campo estático que causará la inicialización de la clase interna, pero eso no asegurará que la clase envolvente se inicialice.
Violaría algunas reglas básicas . puede saltar a la última sección (a
two cases
) para evitar cosas novato
Una cosa sobre static nested
class
static nested
, cuando una nested class
es static
se comportará como una clase normal en todos los sentidos y se asocia con la clase Outer.
Pero el concepto de Inner class
/ Inner class
nested class
non-static
es que se asociará con la instance
de clase externa / adjunta. Tenga en cuenta asociado a la instancia, no a la clase. Ahora asociar con la instancia significa claramente que ( del concepto de variable de instancia ) existirá dentro de una instancia y será diferente entre las instancias.
Ahora, cuando hacemos algo estático, esperamos que se inicialice cuando se cargue la clase y se debe compartir entre todas las instancias. Pero por ser no estático, incluso las propias clases internas ( definitivamente puede olvidarse de la instancia de la clase interna por el momento ) no se comparten con todas las instancias de la clase externa / adjunta ( 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 .
- Si se comparte con toda la instancia de clase interna, violará el concepto de
context of instance
(variable de instancia). Es un NO entonces. - Si no se comparte con todas las instancias, violará el concepto de ser estático. Nuevamente NO.
Aquí está la motivación que considero 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; Entonces no necesitas campos / métodos estáticos . El comportamiento que quiero decir es que todas las instancias de clase interna de algún objeto comparten un campo (o método).
Entonces, supongamos que quieres contar todas las instancias de la clase interna, harías:
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++;
}
}
}
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 tiempo de carga de clase. Así que la clase interna no estática es lo de tiempo de ejecución, por eso estática no es la 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.
En realidad, puede declarar campos estáticos si son constantes y se escriben 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
}
}
}
La idea detrás de las clases internas es operar en el contexto de la instancia adjunta. De alguna manera, ¿permitir variables estáticas y métodos contradice esta motivación?
8.1.2 Clases internas e instancias adjuntas
Una clase interna es una clase anidada que no está explícita o implícitamente declarada estática. Las clases internas no pueden declarar inicializadores estáticos (§8.7) o interfaces de miembros. Las clases internas no pueden declarar miembros estáticos, a menos que sean campos constantes en tiempo de compilación (§15.28).
Supongo que es por consistencia. Si bien no parece haber ninguna limitación técnica para ello, 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.
InnerClass
no puede tener miembros static
porque pertenece a una instancia (de OuterClass
). Si declara InnerClass
como static
para separarlo de la instancia, su código se compilará.
class OuterClass {
static class InnerClass {
static int i = 100; // no compile error
static void f() { } // no compile error
}
}
Por cierto: todavía podrás crear instancias de InnerClass
. static
en este contexto permite que eso ocurra sin una instancia OuterClass
de OuterClass
.