Bölüm 6: Hata Ayıklama ve İstisnalar

Bölüm 6: Hata Ayıklama ve İstisnalar · Çalışma Soruları
Hata türleritry ve catchfinallytry-with-resourcesHiyerarşiKontrol edilenthrow ve throwsYayılımErrorÖzel istisnaİzleme listesi
Sercan KÜLCÜ

Çoktan Seçmeli · İstisna Kavramı

Soru 1: Hata Türü

Ortalama hesaplayan bir programda toplam yanlışlıkla 3 yerine 2'ye bölünüyor. Program derleniyor, çalışıyor ve bir sayı yazıyor; ama sayı yanlış. Bu hangi tür hatadır?

C: Kod dil kurallarına uyduğu için derlenir ve hiçbir işlem geçersiz olmadığı için istisna da oluşmaz. Mantık hataları ancak beklenen sonuçla karşılaştırarak, yani testlerle bulunur. İstisna mekanizması yalnızca ortadaki türü (çalışma zamanı hatalarını) ele alır.

Çıktı Sorusu · İstisna Kavramı

Soru 2: Yakalanmayan İstisna

Program ne yazdırır? "B" neden yazılmaz? İzleme listesindeki satır numaraları neyi gösterir?

public class Bolme {
  static int f(int[] d) {
    return 10 / (d.length - 2);
  }
  public static void main(String[] args) {
    System.out.println("A");
    System.out.println(f(new int[3]));
    System.out.println(f(new int[2]));
    System.out.println("B");
  }
}
Cevabı göster
A
10
Exception in thread "main"
  java.lang.ArithmeticException: / by zero
    at Bolme.f(Bolme.java:3)
    at Bolme.main(Bolme.java:8)

(İstisna satırı ekranda tek satırdır; burada bölündü.)

İlk çağrıda 10 / 1 = 10. İkincide payda 0: tam sayı bölmesi ArithmeticException fırlatır. f de main de yakalamadığı için program sonlanır; 9. satır hiç çalışmaz.

İlk at istisnanın doğduğu yer (f, 3. satır), alttaki onu çağıran satırdır (main, 8).

Adım Adım Çalıştırma · try ve catch

Soru 3: Hangi catch Çalışır?

dene sırasıyla "5", "x", "1", "-2" ve "0" ile çağrılıyor. Her çağrıda hangi blok çalışır, ne yazdırılır?

try { parseInt; new int[n]; d[n-1] = 100/(n-1) }catch (ArithmeticException e)catch (RuntimeException e)istisna yok: catch blokları atlanır

d = new int[5], d[4] = 100 / 4 = 25. İstisna olmadığı için hiçbir catch çalışmaz.

try { parseInt; new int[n]; d[n-1] = 100/(n-1) }catch (ArithmeticException e)catch (RuntimeException e)fırlatılan: NumberFormatException

NumberFormatException (3. satır) ilk catch ile eşleşmez; bir RuntimeException olduğu için ikincisi yakalar.

try { parseInt; new int[n]; d[n-1] = 100/(n-1) }catch (ArithmeticException e)catch (RuntimeException e)fırlatılan: ArithmeticException (/ by zero)

n − 1 = 0: bölmede ArithmeticException. İlk catch eşleşir; ikinci denenmez.

try { parseInt; new int[n]; d[n-1] = 100/(n-1) }catch (ArithmeticException e)catch (RuntimeException e)fırlatılan: NegativeArraySizeException

Negatif boyutla dizi oluşturulamaz: NegativeArraySizeException, bir RuntimeException.

try { parseInt; new int[n]; d[n-1] = 100/(n-1) }catch (ArithmeticException e)catch (RuntimeException e)fırlatılan: ArrayIndexOutOfBoundsException

İndis (−1) ve sağ taraf (−100) hesaplanır; atamada indis denetlenince ArrayIndexOutOfBoundsException.

static void dene(String s) {
  try {
    int n = Integer.parseInt(s);
    int[] d = new int[n];
    d[n - 1] = 100 / (n - 1);
    System.out.println("tamam " + d[n - 1]);
  } catch (ArithmeticException e) {
    System.out.println("A");
  } catch (RuntimeException e) {
    System.out.println("R " + e.getClass().getSimpleName());
  }
}

Çoktan Seçmeli · try ve catch

Soru 4: catch Sırası

Bu kod için hangisi doğrudur?

try {
  int s = 10 / 0;
} catch (Exception e) {
  System.out.println("Genel");
} catch (ArithmeticException e) {
  System.out.println("Aritmetik");
}

A: catch blokları yukarıdan aşağıya denenir; Exception bloğu her ArithmeticException'ı zaten yakalar, ikinci blok asla çalışamaz. Derleyici erişilemeyen catch'e izin vermez. Kural: alt sınıf önce, üst sınıf sonra.

