88 votes

Impossible de faire référence à "X" avant que le constructeur du super-type n'ait été appelé, où x est une variable finale.

Considérons la déclaration de classe Java suivante :

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;
    }
}

Le code ne sera pas compilé, le compilateur se plaignant de la ligne que j'ai mise en évidence ci-dessus. Pourquoi cette erreur se produit-elle et quelle est la meilleure solution ?

115voto

Amr Bekhit Points 1059

La raison pour laquelle le code ne se compile pas initialement est la suivante defaultValue est un variable d'instance de la classe Test ce qui signifie que lorsqu'un objet de type Test est créée, une instance unique de defaultValue est également créé et rattaché à cet objet particulier. Pour cette raison, il n'est pas possible de référencer defaultValue dans le constructeur, car ni lui ni l'objet n'ont encore été créés.

La solution consiste à rendre la variable finale static :

public class Test {

    private static final int defaultValue = 10;
    private int var;

    public Test() {
        this(defaultValue);
    }

    public Test(int i) {
        var = i;
    }
}

En rendant la variable static il devient associé à la classe elle-même, plutôt qu'aux instances de cette classe, et il est partagé par toutes les instances de Test . Les variables statiques sont créées lorsque la JVM charge la classe pour la première fois. Comme la classe est déjà chargée lorsque vous l'utilisez pour créer une instance, la variable statique est prête à l'emploi et peut donc être utilisée dans la classe, y compris dans le constructeur.

Références :

9voto

Jigar Joshi Points 116533

C'est parce que le defaultValue est un membre de Test qui est en cours de construction (pas encore créée)

Si vous l'aviez static il a été chargé lors du chargement de votre classe par les classloaders

6voto

Sherif Eldeeb Points 91

Vous faites référence à une variable qui n'existe pas encore , s'il était statique il existerait avant même le constructeur lui-même .

Mais vous serez confronté à un autre problème, car defaultValue est devenue statique, de sorte que toutes les autres instances peuvent partager la même valeur, ce que vous n'aimeriez peut-être pas :

public class Test {

    private final int defaultValue = 10; //this will exist only after calling the constructor
    private final static int value2= 10; //this exists before the constructor has been called
    private int var;

    public Test() {
       // this(defaultValue);    // this method will not work as defaultValue doesn't exist yet
    this(value2); //will work
    //this(10); will work
    }

    public Test(int i) {
        var = i;
    }
}

4voto

Himanshu Mohta Points 546

Règle : Chaque constructeur doit exécuter le constructeur de la super-classe avant de s'exécuter lui-même.

La première ligne de chaque constructeur est donc super() ou peut-être this() et vous envoyez la valeur par défaut au constructeur de cette classe qui (valeur par défaut) n'existe pas encore, d'où l'erreur au moment de la compilation.

Vous pouvez rendre la valeur par défaut statique et comme la variable statique est créée lorsque la classe est chargée en mémoire, la valeur par défaut est disponible à la ligne this(defaultValue).

1voto

amicngh Points 4464

Tant que votre objet n'est pas construit, les valeurs par défaut des variables ne seront pas définies. Par conséquent, si vous voulez que leurs valeurs par défaut soient définies au moment de la construction, faites-les static ou de les définir explicitement auparavant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X