Domanda 1:
Perché il seguente codice viene compilato senza avere un'istruzione return?
public int a()
{
while(true);
}
Questo è coperto da JLS§8.4.7 :
Se viene dichiarato che un metodo ha un tipo restituito (§8.4.5), si verifica un errore in fase di compilazione se il corpo del metodo può essere completato normalmente (§14.1).
In altre parole, un metodo con un tipo restituito deve restituire solo usando un'istruzione return che fornisce un valore restituito; al metodo non è consentito "abbandonare la fine del suo corpo". Vedere §14.17 per le regole precise sulle dichiarazioni di ritorno in un corpo del metodo.
È possibile che un metodo abbia un tipo di restituzione e tuttavia non contenga dichiarazioni di restituzione. Ecco un esempio:
class DizzyDean {
int pitch() { throw new RuntimeException("90 mph?!"); }
}
Dato che il compilatore sa che il ciclo non si chiuderà mai ( true
è sempre vero, ovviamente), sa che la funzione non può "tornare normalmente" (abbandonare la fine del suo corpo), e quindi va bene che non ci sia return
.
Domanda 2:
D'altra parte, perché viene compilato il seguente codice,
public int a()
{
while(0 == 0);
}
anche se non segue.
public int a(int b)
{
while(b == b);
}
Nel 0 == 0
caso, il compilatore sa che il ciclo non terminerà mai ( 0 == 0
sarà sempre vero). Ma non lo sa per b == b
.
Perchè no?
Il compilatore comprende espressioni costanti (§15.28) . Citando §15.2 - Forme di espressioni (perché stranamente questa frase non è in §15.28) :
Alcune espressioni hanno un valore che può essere determinato al momento della compilazione. Queste sono espressioni costanti (§15.28).
Nel tuo b == b
esempio, poiché è coinvolta una variabile, non è un'espressione costante e non è specificata per essere determinata al momento della compilazione. Possiamo vedere che sarà sempre vero in questo caso (anche se se b
fosse un double
, come ha sottolineato QBrute , potremmo facilmente essere ingannati Double.NaN
, che non==
è esso stesso ), ma JLS specifica solo che le espressioni costanti sono determinate al momento della compilazione , non consente al compilatore di provare a valutare espressioni non costanti. bayou.io ha sollevato un buon punto perché no: se inizi a cercare di determinare espressioni che coinvolgono variabili al momento della compilazione, dove ti fermi? b == b
è ovvio (er, per non-NaN
valori), ma che dire a + b == b + a
? Oppure (a + b) * 2 == a * 2 + b * 2
? Tracciare la linea alle costanti ha senso.
Quindi dal momento che non "determina" l'espressione, il compilatore non sa che il ciclo non si chiuderà mai, quindi pensa che il metodo possa tornare normalmente - cosa che non gli è permesso fare, perché è necessario usarlo return
. Quindi si lamenta della mancanza di a return
.