Adım Adım Çalıştırma · finally

Soru 5: finally ve return

Program ne yazdırır? finally, return'den önce mi sonra mı çalışır?

trycatch (IllegalStateException e)finallybekleyen dönüş—

f(5): try başlar, "T5 " yazılır.

trycatch (IllegalStateException e)finallybekleyen dönüş2

return 10 / x: dönüş değeri 2 hesaplanır ve bekletilir; metot henüz bitmez.

trycatch (IllegalStateException e)finallybekleyen dönüş2

Metottan çıkmadan önce finally çalışır: "F ".

trycatch (IllegalStateException e)finallybekleyen dönüş—

Bekleyen 2 döner; println yazar ve satırı bitirir.

trycatch (IllegalStateException e)finallybekleyen dönüş—

f(0): "T0 ".

trycatch (IllegalStateException e)finallybekleyen dönüş—

throw: try'ın kalanı (return 10 / x) atlanır; 0'a bölme hiç denenmez.

trycatch (IllegalStateException e)finallybekleyen dönüş-1

Eşleşen catch "C " yazar; return -1 değeri bekletir.

trycatch (IllegalStateException e)finallybekleyen dönüş-1

Yine finally: "F ".

trycatch (IllegalStateException e)finallybekleyen dönüş—

−1 döner. finally her iki yolda da, dönüşten hemen önce çalıştı.

static int f(int x) {
  try {
    System.out.print("T" + x + " ");
    if (x == 0) {
      throw new IllegalStateException();
    }
    return 10 / x;
  } catch (IllegalStateException e) {
    System.out.print("C ");
    return -1;
  } finally {
    System.out.print("F ");
  }
}
// main içinde
System.out.println(f(5));
System.out.println(f(0));

Çoktan Seçmeli · finally

Soru 6: finally Değişkeni Değiştirirse

Program ne yazdırır?

static int g() {
  int s = 1;
  try {
    s = 2;
    return s;
  } finally {
    s = 3;
    System.out.print(s + " ");
  }
}
// main içinde
System.out.println(g());

B: return s; çalıştığında dönüş değeri (2) hesaplanıp saklanır; sonra finally çalışır. finally s'yi 3 yapar ve "3 " yazar, ama saklanmış dönüş değeri değişmez: main 2 yazar. finally içinde ayrıca return olsaydı o değer dönerdi (önerilmez).

Çıktı Sorusu · finally

Soru 7: İki Kaynaklı try-with-resources

Program ne yazdırır?

class K implements AutoCloseable {
  String ad;
  K(String ad) {
    this.ad = ad;
    System.out.println(ad + " açıldı");
  }
  public void close() {
    System.out.println(ad + " kapandı");
  }
}
// main içinde
try (K a = new K("A"); K b = new K("B")) {
  System.out.println("iş");
  throw new RuntimeException("hata");
} catch (RuntimeException e) {
  System.out.println("catch " + e.getMessage());
} finally {
  System.out.println("finally");
}
Cevabı göster
A açıldı
B açıldı
iş
B kapandı
A kapandı
catch hata
finally

Kaynaklar yazıldıkları sırayla açılır, ters sırayla kapanır: son açılan önce kapanır.

Kapatma, istisna olsa bile ve catch'ten önce yapılır; ardından catch, en son finally çalışır.

Çıktı Sorusu · finally

Soru 8: İç İçe try

Program ne yazdırır?

try {
  try {
    Object o = "12";
    Integer i = (Integer) o;
    System.out.println("iç try sonu");
  } catch (NumberFormatException e) {
    System.out.println("iç catch");
  } finally {
    System.out.println("iç finally");
  }
  System.out.println("dış try sonu");
} catch (ClassCastException e) {
  System.out.println("dış catch");
} finally {
  System.out.println("dış finally");
}
System.out.println("son");
Cevabı göster
iç finally
dış catch
dış finally
son

o bir String nesnesidir; Integer'a dönüşüm ClassCastException fırlatır ("12" sayıya benzese de dönüşüm yapılmaz).

İç catch bu tipi yakalamaz; istisna dışa ilerlerken iç finally çalışır. Dış try'ın kalanı ("dış try sonu") atlanır, dış catch yakalar, dış finally çalışır ve program devam eder.

Çoktan Seçmeli · İstisna Hiyerarşisi

Soru 9: Hangi catch Yakalar?

new FileReader("yok.txt") bir FileNotFoundException fırlatıyor. Aşağıdaki catch tiplerinden hangisi onu yakalar?

