variable metodo initialize java initialization

initialize - metodo init java



Inicializador de instancia y*esta*palabra clave (4)

Se permite que los inicializadores de instancia se refieran al objeto actual mediante la palabra clave this (§15.8.3), para usar la palabra clave super (§15.11.2, §15.12), y para usar cualquier tipo de variables en el alcance.

La inicialización consiste en la ejecución de cualquier inicializador de variable de clase e inicializadores estáticos de la clase Test, en orden textual.

Lo que sucede es que jvm asigna memoria para x en el marco de la pila. Cuando se utiliza este.x 0 se devuelve como la variable ya está asignada. Obtendrá 1 si la variable es estática a medida que se inicializa.

Tratando de compilar este pedazo de código

public class Main { public static void main(String args[]) { new Main(); } { System.out.println(x); } //Error here int x=1; }

produce un cannot reference a field before it is defined error. Pero si cambio la fila de inicializador a

{ System.out.println(this.x); }

Funciona como un encanto, imprimiendo el valor int predeterminado 0 .

Esto es un poco confuso para mí, ¿por qué this hace la diferencia? ¿No debería ser redundante en este caso? ¿Alguien me puede explicar qué sucede entre bastidores para dejar en claro cómo funciona realmente?

PD: Sé que al declarar x antes del inicializador también funcionaría.


Como en JSL ( §15.8.3 )

Cuando se usa como expresión primaria, la palabra clave denota un valor que es una referencia al objeto para el que se invocó el método de instancia ( §15.12 ), o al objeto que se está construyendo.

This palabra clave, al ser llamada, crea la instancia de la clase en segundo plano. Cuando llama a { System.out.println(this.x); } { System.out.println(this.x); } variable i se crea con Main clase Main .


Lo intentaré para explicar en la capa del compilador.

Digamos que tienes un método como:

int x; x = 1; System.out.println(x);

La compilación tendrá éxito y la ejecución también. Si cambias el Método en esto:

System.out.println(x); int x; x = 1;

Ni siquiera compilará lo mismo que con tu ejemplo dado.

El compilador copia el código del intializador { } en el ctor y también la inicialización x=1 .

Como dijo, funciona si establece x=1 antes del intializador { } .

public class MainC { public static void main(String args[]) { new MainC(); } int x=1; { System.out.println(x); } }

Vea el siguiente código de bytes de Java:

public MainC(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: aload_0 5: iconst_1 6: putfield #2 // Field x:I 9: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 12: aload_0 13: getfield #2 // Field x:I 16: invokevirtual #4 // Method java/io/PrintStream.println:(I)V 19: return LineNumberTable: line 1: 0 line 7: 4 line 9: 9 line 10: 19

El campo x se declara y obtiene el valor 1 antes de ser utilizado en la llamada System.out.println .

Entonces, ¿por qué no funciona si lo establece después de la { } por el mismo motivo por el que no puede usar el Código de mi segundo ejemplo? El campo se declara después del uso que no tiene sentido.

Entonces, ¿por qué funciona con this palabra clave?

Veamos algunos códigos:

public class Main { public static void main(String args[]) { new Main(); } { System.out.println(this.x); } //Error here int x=1; }

El correspondiente Bytecode de Java para el ctor:

public Main(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 7: aload_0 8: getfield #3 // Field x:I 11: invokevirtual #4 // Method java/io/PrintStream.println:(I)V 14: aload_0 15: iconst_1 16: putfield #3 // Field x:I 19: return LineNumberTable: line 1: 0 line 7: 4 line 9: 14

Entonces, ¿qué pasa aquí? Fácil de decir, this palabra clave carga la referencia del objeto principal en la pila. Después de eso, se puede acceder al campo x para que la llamada a System.out.println pueda ejecutarse con éxito.


JSL 8.6 debería explicar su error en tiempo de compilación:

Los inicializadores de instancias pueden referirse al objeto actual mediante la palabra clave this (§15.8.3) ...

El uso de variables de instancia cuyas declaraciones aparecen textualmente después del uso a veces está restringido, aunque estas variables de instancia estén dentro del alcance. Consulte §8.3.3 para conocer las reglas precisas que rigen la referencia a las variables de instancia.

En §8.3.3 , dice:

El uso de variables de instancia cuyas declaraciones aparecen textualmente después del uso a veces está restringido, aunque estas variables de instancia estén dentro del alcance. Específicamente, es un error en tiempo de compilación si se cumplen todas las siguientes condiciones:

  • La declaración de una variable de instancia en una clase o interfaz C aparece textualmente después de un uso de la variable de instancia;

  • El uso es un nombre simple en un inicializador de variable de instancia de C o un inicializador de instancia de C;

  • El uso no está en el lado izquierdo de una asignación;

  • C es la clase o interfaz más interna que incluye el uso.

Es por eso que escribir el nombre simple x te da el error.