java constructor final supertype

java - No se puede hacer referencia a "X" antes de que se haya llamado al constructor de supertipo, donde x es una variable final



supertype (8)

Es porque el defaultValue es un miembro de la instancia de Test que está en construcción (aún no creado)

Si lo tenías static , se cargó cuando tu clase se carga por classloaders

Considere la siguiente declaración de clase Java:

public class Test { private final int defaultValue = 10; private int var; public Test() { this(defaultValue); // <-- Compiler error: cannot reference defaultValue before supertype constructor has been called. } public Test(int i) { var = i; } }

El código no se compilará, y el compilador se queja de la línea que he resaltado anteriormente. ¿Por qué ocurre este error y cuál es la mejor solución?


Hasta que no se haya construido su objeto, no se establecerán valores predeterminados para las variables, por lo tanto, si desea que sus valores predeterminados se establezcan en el momento de la construcción, hágalos static o static explícitamente antes.


Regla: Todo constructor debe ejecutar el constructor de la superclase antes de ejecutarse.

Entonces, la primera línea de cada constructor es super () o puede ser this () y se envía el valor predeterminado al constructor de esta clase, que (defaultValue) no existe, por lo tanto, existe un error de tiempo de compilación.

Puede hacer defaultValue como estático y dado que la variable estática se crea cuando la clase se carga en la memoria, por lo que defaultValue está disponible en la línea this (defaultValue).


La razón por la cual el código no se compilaría inicialmente es porque defaultValue es una variable de instancia de la clase Test , lo que significa que cuando se crea un objeto de tipo Test , también se crea y adjunta una instancia única de defaultValue a ese objeto en particular. Debido a esto, no es posible hacer referencia a defaultValue en el constructor, ya que ni él ni el objeto se han creado todavía.

La solución es hacer que la variable final sea static :

public class Test { private static final int defaultValue = 10; private int var; public Test() { this(defaultValue); } public Test(int i) { var = i; } }

Al hacer que la variable sea static , se asocia con la clase misma, en lugar de las instancias de esa clase, y se comparte entre todas las instancias de Test . Las variables estáticas se crean cuando la JVM primero carga la clase. Como la clase ya está cargada cuando la usa para crear una instancia, la variable estática está lista para usar y, por lo tanto, puede usarse en la clase, incluido el constructor.

Referencias


El constructor se llama en el momento de la creación del objeto, por lo que el compilador no reconoce ninguna referencia a la variable como el compilador no tiene conocimiento de la variable de instancia, ya que el objeto aún no se ha creado.


En realidad, esta no es la respuesta correcta, ya que durante la creación del objeto, las instrucciones de inicialización de los campos se ejecutan antes que el constructor. Puede depurar el proceso de creación del objeto y verlo por su cuenta. Yo también estoy confundido acerca de este problema ... por ejemplo, si cambias un poco y el primer constructor será:

public Test(int i) { this(i, 0); } public Test (int a, int k) { }

Esto funcionará ... entonces, cuando el primer constructor / nulo llama a otro, no funciona por una razón extraña, incluso si llamo explícitamente a super (); antes de.

La explicación más relevante sería que JVM carga declaraciones en la memoria, pero NINGÚN CONSTRUCTOR PODRÁ LLEGAR A CUALQUIER INSTANCIA VARIABLE / CAMPO antes de que se ejecute por completo.


está haciendo referencia a una variable que aún no existe , si era estática, entonces existirá incluso antes que el propio constructor

pero te enfrentarás a otro problema, ya que defaultValue se convirtió en estático, por lo que todas las demás instancias pueden compartir el mismo valor que puede que no te guste,

public class Test { private final int defaultValue = 10; //this will be exists only after calling the contractor private final static int vakue2= 10; //this is exists before the contractor has been called private int var; public Test() { // this(defaultValue); // this metod will not work as defaultValue doesn''t exists yet this(value2); //this will work //this(10); will work } public Test(int i) { var = i; } }


bajo este tema he estado siguiendo esto.

class Super{ int a=10; static int x=100; Super(){ System.out.println("Super()"); } Super(int i){ System.out.println("Super(int)"); } } class Sub extends Super{ int b=20; static int y=20; Sub(int i){ ***Super(b);*** System.out.println("Sub(int)"); } }

las variables de instancia de las clases super y sub, no podemos usar para referirnos. Porque las variables de instancia se inicializan después de ejecutarse el constructor. Y las variables no son definitivas y estáticas. Los valores pueden ser cambiados. Además de estas únicas variables de instancia, por lo tanto, creamos los objetos para inicializar estas variables. Por lo tanto, estas variables no pueden usarse para referirse. Pero si estas variables son finales y estáticas, estas se quedan solo en la plantilla. Además de estas variables tienen valores específicos y estos no se modifican. Por lo tanto, podemos llamar a constructores de superclase utilizando estas variables finales estáticas.