Pertanyaan 1:
Mengapa kode berikut dikompilasi tanpa memiliki pernyataan pengembalian?
public int a()
{
while(true);
}
Ini dicakup oleh JLS§8.4.7 :
Jika suatu metode dinyatakan memiliki tipe kembali (§8.4.5), maka kesalahan waktu kompilasi terjadi jika tubuh metode dapat menyelesaikan secara normal (§14.1).
Dengan kata lain, metode dengan tipe pengembalian harus kembali hanya dengan menggunakan pernyataan pengembalian yang memberikan pengembalian nilai; metode ini tidak diperbolehkan untuk "menurunkan ujung tubuhnya". Lihat §14.17 untuk aturan yang tepat tentang pernyataan pengembalian dalam tubuh metode.
Dimungkinkan bagi suatu metode untuk memiliki tipe pengembalian dan tidak mengandung pernyataan pengembalian. Ini salah satu contohnya:
class DizzyDean {
int pitch() { throw new RuntimeException("90 mph?!"); }
}
Karena kompiler tahu bahwa loop tidak akan pernah berhenti ( true
selalu benar, tentu saja), ia tahu fungsi tidak dapat "kembali secara normal" (jatuhkan ujung tubuhnya), dan dengan demikian tidak apa-apa bahwa tidak ada return
.
Pertanyaan 2:
Di sisi lain, mengapa kode berikut dikompilasi,
public int a()
{
while(0 == 0);
}
meskipun berikut ini tidak.
public int a(int b)
{
while(b == b);
}
Dalam 0 == 0
kasus ini, kompiler tahu bahwa loop tidak akan pernah berhenti (itu 0 == 0
akan selalu benar). Tapi untuk itu tidak tahu b == b
.
Kenapa tidak?
Kompiler memahami ekspresi konstan (§15.28) . Mengutip §15.2 - Bentuk Ekspresi (karena anehnya kalimat ini tidak ada di §15.28) :
Beberapa ekspresi memiliki nilai yang dapat ditentukan pada waktu kompilasi. Ini adalah ekspresi konstan (§15.28).
Dalam b == b
contoh Anda , karena ada variabel yang terlibat, itu bukan ekspresi konstan dan tidak ditentukan untuk ditentukan pada waktu kompilasi. Kita bisa melihat bahwa itu selalu akan menjadi benar dalam kasus ini (meskipun jika b
adalah double
, sebagai QBrute menunjukkan , kita dapat dengan mudah tertipu oleh Double.NaN
, yang tidak ==
sendiri ), tapi JLS hanya menetapkan bahwa ekspresi konstan ditentukan pada waktu kompilasi , itu tidak memungkinkan kompiler untuk mencoba mengevaluasi ekspresi yang tidak konstan. bayou.io mengemukakan suatu alasan mengapa tidak: Jika Anda mulai mencoba menentukan ekspresi yang melibatkan variabel pada waktu kompilasi, di mana Anda berhenti? b == b
jelas (eh, untuk non-NaN
nilai), tetapi bagaimana dengan a + b == b + a
? Atau (a + b) * 2 == a * 2 + b * 2
? Menggambar garis pada konstanta masuk akal.
Jadi karena ia tidak "menentukan" ekspresi, kompiler tidak tahu bahwa loop tidak akan pernah berhenti, jadi ia berpikir metode tersebut dapat kembali secara normal - yang tidak diperbolehkan untuk dilakukan, karena itu diperlukan untuk digunakan return
. Jadi itu mengeluh tentang kurangnya a return
.