Question 1:
Pourquoi le code suivant se compile sans avoir de déclaration de retour?
public int a()
{
while(true);
}
Ceci est couvert par JLS§8.4.7 :
Si une méthode est déclarée avoir un type de retour (§8.4.5), alors une erreur de compilation se produit si le corps de la méthode peut se terminer normalement (§14.1).
En d'autres termes, une méthode avec un type de retour ne doit renvoyer qu'en utilisant une instruction return qui fournit un retour de valeur; la méthode n'est pas autorisée à «déposer l'extrémité de son corps». Voir §14.17 pour les règles précises sur les instructions de retour dans un corps de méthode.
Il est possible qu'une méthode ait un type de retour et ne contienne cependant aucune instruction de retour. Voici un exemple:
class DizzyDean {
int pitch() { throw new RuntimeException("90 mph?!"); }
}
Puisque le compilateur sait que la boucle ne se terminera jamais ( true
c'est toujours vrai, bien sûr), il sait que la fonction ne peut pas "retourner normalement" (déposer la fin de son corps), et donc il est normal qu'il n'y en ait pas return
.
Question 2:
D'un autre côté, pourquoi le code suivant se compile-t-il,
public int a()
{
while(0 == 0);
}
même si ce qui suit ne le fait pas.
public int a(int b)
{
while(b == b);
}
Dans ce 0 == 0
cas, le compilateur sait que la boucle ne se terminera jamais (ce 0 == 0
sera toujours vrai). Mais il ne le sait pas pour b == b
.
Pourquoi pas?
Le compilateur comprend les expressions constantes (§15.28) . Citant le §15.2 - Formes d'expressions (car étrangement cette phrase n'est pas dans le §15.28) :
Certaines expressions ont une valeur qui peut être déterminée au moment de la compilation. Ce sont des expressions constantes (§15.28).
Dans votre b == b
exemple, comme une variable est impliquée, ce n'est pas une expression constante et n'est pas spécifiée pour être déterminée au moment de la compilation. Nous pouvons voir que cela va toujours être vrai dans ce cas (bien que si b
c'était un double
, comme l'a souligné QBrute , nous pourrions facilement être dupés Double.NaN
, ce qui n'est pas ==
lui-même ), mais le JLS spécifie uniquement que les expressions constantes sont déterminées au moment de la compilation , il ne permet pas au compilateur d'essayer d'évaluer des expressions non constantes. bayou.io a soulevé un bon point pour pourquoi pas: si vous commencez à essayer de déterminer des expressions impliquant des variables au moment de la compilation, où vous arrêtez-vous? b == b
est évident (euh, pour lesNaN
valeurs), mais qu'en est-il a + b == b + a
? Ou (a + b) * 2 == a * 2 + b * 2
? Tracer la ligne aux constantes est logique.
Donc, comme il ne "détermine" pas l'expression, le compilateur ne sait pas que la boucle ne se terminera jamais, il pense donc que la méthode peut retourner normalement - ce qu'il n'est pas autorisé à faire, car il est nécessaire d'utiliser return
. Il se plaint donc de l'absence d'un return
.