method - static block java
Comportamiento de bloques estáticos con herencia (5)
Aquí está el enlace a la especificación de Java: la sección 8.7 habla sobre inicializadores estáticos. Proporciona buenos detalles sobre cómo deberían funcionar y el orden en el que reciben el llamado. http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.7
Estoy tratando de usar bloques estáticos como este:
Tengo una clase base llamada Base.java
public class Base {
static public int myVar;
}
Y una clase derivada Derived.java
:
public class Derived extends Base {
static
{
Base.myVar = 10;
}
}
Mi función main
es así:
public static void main(String[] args) {
System.out.println(Derived.myVar);
System.out.println(Base.myVar);
}
Esto imprime el out puesto como 0 0
donde como esperaba 10 0
. ¿Alguien puede explicar este comportamiento? Además, si quiero que mis clases derivadas establezcan los valores para una variable estática, ¿cómo puedo lograr eso?
Cuando lo hacemos
class Base {
public static int myVar = 0;
static {
System.out.println("Base");
}
}
class Derived extends Base {
static {
System.out.println("Derived");
Base.myVar = 9;
}
}
public class StaticBlock {
public static void main(String[] args) {
System.out.println(Base.myVar);
System.out.println(Derived.myVar);
}
}
La salida será Base 0 0
Eso significa que el bloque estático de la clase derivada no se ejecuta ... !!
Hay una sola copia de myVar
y las clases de padres e hijos compartirán la misma. Hasta y a menos que la clase infantil sea iniciada.
Los bloques de inicializador estáticos no se ejecutan hasta que la clase se inicializa. Consulte la Especificación del lenguaje Java, párrafos 8.7 (Inicializadores estáticos) y 12.4.1 (Cuando se produce la inicialización):
Un inicializador estático declarado en una clase se ejecuta cuando la clase se inicializa (§12.4.2). Junto con cualquier inicializador de campo para variables de clase (§8.3.2), los inicializadores estáticos se pueden usar para inicializar las variables de clase de la clase.
Aquí hay un ejemplo similar directamente de JLS 12.4.1:
class Super {
static int taxi = 1729;
}
class Sub extends Super {
static { System.out.print("Sub "); }
}
class Test {
public static void main(String[] args) {
System.out.println(Sub.taxi);
}
}
Este programa solo imprime:
1729
porque la clase Sub nunca se inicializa; la referencia a Sub.taxi es una referencia a un campo realmente declarado en la clase Súper y no activa la inicialización de la clase Sub.
Según entiendo. No llama a ninguna propiedad Derived
( myVar
pertenece a Base
, no a Derived
). Y java no está ejecutando bloque estático desde Derived
. Si agrega un campo estático a Derived
y accede a él, java ejecuta todos los bloques estáticos.
class Base {
static public int myVar;
}
class Derived extends Base {
static public int myVar2;
static
{
Base.myVar = 10;
}
}
public class Main {
public static void main( String[] args ) throws Exception {
System.out.println(Derived.myVar2);
System.out.println(Base.myVar);
}
}
De la especificación java, cuando la clase se inicializa (y se ejecuta el bloque estático):
12.4.1 Cuando se produce la inicialización Una clase o interfaz tipo T se inicializará inmediatamente antes de la primera aparición de cualquiera de los siguientes:
• T es una clase y se crea una instancia de T.
• T es una clase y se invoca un método estático declarado por T.
• Se asigna un campo estático declarado por T.
• Se utiliza un campo estático declarado por T y el campo no es una variable constante (§4.12.4).
• T es una clase de nivel superior (§7.6) y se ejecuta una declaración de afirmación (§14.10) léxicamente anidada dentro de T (§8.1.3).