D: Bir catch, yazılan tipi ve tüm alt sınıflarını yakalar. FileNotFoundException → IOException → Exception → Throwable zincirindedir. RuntimeException ve SQLException ayrı dallardır; Error Exception ailesinden değildir.

Çoktan Seçmeli · İstisna Türleri

Soru 10: Kontrol Edilen İstisnalar

Hangi gruptaki istisnaların hepsi kontrol edilen (checked) istisnadır?

A: Kontrol edilen istisnalar Exception'dan türeyip RuntimeException'dan türemeyenlerdir; derleyici "yakala ya da bildir" kuralını uygular. NullPointerException, NumberFormatException ve ClassCastException RuntimeException alt sınıflarıdır.

Hata Bulma · İstisna Türleri

Soru 11: Derlenmeyen Okuma Metodu

Derleyici bu metot için hangi hataları verir? İki farklı düzeltme yazın.

static String ilkSatir(String yol) {
  BufferedReader r =
      new BufferedReader(new FileReader(yol));
  return r.readLine();
}
Cevabı göster
error: unreported exception
  FileNotFoundException; must be caught
  or declared to be thrown
error: unreported exception IOException;
  must be caught or declared to be thrown

FileReader yapıcısı ve readLine() kontrol edilen istisna fırlatır. 1) Bildir (çağıran ele alır); dosya da kapanır:

static String ilkSatir(String yol)
    throws IOException {
  try (BufferedReader r =
      new BufferedReader(new FileReader(yol))) {
    return r.readLine();
  }
}

2) Ele al: aynı try-with-resources'a catch (IOException e) { return null; } eklenir ve throws kaldırılır. IOException, FileNotFoundException'ı da kapsar.

Adım Adım Çalıştırma · İstisna Fırlatma

Soru 12: İstisnanın Yayılımı

İstisna hangi metotta doğar, hangi satırlar atlanır? Program ne yazdırır?

mainb(1)c(1)

main → b(1) → c(1): üç çerçeve.

mainb(1)c(1)

1 > 2 yanlış; c normal biter, çerçevesi kaldırılır.

mainb(1)c(3)

b ikinci kez c'yi çağırır: c(3).

mainb(1)c(3)IllegalArgument…

3 > 2: istisna fırlatılır. c'de try yok: c o anda sona erer, "c bitti" yazılmaz.

mainb(1)IllegalArgument…

b'de catch yok ama finally var: çalışır, sonra istisna yoluna devam eder. "b bitti" atlanır.

mainIllegalArgument…

main'deki catch eşleşir. "main devam" atlanmıştır.

main

catch'ten sonra program normal akışına döner.

static void c(int x) {
  System.out.println("c " + x);
  if (x > 2) throw new IllegalArgumentException("x=" + x);
  System.out.println("c bitti");
}
static void b(int x) {
  try {
    c(x);
    c(x + 2);
    System.out.println("b bitti");
  } finally {
    System.out.println("b finally");
  }
}
// main içinde
try {
  b(1);
  System.out.println("main devam");
} catch (IllegalArgumentException e) {
  System.out.println("main: " + e.getMessage());
}
System.out.println("son");

Çoktan Seçmeli · İstisna Fırlatma

Soru 13: throw ve Bildirim

Bu metot için hangisi doğrudur?

static void f(int x) {
  if (x < 0) {
    throw new Exception("negatif");
  }
}

C: Exception (RuntimeException olmayan) kontrol edilen bir istisnadır: unreported exception Exception; must be caught or declared to be thrown. Çözüm: imzaya throws Exception eklemek ya da IllegalArgumentException gibi kontrol edilmeyen bir tip fırlatmak. throw gövdenin her yerinde kullanılabilir (D).

Çıktı Sorusu · Çalışma Zamanı İstisnaları

Soru 14: Satır Satır İstisnalar

Her satır tek başına çalıştırılıyor. Hangi istisna fırlatılır?

1  Object o = "5"; Integer i = (Integer) o;
2  char c = "abc".charAt(3);
3  int n = Integer.parseInt(" 7");
4  int m = Math.addExact(Integer.MAX_VALUE, 1);
5  int g = new ArrayList<Integer>().get(0);
6  int[] d = null; d[0] = 1;
7  int[] e = new int[-1];
Cevabı göster
Satırİstisna
1ClassCastException: nesne bir String
2StringIndexOutOfBoundsException: indisler 0 … 2
3NumberFormatException: baştaki boşluk
4ArithmeticException: integer overflow
5IndexOutOfBoundsException: boyut 0
6NullPointerException
7NegativeArraySizeException

Hepsi RuntimeException alt sınıfıdır: derleyici hiçbirini zorunlu tutmaz. Sıradan + taşmada istisna fırlatmaz; addExact fırlatır.

