Spesifik kasus Java untuk ini (yang mungkin sangat mirip dengan kasus C #) berkaitan dengan bagaimana kompiler Java menentukan apakah suatu metode dapat kembali.
Secara khusus, aturannya adalah bahwa metode dengan tipe pengembalian tidak harus dapat diselesaikan secara normal dan sebaliknya harus selalu lengkap secara tiba-tiba (tiba-tiba di sini ditunjukkan melalui pernyataan pengembalian atau pengecualian) per JLS 8.4.7 .
Jika suatu metode dinyatakan memiliki tipe kembali, maka kesalahan waktu kompilasi terjadi jika tubuh metode dapat menyelesaikan secara normal. Dengan kata lain, metode dengan tipe pengembalian harus kembali hanya dengan menggunakan pernyataan pengembalian yang memberikan pengembalian nilai; itu tidak diizinkan untuk "menurunkan ujung tubuhnya" .
Kompilator terlihat untuk melihat apakah penghentian normal dimungkinkan berdasarkan aturan yang didefinisikan dalam JLS 14.21 Pernyataan Tidak Terjangkau karena juga mendefinisikan aturan untuk penyelesaian normal.
Khususnya, aturan untuk pernyataan yang tidak terjangkau membuat kasus khusus hanya untuk loop yang memiliki true
ekspresi konstan yang didefinisikan :
Pernyataan sementara dapat diselesaikan secara normal jika setidaknya salah satu dari yang berikut ini benar:
Jadi jika while
pernyataan tersebut dapat diselesaikan secara normal , maka pernyataan kembali di bawah ini diperlukan karena kode dianggap dapat dicapai, dan setiap while
loop tanpa pernyataan break yang dapat dicapai atau true
ekspresi konstan dianggap mampu menyelesaikan secara normal.
Aturan-aturan ini berarti bahwa Anda while
pernyataan dengan ekspresi yang benar konstan dan tanpa break
yang tidak pernah dianggap untuk menyelesaikan normal , dan sehingga setiap kode di bawah itu tidak pernah dianggap dicapai . Akhir dari metode berada di bawah loop, dan karena segala sesuatu di bawah loop tidak dapat dijangkau, demikian juga akhir dari metode, dan dengan demikian metode tersebut tidak mungkin dapat diselesaikan secara normal (yang dicari oleh pengumpul).
if
pernyataan, di sisi lain, tidak memiliki pengecualian khusus tentang ekspresi konstan yang diberikan untuk loop.
Membandingkan:
// I have a compiler error!
public boolean testReturn()
{
final boolean condition = true;
if (condition) return true;
}
Dengan:
// I compile just fine!
public boolean testReturn()
{
final boolean condition = true;
while (condition)
{
return true;
}
}
Alasan untuk pembedaan ini cukup menarik, dan karena keinginan untuk mengizinkan flag kompilasi bersyarat yang tidak menyebabkan kesalahan kompiler (dari JLS):
Seseorang mungkin mengharapkan pernyataan if ditangani dengan cara berikut:
Pernyataan jika-maka dapat menyelesaikan secara normal jika setidaknya salah satu dari berikut ini benar:
Pernyataan-kemudian dapat dicapai jika pernyataan if-maka dapat dicapai dan ekspresi kondisi bukan ekspresi konstan yang nilainya salah.
Pernyataan if-then-else dapat diselesaikan secara normal jika if-then-statement dapat diselesaikan secara normal atau statement-else dapat diselesaikan secara normal.
Pernyataan kemudian dapat dicapai jika pernyataan if-then-else dapat dicapai dan ekspresi kondisi bukanlah ekspresi konstan yang nilainya salah.
Pernyataan else dapat dicapai jika pernyataan if-then-else dapat dicapai dan ekspresi kondisi bukanlah ekspresi konstan yang nilainya benar.
Pendekatan ini akan konsisten dengan perawatan struktur kontrol lainnya. Namun, untuk memungkinkan pernyataan if digunakan dengan nyaman untuk tujuan "kompilasi bersyarat", aturan sebenarnya berbeda.
Sebagai contoh, pernyataan berikut ini menghasilkan kesalahan waktu kompilasi:
while (false) { x=3; }
karena pernyataan x=3;
itu tidak terjangkau; tetapi kasus serupa yang dangkal:
if (false) { x=3; }
tidak menghasilkan kesalahan waktu kompilasi. Kompilator pengoptimal mungkin menyadari bahwa pernyataan x=3;
itu tidak akan pernah dieksekusi dan dapat memilih untuk menghilangkan kode untuk pernyataan itu dari file kelas yang dihasilkan, tetapi pernyataan x=3;
itu tidak dianggap sebagai "tidak terjangkau" dalam pengertian teknis yang ditentukan di sini.
Alasan untuk perlakuan berbeda ini adalah untuk memungkinkan programmer untuk mendefinisikan "variabel flag" seperti:
static final boolean DEBUG = false;
lalu tulis kode seperti:
if (DEBUG) { x=3; }
Idenya adalah bahwa mungkin untuk mengubah nilai DEBUG dari false ke true atau dari true ke false dan kemudian mengkompilasi kode dengan benar tanpa ada perubahan lain pada teks program.
Mengapa pernyataan break bersyarat menghasilkan kesalahan kompilator?
Seperti dikutip dalam aturan reachability loop, loop sementara juga bisa selesai secara normal jika berisi pernyataan break yang dapat dicapai. Karena aturan untuk keterjangkauan suatu if
pernyataan maka klausa tidak mempertimbangkan kondisi itu if
sama sekali, maka klausa if
pernyataan bersyarat seperti itu selalu dianggap dapat dijangkau.
Jika break
terjangkau, maka kode setelah loop sekali lagi juga dianggap dapat dijangkau. Karena tidak ada kode yang dapat dijangkau yang menghasilkan penghentian mendadak setelah loop, metode ini kemudian dianggap dapat menyelesaikan secara normal, dan kompilator menandainya sebagai kesalahan.