Les spécificités du cas Java pour cela (qui sont probablement très similaires au cas C #) sont liées à la façon dont le compilateur Java détermine si une méthode est capable de retourner.
Plus précisément, les règles sont qu'une méthode avec un type de retour ne doit pas pouvoir se terminer normalement et doit à la place toujours se terminer brusquement (brusquement ici indiquant via une instruction de retour ou une exception) selon JLS 8.4.7 .
Si une méthode est déclarée avoir un type de retour, une erreur de compilation se produit si le corps de la méthode peut se terminer normalement. En d'autres termes, une méthode avec un type de retour doit renvoyer uniquement en utilisant une instruction return qui fournit un retour de valeur; il n'est pas autorisé à «déposer le bout de son corps» .
Le compilateur cherche à voir si une terminaison normale est possible sur la base des règles définies dans JLS 14.21 Instructions inaccessibles car il définit également les règles pour la complétion normale.
Notamment, les règles pour les instructions inaccessibles font un cas spécial uniquement pour les boucles qui ont une true
expression constante définie :
Une instruction while peut se terminer normalement si au moins l'une des conditions suivantes est vraie:
L'instruction while est accessible et l'expression de condition n'est pas une expression constante (§15.28) avec la valeur true.
Il existe une instruction break accessible qui quitte l'instruction while.
Donc, si l' while
instruction peut se terminer normalement , une instruction return ci-dessous est nécessaire car le code est considéré comme accessible, et toute while
boucle sans instruction break ou constante accessibletrue
expression est considérée comme capable de se terminer normalement.
Ces règles signifient que votre while
instruction avec une expression vraie constante et sans a break
n'est jamais considérée comme terminée normalement , et donc tout code en dessous n'est jamais considéré comme accessible . La fin de la méthode est en dessous de la boucle, et comme tout ce qui se trouve en dessous de la boucle est inaccessible, la fin de la méthode l'est aussi, et donc la méthode ne peut pas se terminer normalement (ce que recherche le complicateur).
if
les instructions, en revanche, ne bénéficient pas de l'exemption spéciale concernant les expressions constantes accordées aux boucles.
Comparer:
public boolean testReturn()
{
final boolean condition = true;
if (condition) return true;
}
Avec:
public boolean testReturn()
{
final boolean condition = true;
while (condition)
{
return true;
}
}
La raison de la distinction est assez intéressante, et est due au désir de permettre des indicateurs de compilation conditionnelle qui ne provoquent pas d'erreurs de compilation (à partir du JLS):
On peut s'attendre à ce que l'instruction if soit gérée de la manière suivante:
Une instruction if-then peut se terminer normalement ssi au moins l'une des conditions suivantes est vraie:
L'instruction then est accessible ssi l'instruction if-then est accessible et l'expression de condition n'est pas une expression constante dont la valeur est fausse.
Une instruction if-then-else peut se terminer normalement si l'instruction then peut se terminer normalement ou si l'instruction else peut se terminer normalement.
L'instruction then est accessible ssi l'instruction if-then-else est accessible et l'expression de condition n'est pas une expression constante dont la valeur est fausse.
L'instruction else est accessible ssi l'instruction if-then-else est accessible et l'expression de condition n'est pas une expression constante dont la valeur est true.
Cette approche serait cohérente avec le traitement des autres structures de contrôle. Cependant, afin de permettre l'utilisation pratique de l'instruction if à des fins de "compilation conditionnelle", les règles réelles diffèrent.
À titre d'exemple, l'instruction suivante entraîne une erreur de compilation:
while (false) { x=3; }
parce que l'instruction x=3;
n'est pas accessible; mais le cas superficiellement similaire:
if (false) { x=3; }
n'entraîne pas d'erreur de compilation. Un compilateur d'optimisation peut réaliser que l'instruction x=3;
ne sera jamais exécutée et peut choisir d'omettre le code de cette instruction du fichier de classe généré, mais l'instructionx=3;
n'est pas considérée comme "inaccessible" au sens technique spécifié ici.
La justification de ce traitement différent est de permettre aux programmeurs de définir des «variables de drapeau» telles que:
static final boolean DEBUG = false;
puis écrivez du code tel que:
if (DEBUG) { x=3; }
L'idée est qu'il devrait être possible de changer la valeur de DEBUG de false à true ou de true à false, puis de compiler le code correctement sans aucune autre modification du texte du programme.
Pourquoi l'instruction de rupture conditionnelle entraîne-t-elle une erreur du compilateur?
Comme indiqué dans les règles d'accessibilité de boucle, une boucle while peut également se terminer normalement si elle contient une instruction break accessible. Étant donné que les règles de joignabilité d'une if
de déclaration alors l' article ne prend pas l'état du if
compte du tout, une telle condition if
déclaration est alors clause est toujours considérée comme atteignable.
Si le break
est accessible, le code après la boucle est à nouveau considéré comme accessible. Puisqu'il n'y a pas de code accessible qui entraîne une interruption brutale après la boucle, la méthode est alors considérée comme capable de se terminer normalement, et donc le compilateur la signale comme une erreur.