Çoktan Seçmeli · Çalışma Zamanı İstisnaları

Soru 15: İstisnasız Satır

Aşağıdaki ifadelerden hangisi çalışırken istisna fırlatmaz?

D: Kayan noktalı bölme IEEE 754 kurallarına uyar: 10.0 / 0 Infinity üretir, istisna yoktur. Tam sayı bölmesi ve kalan 0 ile ArithmeticException: / by zero; toIntExact int aralığına sığmayan değerde integer overflow fırlatır.

Çoktan Seçmeli · Kontrol Edilen Sınıflar

Soru 16: Derleyicinin İstediği

main içinde, try-catch ve throws olmadan yazılınca hangisi derlenmez?

B: Thread.sleep kontrol edilen InterruptedException fırlatabileceğini bildirir: unreported exception InterruptedException. Diğerleri en fazla kontrol edilmeyen istisna fırlatır (NumberFormatException, IllegalArgumentException, NullPointerException); derleyici bunları denetlemez.

Çoktan Seçmeli · Error Sınıfları

Soru 17: Sonsuz Özyineleme

Program çalıştırılınca ne olur?

static int f(int n) {
  return f(n + 1);
}
public static void main(String[] args) {
  try {
    f(0);
  } catch (Exception e) {
    System.out.println("yakalandı");
  }
  System.out.println("son");
}

C: Her çağrı yığına yeni bir çerçeve ekler; yığın dolunca JVM StackOverflowError fırlatır. Bu bir Error'dur, Exception ailesinden değildir: catch (Exception e) yakalamaz, program izleme listesiyle sonlanır. Derleyici sonsuz özyinelemeyi denetlemez.

Kod Yazma · Özel İstisnalar

Soru 18: Özel İstisna Sınıfı

Kontrol edilen bir GecersizNotHatasi sınıfı ve int notGir(int not) metodunu yazın: not 0–100 dışındaysa istisna "Not 0-100 arası olmalı: …" mesajıyla fırlatılsın, geçerliyse not dönsün. main içindeki döngü ne yazdırır?

for (int g : new int[]{85, 120, 40}) {
  try {
    System.out.println("Kaydedildi: "
        + notGir(g));
  } catch (GecersizNotHatasi e) {
    System.out.println("Hata: "
        + e.getMessage());
  }
}
Cevabı göster
class GecersizNotHatasi extends Exception {
  GecersizNotHatasi(String m) { super(m); }
}
static int notGir(int not)
    throws GecersizNotHatasi {
  if (not < 0 || not > 100) {
    throw new GecersizNotHatasi(
        "Not 0-100 arası olmalı: " + not);
  }
  return not;
}
Kaydedildi: 85
Hata: Not 0-100 arası olmalı: 120
Kaydedildi: 40

Kontrol edilen tip: throws zorunlu. try döngünün içinde: 120 hatası 40'ı engellemez.

Kod Okuma · İzleme Listesi

Soru 19: İzleme Listesini Okumak

Program ne yazdırır? İzleme listesine göre istisna hangi satırda doğar, null değeri nereden gelir, "bitti" neden yazılmaz?

 1 public class Okul {
 2   public static void main(String[] args) {
 3     int[] a = {70, 80};
 4     int[] b = null;
 5     rapor("A", a);
 6     rapor("B", b);
 7     System.out.println("bitti");
 8   }
 9   static void rapor(String ad, int[] d) {
10     System.out.println(ad + ": " + ortalama(d));
11   }
12   static double ortalama(int[] notlar) {
13     int t = 0;
14     for (int n : notlar) {
15       t += n;
16     }
17     return (double) t / notlar.length;
18   }
19 }
Cevabı göster
A: 75.0
Exception in thread "main"
  java.lang.NullPointerException
    at Okul.ortalama(Okul.java:14)
    at Okul.rapor(Okul.java:10)
    at Okul.main(Okul.java:6)
  • İlk at satırı doğduğu yeri gösterir: ortalama, 14. satır. for-each null bir dizinin uzunluğunu okumaya çalışır.
  • Aşağı doğru okununca zincir: main (6) → rapor (10) → ortalama (14). null, 4. satırda b'ye atanıp 6. satırda gönderilmiştir: düzeltilecek yer çoğu zaman istisnanın doğduğu yer değil, değeri üreten yerdir.
  • Kimse yakalamadığı için program sonlandı; 7. satır çalışmadı.

Java 14 ve sonrası mesaja hangi değerin null olduğunu da ekler ("Cannot read the array length …").

Son

Bölüm 6: Hata Ayıklama ve İstisnalar: Çalışma Soruları
Konu anlatımı: Hata ayıklama ve istisnalar sunumu · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.