54 votes

Pourquoi le compilateur Java ne comprend-il pas que cette variable est toujours initialisée ?

class Foo{
    public static void main(String args[]){
        final int x=101;

        int y;
        if(x>100){
            y=-1;
        }
        System.out.println(y);
    }
}

Le compilateur Java comprend que la condition de l'instruction if est toujours vraie et donc que y sera toujours initialisé. Aucune erreur de compilation, comme prévu.

class Bar{
    public static void main(String args[]){
        final int x;
        x=101;

        int y;      
        if(x>100){
            y=-1;
        }
        System.out.println(y);
    }
}

Mais lorsque je sépare la déclaration et l'initialisation de x en deux lignes, le compilateur ne semble pas comprendre que la condition est toujours vraie et que y sera toujours initialisé.

final int x;
x=101;
byte b;
b=x;
System.out.println(b);

La même chose se produit ici et le compilateur donne une erreur de perte de précision.

final int x=101;
byte b;
b=x;
System.out.println(b);

Encore une fois, le compilateur peut comprendre que x est à l'intérieur de l'intervalle de b.

46voto

Patricia Shanahan Points 11270

Dans le cadre de l'objectif de portabilité, il existe un ensemble de règles très spécifiques concernant ce qu'un compilateur doit accepter et ce qu'il doit rejeter. Ces règles n'autorisent et n'exigent qu'une forme limitée d'analyse de flux lorsqu'il s'agit de déterminer si une variable est définitivement assignée lors de son utilisation.

Voir la spécification du langage Java Chapitre 16. Assignation définitive

La règle essentielle est celle qui figure dans 16.2.7. Déclarations if Le cas "si (e) S". La règle de l'affectation définitive s'étend à :

V est attribué après si (e) S si, et seulement si, V est attribué après S y V est attribué après e lorsqu'il est faux.

y est la valeur pertinente V . Il n'est pas assigné avant l'instruction if. Il est en effet assigné après S , y = {y=-1;} mais rien ne permet de l'affecter lorsque x>100 est faux.

Ainsi, y n'est pas définitivement affecté après l'instruction if.

Une analyse de flux plus complète déterminerait que la condition x>100 est toujours vraie, mais le compilateur est tenu par le JLS de rejeter le programme sur la base de ces règles spécifiques.

La variable finale est bonne. La règle est en fait : -

"Il s'agit d'une erreur de compilation si une variable finale est assignée à moins que elle est définitivement non assignée (§16) immédiatement avant l'exécution de la fonction l'affectation."

La déclaration le laisse définitivement non affecté, et même l'analyse limitée du flux peut déterminer que x est toujours définitivement non affecté lors de l'affectation.

26voto

assylias Points 102015

Il s'agit de la façon dont le compilateur détermine si une instruction sera exécutée ou non. Il est défini dans le fichier JLS #16 :

Chaque variable locale et chaque champ final vide doit avoir une valeur définitivement attribuée lors de tout accès à sa valeur.

Dans votre cas, le compilateur ne peut pas déterminer que y a été définitivement attribué et vous donne une erreur. En effet, il faudrait déterminer que la condition est toujours vraie, ce qui n'est possible que si la condition dans la balise if est un expression constante .

JLS #15.28 définit expressions constantes :

Une expression constante en temps de compilation est une expression dénotant une valeur de type primitif ou une chaîne de caractères qui ne se termine pas brusquement et qui est composée en utilisant uniquement les éléments suivants :

  • [...]
  • Noms simples (§6.5.6.1) qui font référence à des variables constantes (§4.12.4).

En JLS #4.12.4 définit constantes variables comme :

Une variable de type primitif ou de type String, qui est finale et initialisée avec une expression constante au moment de la compilation, est appelée une variable constante.

Dans votre cas, final int x = 101; est une variable constante mais final int x; x = 101; ne l'est pas.

11voto

Sajith Janaprasad Points 361

Qu'avez-vous fait pour la variable x dans le second code est appelé finale vierge variable. Si une variable finale n'est pas initialisée lors de sa déclaration, on parle alors de variable finale vide.

De nombreux développeurs Java pensent que la valeur d'une variable finale est connue au moment de la compilation. Ce n'est PAS toujours vrai. Il est dit que la valeur d'une variable finale vide N'EST PAS connue au moment de la compilation. Par conséquent, votre deuxième code vous donnera une erreur de compilation. Le compilateur peut voir que vous avez initialisé la variable finale. x mais compile ne connaît pas sa valeur. Donc le compilateur ne peut pas résoudre l'instruction if. Il pense donc que la variable y n'est pas initialisé.

Vous pouvez en savoir plus sur les variables finales de Java aquí .

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