sirve que para herencia ejercicios ejemplos comando java inheritance static static-initialization

que - super java herencia



Inicialización estática java con herencia. (5)

public class Main { public static void main(String[] args) { System.out.println(B.x); } } class A { public static String x = "x"; } class B extends A { static { System.out.print("Inside B."); } }

Pregunta: ¿Por qué la salida será: x . Pero no: Inside Bx


Debido a que Bx es en realidad Ax solo se necesita cargar la clase A


En realidad, no necesita cargar B hasta que accede directamente a un miembro estático de B Tenga en cuenta que este código:

public class TestMain { public static void main(String[] args) { System.out.println(B.x); System.out.println(B.y); } static class A { public static String x = "x"; } static class B extends A { public static String y = "y"; static { System.out.print("Inside B."); } } }

Saldrá:

x Inside B.y

Porque no es necesario cargar B hasta que se acceda a algo en B

Aquí hay un buen enlace sobre el tema. Del artículo: "Y no lo olvides, este código se ejecutará cuando JVM cargue la clase. JVM combina todos estos bloques en un solo bloque estático y luego se ejecuta. Aquí hay un par de puntos que me gustaría mencionar:"


La referencia a Bx emite el siguiente bytecode:

getstatic #3 <Field int B.x>

Según la especificación de la máquina virtual de Java

Las instrucciones de la máquina virtual de Java son una nueva opción, checkcast, getfield, getstatic , instanceof, invokedynamic, invokeinterface, invokepecial, invokestatic, invokevirtual, ldc, ldc_w, multianewarray, new, putfield y putstatic hacen referencias simbólicas al conjunto constante de runtime. La ejecución de cualquiera de estas instrucciones requiere la resolución de su referencia simbólica .

Así que la JVM debería resolver la referencia simbólica a Bx . La resolución del campo se especifica así :

Para resolver una referencia simbólica no resuelta de D a un campo en una clase o interfaz C, primero debe resolverse la referencia simbólica a C dada por la referencia de campo (§5.4.3.1).

...

Al resolver una referencia de campo, la resolución de campo primero intenta buscar el campo referenciado en C y sus superclases :

Si C declara un campo con el nombre y el descriptor especificados por la referencia del campo, la búsqueda del campo es exitosa. El campo declarado es el resultado de la búsqueda de campo.

De lo contrario, la búsqueda de campos se aplica recursivamente a las superinterfaces directas de la clase o interfaz C especificada.

De lo contrario, si C tiene una superclase S, la búsqueda de campos se aplica recursivamente a S.

De lo contrario, la búsqueda de campo falla.

En otras palabras, la JVM resolverá Bx en Ax . Es por esto que solo A clase necesita ser cargada.


§12.4 "Inicialización de clases e interfaces" de la especificación del lenguaje Java, Java SE 7 Edition especifica que:

La inicialización de una clase consiste en ejecutar sus inicializadores static y los inicializadores para campos estáticos (variables de clase) declarados en la clase.

[…]

Una referencia a un campo static ( §8.3.1.1 ) provoca la inicialización de solo la clase o interfaz que realmente lo declara, incluso aunque se pueda hacer referencia a él a través del nombre de una subclase, una subinterfaz o una clase que implementa una interfaz.

Entonces, aunque, al contrario de lo que se afirma en algunas de las respuestas anteriores, la clase B debe cargarse , para determinar que Bx se declara en A , la clase B no se inicializa (es decir, sus inicializadores static no se ejecutan) hasta que hacer algo mas especifico a B .


Class B extiende a A que tiene una public static variable x que está accediendo cuando llama a Bx

Si espera que Inside B. como sea, debe crear un Objeto de esa clase. Se ejecutan todos los bloques de código estático. o mueva ese bloque de código estático a la clase A :-)

Cuando JVM carga la clase, agrupa todos los bloques estáticos y los ejecuta en la secuencia en que están declarados.

EDITAR ( Source ): La respuesta corta es que las estadísticas no se heredan en Java. Más bien, los miembros estáticos declarados en una clase son (sujetos a restricciones de "acceso") directamente visibles en el espacio de nombres de las clases derivadas, a menos que estén "ocultos" por declaraciones en la clase derivada.

Entonces, si la Estática pertenece a la Clase solo, ¿por qué se filtra hacia la clase derivada? ¿No debería simplemente quedarse con la Clase en la que se definió?