59 votes

Pourquoi un compilateur Java ne génère-t-il pas une erreur d'instruction inaccessible pour une instruction inaccessible?

Si j'essaye de compiler

 for(;;)
{

}
System.out.println("End");
 

Le compilateur Java génère une erreur indiquant Unreachable statement . Mais si j'ajoute une autre déclaration " inaccessible " (selon moi) break et le fais:

 for(;;)
{
    if(false) break;
}
System.out.println("End");
 

Il compile. Pourquoi cela ne produit-il pas une erreur? Java essaie de dire que deux maux ne font un droit?

56voto

assylias Points 102015

Le comportement est défini dans le JLS description de l'inaccessible déclarations:

La déclaration est accessible iff l'instruction if-then est accessible.

Ainsi, le compilateur détermine que l'instruction (break;) est accessible, quelle que soit la condition dans l' if.

Et un peu plus loin, c'est moi qui souligne:

Une base for déclaration peut se terminer normalement le forum au moins une des conditions suivantes est remplie:

  • La déclaration est accessible, il est une condition de l'expression, et l'expression de condition n'est pas une expression constante (§15.28) avec la valeur true.
  • Il est joignable break déclaration qui sort de l'instruction for.

Donc la pour peut se terminer normalement parce que la déclaration contient un break. Comme vous l'avez remarqué, cela ne fonctionnerait pas si vous avez remplacé break avec return.


La raison en est expliqué vers la fin de la section. En substance, if a un traitement spécial pour permettre à des constructions telles que:

if(DEBUG) { ... }

où DÉBOGAGE peut être un moment de la compilation constante.

11voto

chrylis Points 22655

Comme expliqué dans ma réponse à une question similaire , la construction spécifique if(compile-time-false) est exemptée des règles d'inaccessibilité en tant que porte dérobée explicite. Dans ce cas, le compilateur traite votre break comme étant accessible à cause de cela.

7voto

DeveloperXY Points 12323

À partir de la JLS

Une instruction if-then peut se terminer normalement si au moins l'un des suivantes est remplie:

> L'instruction if-then est accessible et l'expression de condition n'est pas une expression constante dont la valeur est true.

> La déclaration peut se terminer normalement.

Donc, if(false) est autorisée.

Cette capacité à "conditionnellement de la compilation" a un impact significatif sur l', et de la relation, la compatibilité binaire. Si un ensemble de classes que l'utilisation d'une telle "drapeau" variable sont compilés et à la condition que le code est omis, il ne suffit pas tard distribuer une nouvelle version de la classe ou de l'interface qui contient la définition de l'indicateur. Un changement de la valeur d'un indicateur n'est donc pas compatible binaire avec pré-existantes des fichiers binaires . (Il y a d'autres raisons pour une telle incompatibilité, comme l'utilisation de constantes dans les cas les étiquettes dans les instructions de commutation;)

4voto

TAsk Points 7431

Fondamentalement, le code inaccessible est détecté en analysant le programme de manière statique sans exécuter le code. Alors que la condition sera vérifiée au moment de l' exécution . Ainsi, lorsque cette analyse est effectuée, elle ne tient pas compte de la situation mais vérifie simplement que break; est accessible ( accessible ) via if .

1voto

Sergey Fedorov Points 853

La raison de base de Java n'est pas détecter toutes inaccessible déclarations, c'est qu'il est généralement impossible de dire si le code est accessible ou pas. Cela découle du fait que le problème de l'arrêt est indécidable sur des machines de Turing.

Donc, il est clair que toutes inaccessible instructions ne peuvent pas être détectés, mais pourquoi ne pas essayer d'évaluer les conditions? Imaginez maintenant que la condition n'est pas juste false , mais quelque chose comme ~x == x. Par exemple, tous ces énoncés imprimer true pour chaque int x (source).

    System.out.println((x + x & 1) == 0);
    System.out.println((x + -x & 1) == 0);
    System.out.println((-x & 1) == (x & 1));
    System.out.println(((-x ^ x) & 1) == 0);
    System.out.println((x * 0x80 & 0x56) == 0);
    System.out.println((x << 1 ^ 0x1765) != 0);

Les déclarations peuvent être plutôt compliqué; il faut du temps pour les résoudre. Elle augmenterait de manière significative le temps de construction, et après tout, il ne détecte pas tous inaccessible consolidés. Compilateur a été conçu pour prendre quelques efforts, mais ne pas dépenser trop de temps pour ça.

La seule question demeure: où s'arrêter résoudre conditions? Les raisons qui ne semblent pas avoir de justification mathématique et sont basés sur l'utilisation de scénario. Justification de votre cas particulier est donné par JLS-14.21

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