Erişilemeyen Kod (Unreachable Code)

Java programcıları zaman zaman garip bir derleyici hatası ile karşılaşırlar: Unreachable code Hiç merak ettiniz mi bu hata ne anlama geliyor? Java şartnamesi, derleyicilerin, bir Java kaynak kodundaki her bir cümlenin, en az bir akış yoluyla erişilebilir olduğunu kontrol etmesini şart koşmaktadır. Dolayısıyla erişilemeyen bir kod parçasına sahip bir Java kodu, derleme zamanı hatası verecektir.

Erişilemeyen kod konusunda farklı diller farklı yaklaşımlara sahiptirler. Örneğin C/C++’ta bu durum bir hata değildir, fakat bazı derleyiciler bu durumu bir uyarı ile belirterek, erişilemeyen kod parçasını derlememeyi seçiyorlar.

Java’da hangi durumlarda erişilemeyen kod olacağı Java şartnamesinde ayrıntılı olarak açıklanmıştır. Konunun teorisine girip sizlerin canını sıkmadan örnekler üzerinden kısaca açıklayayım.

Bu konuda yapılması gereken en temel şey akışın analizidir. Akış analizinde araştırılması gereken şey ise her cümleye en az bir erişimin olup olmadığıdır. (Cümle yani statement, malum, bir Java kodundaki çalıştırılabilen en temel kod birimidir ve daima bir “;” ile biter.)

Akış analizi derleme zamanında yapıldığına göre eldeki bilgiler de tamamen derleme zamanıyla sınırlıdır. Dolayısıyla, prensip olarak, değeri çalışma zamanında elde edilebilecek olan ifadeler, akış analizine dahil olmazlar. (Bu konuda benim diğer bir yazıma bakabilirsiniz.) Yani aşağıdaki gibi bir kod, “Unreachable code” hatası vermez:


int a = 8;
int k;
if(a > 11)
k = 7;

Peki hangi durumlarda “Unreachable code” hatası alırız?

İlki sonsuz döngülerdir: Aşağıdaki kod bu hatayı verir çünkü “while” döngüsü bir sonsuz döngüdür ve akış, 3. satıra hiçbir zaman gelmeyecektir.


while (true)
System.out.println("Selam");
int i = 5; // Unreachable code!

Bu kodu düzeltmenin yolu “while”dan sonra bir blok kullanıp, blokta “break”e yer vermektir:


while (true) {
System.out.println("Selam");
break;
}
int i = 5; // Unreachable code without break.

Ya da, benzer şekilde, aşağıdaki kod da bir “Unreachable code” hatası verir:


while (false)
System.out.println("Selam"); // Unreachable code!

Peki ya aşağıdaki kod? Yukarıdaki kod bu hatayı veriyorsa 2. satır için de aynı şey söz konusudur, değil mi?


if (false) {
System.out.println("Selam");
}

Değil! Çünkü “while” ifadesi bir döngüdür, “if” ifadesi ise bir seçim ya da karardır. “while” bloğu, ya bir “break” ile, gerekiyorsa bir şarta bağlı olarak, kırılmalı ya da döngünün devam edip etmeyeceğine karar veren boolean ifadede kullanılan değişkenlerden en az birisinin değeri değişmelidir ki “while” sonsuz döngüye girmesin. Ama “if”de 2. satırın çalışması bir şarta bağlı, bu yüzden de bir problem yok. Yukarıdaki gibi bir durumda 2. satıra “dead code” denir ve genelde editörler buna bir uyarı verirler ve derleyiciler de bu kodu silebilirler.

Bakın, şimdi de 2. satır, aynı hatayı veriyor, çünkü problem aynı:


while(false)
System.out.println("Selam"); // Unreachable code!
int i = 5;

Sonsuz döngüyü “while” yerine “do-while” ve “for” ile de kurabilirsiniz ve bu yapılar da aynı durumlarda “Unreachable code” hatasına sebep olurlar.

Benzer bir durum, “break” ve “continue” kullanımında da söz konusudur:


for (;;) {
System.out.println("Selam");
break;
System.out.println("Bir selam daha.");
}

Yukarıdaki kod parçasında “break” yerine “continue” gelse de durum değişmez, 4. satır erişilemeyen koddur. Ama “break”/”continue” ifadeleri bir şarta bağlı hale gelirse durum düzelir:


for (;;) {
System.out.println("Selam");
if (true)
break;
System.out.println("Bir selam daha.");
}

Bu durumda 5. satır “dead code” olur.

Bir diğer durum ise “return” cümlelerinden sonra gelen kodlardır. Özellikle de bir metotta birden fazla yerde “return” varsa, mesela “if-else” içinde, bazı satırların mümkün bütün “return”lerden sonraya düşmesi muhtemeldir.


public int f() {
if (false) {
System.out.println("In if");
return 8;
} else {
System.out.println("in Else");
return 0;
}
System.out.println("Son"); // Unreachable code!
}

Bir başka durum da fırlatılmayan bir sıradışı durumu yakalamaya çalıştığınızda olur:


try {

} catch (IOException e) { // Unreachable code. Try to catch Exception
// or RuntimeException and see what happens

}

Yukarıdaki koddaki problem “try” bolkunda bir “java.io.IOException” fırlatan kodun olmamasıdır. Yakalanan sıradışı durum nesnesinin tipinin “java.lang.Exception” ya da “lava.lang.RuntimeException” olması durumunda “Unreachable code” hatasının neden oluşmadığı da size ufak bir düşünme fırsatı olarak kalsın 🙂

Java derleyicilerinin erişilemeyen kodlara izin vermemesinin programcılara sıkıntı çıkardığı düşünülebilir, fakat ben bu gibi derleyici kontrollerinin aslında Java kültürüne katkıda bulunup, Java’cıların kodlarını, daha güvenli ve sağlam (robust) yazmaya teşvik ettiğini düşünüyorum.

Toplam görüntülenme sayısı: 3199