2

Supposons que j'ai la pièce de code suivantePourquoi les champs de reconnaissance du compilateur Java n'ont-ils pas été initialisés?

int myVar; 
final boolean condition = <someCondition>; 
if (condition) { 
    myVar = 1; 
} 
if (condition) { 
    System.out.println("myVar = " + myVar); 
} 

Quand je compilé, je suis l'attendais myVar might not have been initialized erreur. Est-ce un bug dans le compilateur? Il est facile de voir que "myVar" a été défini quand condition est vrai, et il est seulement référencé lorsque condition est vrai. (condition est également jamais réinitialisé)

P.S: Pour ces commentaires sur moi ayant besoin d'init it à 0, oui je suis conscient de cela. Mais le point est, je voulais « myVar » être finale

+1

@imk Il est assez évident que le OP sait déjà que, depuis le point de l'ensemble de la question concerne * pourquoi * le compilateur est nécessitant l'initialisation. – azurefrog

+4

Le compilateur Java ne fait tout simplement pas une analyse suffisamment approfondie pour conclure qu'une valeur est toujours affectée à la variable 'myVar' avant d'être utilisée. En général, il ne tente pas de corréler les conditions dans différentes instructions conditionnelles. –

+0

Je ne pense pas que le compilateur est conscient que la condition ne changera pas. Prenons, par exemple, ceci étant exécuté sur une CPU qui est interrompue. La condition peut changer quand elle revient à l'exécution de ceci. Peu importe, je n'ai pas regardé la déclaration de condition. Ce que @JohnBollinger semble suffisant. – bhow

Répondre

4

L'exigence d'initialisation est une partie formelle de Java, tel que décrit dans la JLS (c.-à-valeur réglée au plus une fois.):

Pour chaque accès d'une variable locale ou d'un champ final vierge x, x doit être définitivement assigné avant l'accès ou une erreur de compilation survient.

(JLS 8, chapter 16, souligné dans l'original)

Le JLS poursuit en disant

L'analyse tient compte de la structure des états et expressions; il fournit également un traitement spécial de l'expression des opérateurs !, &&, ||, et ? :, et des expressions de constante booléenne .

A l'exception du traitement spécial des opérateurs booléens conditionnelles &&, || et ? : et d'expressions constantes valeur booléennes, les valeurs des expressions ne sont pas prises en compte dans l'analyse des flux.

(italique ajouté)

Notez bien que condition être final ne fait pas une « expression constante » comme la spécification définit ce terme. Le cahier des charges se poursuit pour donner the specific rule for if statements:

V est [un] attribué après if (e) S ssi V est [un] attribué après S et V est [un] attribué après e lorsque [e est évaluée à] false.

Dans votre code particulier, alors:

int myVar; 

myVar est certainement un attribué ici.

final boolean condition = <someCondition>; 
if (condition) { 
    myVar = 1; 
} 

myVar est "attribué après S" parce que S, le corps de l'instruction if, effectue une mission sans conditions. myVar est pas affecté après l'évaluation de la condition, cependant, si la condition évalue à true ou false. Par conséquent, myVar n'est pas définitivement affecté à ce stade de la méthode.

if (condition) { 

Et rien n'a changé à ce point: myVar est toujours pas vraiment affecté dans la mesure où les règles JLS sont concernées, de sorte que sa valeur ne doit pas être lu. Le compilateur est donc obligé de signaler une erreur dans la déclaration suivante:

System.out.println("myVar = " + myVar); 
}