Bölüm 9: Metotlar

Bilgisayar ve Programlamaya Giriş
TanımParametreDönüşKapsamÖrnekler
Sercan KÜLCÜ · Giresun Üniversitesi

Giriş

Öğrenme Çıktıları

Tanımlama

Metot tanımlaması ve çağrısını yazmak.

Veri akışı

Parametre ve dönüş değerini kullanmak.

Kapsam

Yerel değişkenlerin yaşam alanını açıklamak.

Tasarım

Kısa, odaklı ve test edilebilir metotlar kurmak.

Temeller

Fonksiyon Nedir?

  • Java’da fonksiyonlar sınıf içinde metot olarak tanımlanır.
  • Belirli bir görevi adlandırır ve tekrar kullanılabilir bir birim oluşturur.
  • Girdi parametrelerle alınır; sonuç dönüş değeriyle verilir.
  • Örnek: Math.sqrt(16) → 4.0; nasıl hesapladığını bilmemiz gerekmez.
girdi53topla(a, b)çıktı8parametrelergövde (ayrıntı gizli)dönüş değeri

Temeller

Metot Çalışması

mainint x = 5;int t = topla(x, 3);System.out.println(t);toplastatic int topla(int a, int b) { return a + b;}① çağrı: a = 5, b = 3② return 8 → çağrı yerine 8③ main kaldığı yerden devam eder: t = 8, sonra println
Argümanları değerlendir
Parametrelere kopyala
Gövdeyi çalıştır
Değer döndür
Çağrıya devam et
  • Her çağrı kendi parametre ve yerel değişkenleriyle çalışır.

Temeller

Metot Tanımı ve Çağrısı

static int topla(int a, int b) {
    int sonuc = a + b;
    return sonuc;
}

int toplam = topla(5, 3);
System.out.println(toplam);
int toplam = topla(5, 3);topla(5,3)gerçek argümanlardeğer kopyalanır53abbiçimsel parametrelersonuc = 5 + 3 = 8returntoplam = 8
  • int dönüş tipi; a ve b biçimsel parametrelerdir.
  • 5 ve 3 gerçek argümanlardır.
  • Dönen değer değişkene atanabilir veya başka ifadede kullanılabilir.

Temeller · Kodu adım adım çalıştır

Kod İzleme: topla(5, 3)

main()toplam = topla(5, 3)

main çalışıyor. Sağ taraf önce hesaplanmalı: topla(5, 3) çağrılır.

main()toplam = topla(5, 3)toplaa5b3

Yeni çerçeve açılır: argümanlar 5 ve 3, parametreler a ve b’ye kopyalanır.

main()toplam = topla(5, 3)toplaa5b3sonuc8

Yerel değişken sonuc = 5 + 3 = 8; yalnızca topla’nın çerçevesinde yaşar.

main()toplam = topla(5, 3)toplaa5b3sonuc8kapandıreturn 8

return sonuc: 8 çağırana gönderilir, topla’nın çerçevesi kapanır.

main()toplam8toplam = 8

Dönen değer çağrının yerine geçer: toplam = 8. a, b, sonuc artık yok.

main()toplam8

8 yazılır.

static int topla(int a, int b) {
    int sonuc = a + b;
    return sonuc;
}

// main içinde:
int toplam = topla(5, 3);
System.out.println(toplam);

Temeller · Kodu adım adım çalıştır

Çağrı Yığını: metot metodu çağırınca

main()o = ortalama(9, 7)

main, ortalama(9, 7)’yi çağırır. Yığında şimdilik tek çerçeve var.

main()o = ortalama(9, 7)ortalamax9y7

ortalama çerçevesi main’in üstüne konur: x = 9, y = 7.

main()o = ortalama(9, 7)ortalamax9y7t = topla(x, y)

ortalama da bir metot çağırıyor: topla(x, y) → x ve y’nin değerleri (9, 7) gönderilir.

main()o = ortalama(9, 7)ortalamax9y7t = topla(x, y)toplaa9b7

topla en üste: 3 çerçeve. Yalnız en üstteki çalışır.

main()o = ortalama(9, 7)ortalamax9y7t = topla(x, y)toplaa9b7kapandıreturn 16

return 16: topla’nın çerçevesi kapanır (son giren ilk çıkar).

main()o = ortalama(9, 7)ortalamax9y7t16t = 16

16 çağrı yerine geçer: t = 16. ortalama kaldığı yerden sürer.

main()o = ortalama(9, 7)ortalamax9y7t16kapandıreturn 8

return t / 2 → 16 / 2 = 8 (tam sayı bölmesi). ortalama’nın çerçevesi kapanır.

main()o8o = 8

main’e dönüldü: o = 8. x, y, t, a, b hiçbiri artık yok.

main()o8

8 yazılır. Çerçeveler yığın (stack) gibi: son açılan ilk kapanır.

static int topla(int a, int b) {
    return a + b;
}
static int ortalama(int x, int y) {
    int t = topla(x, y);
    return t / 2;
}
int o = ortalama(9, 7);  // main içinde
System.out.println(o);

Temeller

Metot Tanımlamasının Parçaları

public static int topla(int a, int b) {erişimkim çağırabilir?niteleyicinesne gerekmezdönüş tipine döner?adgörevin adıparametre listesihangi girdiler?int sonuc = a + b;return sonuc;}gövde: çağrılınca çalışan deyimlerreturn ile dönüş tipinde değer veririmza = ad + parametretipleri: topla(int, int)

Örneklerde metotlar main ile aynı sınıfta ve static yazılır.

Temeller

main Metodunun İmzası ve static

public static void main(String[] args)
public: JVM dışarıdan çağırabilsin
static: nesne üretmeden çağrılsın
void: değer döndürmez
main: JVM’nin aradığı ad
String[] args: komut satırı argümanları
void selamla() { }
public static void main(String[] args) {
    selamla();   // hata
}
error: non-static method selamla() cannot be referenced from a static context
  • static metot sınıfa aittir; nesne olmadan çağrılır. static olmayan metot bir nesneye aittir.
  • static metot, static olmayan metoda ya da alana doğrudan erişemez; çözüm o metodu da static yapmaktır.
  • JVM programı başlatırken henüz hiç nesne yoktur; bu yüzden main static olmalıdır.

Dönüş

void Metotlar

static void cizgiCiz(int n) {
    for (int i = 0; i < n; i++)
        System.out.print("-");
    System.out.println();
}
// main içinde:
cizgiCiz(5);           // -----
int x = cizgiCiz(5);   // HATA: void değer vermez
  • void: metot çağrıya bir değer döndürmez; iş yan etkidir (ekrana yazmak gibi).
  • Bu yüzden void çağrı bir atamanın ya da ifadenin parçası olamaz.
  • return; (değersiz) void metottan erken çıkmak için kullanılabilir.
topla(5, 3)return8int t = 8;değer çağrı yerine gelircizgiCiz(5)-----ekrana yazar (yan etki), değer döndürmezint x = cizgiCiz(5); ✗

Dönüş

Erken Dönüş

static void yazdirPozitif(int sayi) {
    if (sayi <= 0) return;
    System.out.println(sayi);
}
  • Özel durumu başta ele almak iç içeliği azaltabilir.
  • Değer döndüren metotta her yol uyumlu bir değer döndürmelidir.
yazdirPozitif(sayi)sayi <= 0 ?evetreturn;erken çıkışhayırprintln(sayi);metot biteryazdirPozitif(-3) → çıktı yokyazdirPozitif(7) → 7

Dönüş · Kodu adım adım çalıştır

Kod İzleme: yazdirPozitif(-3) ve (7)

main()yazdirPozitif(-3)

İlk çağrı: argüman −3.

main()yazdirPozitif(-3)yazdirPozitifsayi-3

Çerçeve açılır: sayi = −3.

main()yazdirPozitif(-3)yazdirPozitifsayi-3kapandıreturn (değersiz)

−3 <= 0 → true → return; Metot hemen biter; println’e hiç gelinmez.

main()yazdirPozitif(7)

main sonraki satırdan sürer: ikinci çağrı, argüman 7.

main()yazdirPozitif(7)yazdirPozitifsayi7

Yepyeni bir çerçeve: sayi = 7 (önceki çağrının sayi’sı çoktan yok oldu).

main()yazdirPozitif(7)yazdirPozitifsayi7

7 <= 0 → false → erken dönüş yok, devam.

main()yazdirPozitif(7)yazdirPozitifsayi7

7 yazılır.

main()yazdirPozitif(7)yazdirPozitifsayi7kapandı

Kapanış süslü parantezine gelindi: void metot burada kendiliğinden döner.

static void yazdirPozitif(int sayi) {
    if (sayi <= 0) return;
    System.out.println(sayi);
}
// main içinde:
yazdirPozitif(-3);
yazdirPozitif(7);

Dönüş

Derleme Hataları: return ve Tip

static int yaz(int n) {
    if (n > 0) {
        return 1;
    }
}

error: missing return statement (kapanan } satırında)

static int f() {
    return 2.5;
}

error: incompatible types: possible lossy conversion from double to int

  • void olmayan metotta her yol return ile bitmelidir; burada if’in false dalı eksik. Çözüm: sona return 0; eklemek.
  • Değer, dönüş tipine sığmalıdır: return (int) 2.5; derlenir (2 döner) ya da dönüş tipi double yapılır.
  • void metotta return 1; → error: incompatible types: unexpected return value

Parametreler

Parametre Aktarımı

  • Java her zaman değer ile aktarır (pass by value).
  • İlkel tipte değerin kopyası parametreye yazılır: iki ayrı bellek kutusu.
  • Metot kendi kopyasını değiştirse de çağıranın değişkeni değişmez.
  • Nesnelerde (ör. dizilerde) referansın kopyası aktarılır.
main()sayi5artir(sayi)x5değer kopyalanır

Parametreler · Kodu adım adım çalıştır

Değer ile Aktarım: artir(sayi)

main()sayi5

main’de sayi = 5: main çerçevesinde bir kutu.

main()sayi5artir(sayi)

artir(sayi): gönderilen değişken değil, değeri (5).

main()sayi5artirx5kopya

Yeni çerçevede ayrı bir kutu: x = 5 (kopya).

main()sayi5artirx6

x++ → x = 6. Yalnızca artir’ın kutusu değişti; main’deki sayi hâlâ 5.

main()sayi5artirx6kapandı

Metot biter; çerçeve ve içindeki x (6) silinir. Değer geri gönderilmez (void).

main()sayi5

5 yazılır. Değiştirmek isteseydik: static int artir(int x) { return x + 1; } ve sayi = artir(sayi);

static void artir(int x) {
    x++;
}
// main içinde:
int sayi = 5;
artir(sayi);
System.out.println(sayi);   // 5

Parametreler · Kodu adım adım çalıştır

Değer ile Aktarım Tuzağı: swap(x, y)

main()x3y5

main’de x = 3 ve y = 5: main çerçevesinde iki ayrı kutu.

main()x3y5swap(x, y)

swap(x, y): gönderilen değişkenlerin kendisi değil, değerleri (3 ve 5).

main()x3y5swap(x, y)swapa3b5kopya

swap’in çerçevesinde iki yeni kutu: a = 3 ve b = 5 (kopyalar). x ve y ile bağlantı yok.

main()x3y5swap(x, y)swapa3b5t3

t = a → t = 3: geçici kutu a’nın değerini saklar.

main()x3y5swap(x, y)swapa5b5t3

a = b → a = 5. Eski a değeri artık yalnızca t’de.

main()x3y5swap(x, y)swapa5b3t3

b = t → b = 3. swap’in kopyaları yer değiştirdi (a = 5, b = 3); ama main’deki x ve y’ye hiç dokunulmadı.

main()x3y5

swap bitince çerçevesi (a, b, t) silinir. main’de hâlâ x = 3, y = 5: yalnızca kopyalar takas edildi. Gerçek takas için sonucu döndürmek ya da dizi kullanmak gerekir.

static void swap(int a, int b) {
    int t = a;
    a = b;
    b = t;
}
// main içinde:
int x = 3, y = 5;
swap(x, y);
System.out.println(x + " " + y);   // 3 5

Parametreler

Metot Aşırı Yükleme

static int alan(int kenar) {
    return kenar * kenar;
}
static int alan(int en, int boy) {
    return en * boy;
}
// HATA: yalnız dönüş tipi farklı
static double alan(int kenar) { … }
  • Aynı ad, farklı parametre listesi (sayı, tip veya sıra).
  • Yalnızca dönüş tipini değiştirmek yetmez: çağrıdan hangisi olduğu anlaşılmaz.
  • Derleyici çağrıdaki argümanlara bakarak uygun imzayı seçer.
  • Tanıdık örnek: println(int), println(double), println(String).
alan(4)1 int argümanalan(int kenar)16alan(3, 5)2 int argümanalan(int en, int boy)15Derleyici argümanların sayı ve tipine bakar; dönüş tipine bakmaz.

Parametreler · Kodu adım adım çalıştır

Kod İzleme: derleyici hangi alan’ı seçer?

alan(4)çağrı (argümanlar)alan(int)alan(int, int)derleyicinin gördüğü imzalar

alan(4): derleyici argümanlara bakar: 1 tane int.

alan(4)çağrı (argümanlar)alan(int)✓ eşleşiralan(int, int)✗ 2 parametre isterderleyicinin gördüğü imzalar

Aynı ada sahip iki metot var; parametre sayısı/tipi uyan alan(int) seçilir. Bu karar program çalışmadan, derlemede verilir.

alan(4)çağrı (argümanlar)alan(int)✓ eşleşiralan(int, int)✗ 2 parametre isterderleyicinin gördüğü imzalar

Çalışma zamanında alan(int) çağrılır: kenar = 4 → return 16.

alan(4)çağrı (argümanlar)alan(int)✓ eşleşiralan(int, int)✗ 2 parametre isterderleyicinin gördüğü imzalar

16 yazılır.

alan(3, 5)çağrı (argümanlar)alan(int)✗ 1 parametre isteralan(int, int)✓ eşleşirderleyicinin gördüğü imzalar

alan(3, 5): 2 int argüman → alan(int, int) seçilir.

alan(3, 5)çağrı (argümanlar)alan(int)✗ 1 parametre isteralan(int, int)✓ eşleşirderleyicinin gördüğü imzalar

en = 3, boy = 5 → return 15.

alan(3, 5)çağrı (argümanlar)alan(int)✗ 1 parametre isteralan(int, int)✓ eşleşirderleyicinin gördüğü imzalar

15 yazılır. alan(2.5) yazılsaydı hiçbir imza uymaz → derleme hatası (double → int otomatik olmaz).

static int alan(int kenar) {
    return kenar * kenar;
}
static int alan(int en, int boy) {
    return en * boy;
}
System.out.println(alan(4));      // main
System.out.println(alan(3, 5));   // main

Parametreler

Değişken Sayıda Argüman (varargs)

static int topla(int... s) {
    int t = 0;
    for (int v : s) t += v;
    return t;
}
topla(1, 2, 3)   // 6
topla()          // 0
topla(new int[]{4, 5})   // 9
  • int... s: istenen sayıda argüman; metot içinde s bir int[] dizisidir.
  • Derleyici çağrıdaki değerleri bir diziye paketler; argüman yoksa boş dizi (s.length == 0) olur.
  • Varargs parametresi listenin en sonunda olmalı ve metotta yalnız bir tane bulunabilir.
  • Tanıdık örnek: printf(String, Object...).

Parametreler · Kodu adım adım çalıştır

Değişken Sayıda Argüman: topla(1, 2, 3)

main()topla(1, 2, 3)

topla(1, 2, 3): derleyici üç değeri new int[]{1, 2, 3} dizisine paketler.

main()topla(1, 2, 3)toplas123

s bir int[] dizisidir: s = {1, 2, 3}, s.length = 3.

main()topla(1, 2, 3)toplas123t0

t = 0: toplam için yerel kutu.

main()topla(1, 2, 3)toplas123t1v1

Gelişmiş for, 1. tur: v = 1 → t = 0 + 1 = 1.

main()topla(1, 2, 3)toplas123t3v2

2. tur: v = 2 → t = 1 + 2 = 3.

main()topla(1, 2, 3)toplas123t6v3

3. tur: v = 3 → t = 3 + 3 = 6. Dizide öğe kalmadı.

main()topla(1, 2, 3)toplas123t6

return t → 6 döner. v döngüyle birlikte kapsam dışında.

main()

6 yazılır. topla çerçevesi (s, t) silindi.

static int topla(int... s) {
    int t = 0;
    for (int v : s) t += v;
    return t;
}
// main içinde:
System.out.println(topla(1, 2, 3));
System.out.println(topla());

Parametreler · Kodu adım adım çalıştır

Boş Çağrı: topla()

main()topla()

topla(): hiç argüman yok → derleyici boş dizi (new int[0]) geçirir; null değil.

main()topla()toplas[ ] boş

s boş bir dizi: s.length = 0.

main()topla()toplas[ ] boşt0

t = 0.

main()topla()toplas[ ] boşt0

Dizi boş: gövde hiç çalışmaz, t 0 kalır.

main()topla()toplas[ ] boşt0

return t → 0 döner.

main()

0 yazılır. Boş çağrı hata değildir; sonuç toplamanın etkisiz elemanı olan 0’dır.

static int topla(int... s) {
    int t = 0;
    for (int v : s) t += v;
    return t;
}
// main içinde:
System.out.println(topla(1, 2, 3));
System.out.println(topla());

Kapsam

Yerel Kapsam

  • Parametreler ve metot içinde bildirilen değişkenler yereldir.
  • Bir blokta ({ }) bildirilen değişken yalnızca o blok ve iç bloklarda görünür.
  • Aynı kapsamda aynı adlı iki yerel değişken bildirilemez.
  • Başka metodun yerel değişkenine erişilemez.
hesapla(int n) { … } — metot kapsamın3sonuc0if (n > 0) { … } — blok kapsamıkatki6

Kapsam · Kodu adım adım çalıştır

Kapsam Örneği: hesapla(3)

hesapla(int n) { … } — metot kapsamı

main, hesapla(3)’ü çağırır.

hesapla(int n) { … } — metot kapsamın3

Metot kapsamı açılır: parametre n = 3.

hesapla(int n) { … } — metot kapsamın3sonuc0

sonuc metot kapsamında: metodun sonuna kadar görünür.

hesapla(int n) { … } — metot kapsamın3sonuc0if (n > 0) { … } — blok kapsamı

3 > 0 → true: if bloğuna girilir, yeni bir iç kapsam açılır.

hesapla(int n) { … } — metot kapsamın3sonuc0if (n > 0) { … } — blok kapsamıkatki6

katki = 3 × 2 = 6: yalnızca if bloğunun içinde var.

hesapla(int n) { … } — metot kapsamın3sonuc6if (n > 0) { … } — blok kapsamıkatki6

İç bloktan dış kapsamdaki sonuc’a erişilebilir: sonuc = 0 + 6 = 6.

hesapla(int n) { … } — metot kapsamın3sonuc6if (n > 0) { … } — blok kapsamıkatki → blok bitti, değişken yok

Blok kapandı: katki yok oldu. Burada katki yazmak derleme hatası olurdu.

hesapla(int n) { … } — metot kapsamın3sonuc6if (n > 0) { … } — blok kapsamıkatki → blok bitti, değişken yok

return 6: metot kapsamı da kapanır (n ve sonuc silinir).

hesapla(int n) { … } — metot kapsamı

Dönen 6 println’e argüman olur ve yazılır.

static int hesapla(int n) {
    int sonuc = 0;
    if (n > 0) {
        int katki = n * 2;
        sonuc += katki;
    }
    return sonuc;
}
System.out.println(hesapla(3));  // main

Kapsam

Kapsam: Aynı Adlı Değişken

int x = 1;
if (x > 0) {
    int x = 5;   // hata
}
main metodu kapsamıx1dış x: iç blokta da görünürif (x > 0) { … } bloğuint x = 5;✗ x zaten tanımlı
error: variable x is already defined in method main(String[])
  • İç blokta dış kapsamdaki yerel değişkenle aynı ad kullanılamaz; yerel değişken yerel değişkeni gölgelemez.
  • Parametre de yereldir: topla(int a, int b) içinde int a = 3; aynı hatayı verir.
  • Blok bitince değişken silinir: for (int i …) { } sonrası int i = 7; yazılabilir.
  • static alanla aynı adlı yerel değişken derlenir; yerel olan görünür, alan değişmez.

Kütüphane

Sık Kullanılan Hazır Metotlar: Math

ÇağrıSonuçDönüş tipiNot
Math.abs(-7)7intmutlak değer (aşırı yüklü: int, long, double…)
Math.max(3, 9)9intbüyük olanı döndürür
Math.sqrt(16)4.0doublekarekök; sonuç her zaman double
Math.pow(2, 10)1024.0doubleüs; int’e atamak için (int) gerekir
Math.round(2.5)3longen yakın tam sayıya yuvarlar
  • Belgelerde parametre, dönüş tipi ve özel durumlar okunmalı (ör. Math.sqrt(-1) → NaN).

Tasarım

Soyutlama

çağıran kodMath.sqrt(16)görünen: imza + sözleşmedouble sqrt(double x)x ≥ 0 için √xgizli: gövde? ? ?değişebilir
  • Metot, çağıran koddan uygulama ayrıntısını saklar.
  • İyi adlandırılmış metot ne yapıldığını söyler; nasıl yapıldığı gövdede kalır.
  • Gövde değişse bile imza aynı kaldıkça çağıranlar etkilenmez.

Tasarım

Ayrıştırma

notRaporu()notlariOku()girdiortalamaHesapla()hesap, safharfNotu(ort)kararraporYaz(…)çıktı
  • Büyük görev tek sorumluluklu alt görevlere ayrılır.
  • Her alt görev için girdi, çıktı ve hata davranışı belirlenir.
  • Üst düzey metot bu görevleri anlamlı sırada birleştirir; okuması içindekiler tablosu gibi olur.

Tasarım

İyi Metot Tasarımı

İlkeSoru
Tek görevMetot tek cümleyle açıklanabiliyor mu?
Anlamlı adAd sonuç veya eylemi söylüyor mu?
Az parametreGirdilerin hepsi gerekli mi?
Belirgin sonuçDönüş ve yan etkiler açık mı?
Test edilebilirlikMetot bağımsız örneklerle denenebilir mi?

Örnek

Önce Metot Sözleşmesi

  • Metot adı yaptığı işi açıkça belirtmelidir.
  • Parametrelerin geçerli değer aralığı tanımlanmalıdır.
  • Dönüş değerinin anlamı ve hata davranışı bilinmelidir.
// Görev : sayının onluk basamak sayısını döndürür.
// Girdi : herhangi bir int (negatif de olabilir).
// Çıktı : 1..10; 0 için 1, -507 için 3.
static int basamakSayisi(int sayi) { … }
girdi (ön koşul)herhangi intnegatif de olabilirbasamakSayisiçıktı (son koşul)1 … 10döndürür, ekrana yazmazörnek:0 → 1-507 → 32147483647 → 10-2147483648 → 10

Örnek

Tek / Çift

static boolean ciftMi(int sayi) {
    return sayi % 2 == 0;
}
  • boolean sonuç kararlarda doğrudan kullanılabilir.
  • Metot ekrana yazmak yerine sonucu döndürür.
sayisayi % 2ciftMi(sayi)71false100true-40true-3-1falseJava’da negatif sayının kalanı negatif olabilir (-3 % 2 = -1); bu yüzden == 0 ile bakılır.

Örnekler · Kodu adım adım çalıştır

Kod İzleme: ciftMi(7)

main()if (ciftMi(7))

if koşulunu bulmak için önce ciftMi(7) çağrılır.

main()if (ciftMi(7))ciftMisayi7

Çerçeve açılır: sayi = 7.

main()if (ciftMi(7))ciftMisayi7kapandıreturn false

7 % 2 = 1 → 1 == 0 → false. return false.

main()if (false)

Dönüş değeri çağrının yerine geçer: if (false) → then dalı atlanır.

main()

else dalı: tek yazılır. Metot yalnızca hesapladı; yazma kararı çağırana ait.

static boolean ciftMi(int sayi) {
    return sayi % 2 == 0;
}
// main içinde:
if (ciftMi(7)) System.out.println("çift");
else System.out.println("tek");

Örnek

Basamak Sayısı

static int basamakSayisi(int sayi) {
    long kalan = Math.abs((long) sayi);
    if (kalan == 0) return 1;
    int adet = 0;
    while (kalan > 0) {
        adet++;
        kalan /= 10;
    }
    return adet;
}
System.out.println(basamakSayisi(-507));
  • (long) önce dönüştürür: Math.abs(-2147483648) int’te yine negatif kalırdı.
  • 0 için erken dönüş: 1 basamak.
  • Sonuç ekrana yazılmaz, döndürülür; çağıran istediği gibi kullanır.

Örnekler · Kodu adım adım çalıştır

Kod İzleme: basamakSayisi(-507)

main()println(basamakSayisi(-507))

println’in argümanı için önce basamakSayisi(-507) çağrılır.

main()println(basamakSayisi(-507))basamakSayisisayi-507

Çerçeve açılır: sayi = −507.

main()println(basamakSayisi(-507))basamakSayisisayi-507kalan507

Math.abs((long) −507) → kalan = 507. (Hazır metot da bir çağrıdır: değer döndürür.)

main()println(basamakSayisi(-507))basamakSayisisayi-507kalan507

507 == 0 → false: erken dönüş yok.

main()println(basamakSayisi(-507))basamakSayisisayi-507kalan507adet0

Sayaç adet = 0.

main()println(basamakSayisi(-507))basamakSayisisayi-507kalan50adet1

Tur 1: 507 > 0 → adet = 1, kalan = 507 / 10 = 50.

main()println(basamakSayisi(-507))basamakSayisisayi-507kalan5adet2

Tur 2: 50 > 0 → adet = 2, kalan = 50 / 10 = 5.

main()println(basamakSayisi(-507))basamakSayisisayi-507kalan0adet3

Tur 3: 5 > 0 → adet = 3, kalan = 5 / 10 = 0.

main()println(basamakSayisi(-507))basamakSayisisayi-507kalan0adet3

0 > 0 → false: döngü biter.

main()println(basamakSayisi(-507))basamakSayisisayi-507kalan0adet3kapandıreturn 3

return 3: çerçeve kapanır.

main()println(3)

Çağrının yerine 3 geçer: println(3) → 3 yazılır.

static int basamakSayisi(int sayi) {
    long kalan = Math.abs((long) sayi);
    if (kalan == 0) return 1;
    int adet = 0;
    while (kalan > 0) {
        adet++;
        kalan /= 10;
    }
    return adet;
}
System.out.println(basamakSayisi(-507));

Örnek

Asal mı?

static boolean asalMi(int n) {
    if (n < 2) return false;
    for (int i = 2; i <= n / i; i++)
        if (n % i == 0) return false;
    return true;
}
  • İlk bölen bulunduğunda erken dönüş yapılır.
asalMi(37): yalnızca i ≤ n / i olan i değerleri denenir (√37 ≈ 6,08)in / i37 % i2181312149157266175denenmezHiçbir kalan 0 değil; i = 7 için 7 > 37 / 7 = 5 → döngü biter → return true

Örnekler · Kodu adım adım çalıştır

Kod İzleme: asalMi(15) ve asalMi(7)

main()println(asalMi(15))

asalMi(15) çağrılır.

main()println(asalMi(15))asalMin15

n = 15: 15 < 2 → false.

main()println(asalMi(15))asalMin15i2

2 <= 15/2 = 7 → true; 15 % 2 = 1 → bölmüyor, i++.

main()println(asalMi(15))asalMin15i3kapandıreturn false

3 <= 5 → true; 15 % 3 = 0 → return false: kalan turlar hiç çalışmaz (erken dönüş).

main()println(false)

Dönen false println’e verilir ve yazılır.

main()println(asalMi(7))

asalMi(7) çağrılır.

main()println(asalMi(7))asalMin7

n = 7: 7 < 2 → false.

main()println(asalMi(7))asalMin7i2

2 <= 7/2 = 3 → true; 7 % 2 = 1 → bölmüyor, i++.

main()println(asalMi(7))asalMin7i3

3 <= 7/3 = 2 → false: √7’ye kadar bölen yok.

main()println(asalMi(7))asalMin7kapandıreturn true

Döngü erken dönüş olmadan bitti → return true.

main()println(true)

Dönen true println’e verilir ve yazılır.

static boolean asalMi(int n) {
    if (n < 2) return false;
    for (int i = 2; i <= n / i; i++)
        if (n % i == 0) return false;
    return true;
}
System.out.println(asalMi(15));  // main
System.out.println(asalMi(7));   // main

Örnekler · Kodu adım adım çalıştır

ebob: Öklid algoritması (48, 18)

main()println(ebob(48, 18))

Öklid algoritması en büyük ortak böleni (EBOB) bulur: ebob(a, b) = ebob(b, a % b); b = 0 olunca cevap a.

main()println(ebob(48, 18))eboba48b18

Çerçeve açılır: a = 48, b = 18.

main()println(ebob(48, 18))eboba48b18

Koşul: 18 != 0 → true.

main()println(ebob(48, 18))eboba18b12r12

r = 48 % 18 = 12; a = 18, b = 12. (ebob(48, 18) = ebob(18, 12))

main()println(ebob(48, 18))eboba18b12

Koşul: 12 != 0 → true.

main()println(ebob(48, 18))eboba12b6r6

r = 18 % 12 = 6; a = 12, b = 6. (ebob(18, 12) = ebob(12, 6))

main()println(ebob(48, 18))eboba12b6

Koşul: 6 != 0 → true.

main()println(ebob(48, 18))eboba6b0r0

r = 12 % 6 = 0; a = 6, b = 0. (ebob(12, 6) = ebob(6, 0))

main()println(ebob(48, 18))eboba6b0

Koşul: 0 != 0 → false.

main()println(ebob(48, 18))eboba6b0kapandıreturn 6

return 6.

main()println(6)

6 yazılır: 48 = 6 × 8, 18 = 6 × 3. Yalnızca 3 tur; 1’den 18’e tüm sayıları denemekten çok hızlı.

static int ebob(int a, int b) {
    while (b != 0) {
        int r = a % b;
        a = b;
        b = r;
    }
    return a;
}
System.out.println(ebob(48, 18));  // main

Örnekler · Kodu adım adım çalıştır

ekok(12, 18): metot içinden metot çağrısı

main()println(ekok(12, 18))

main, ekok(12, 18)’i çağırır.

main()println(ekok(12, 18))ekoka12b18

ekok çerçevesi: a = 12, b = 18.

main()println(ekok(12, 18))ekoka12b18a / ebob(a, b) * beboba12b18

İfadeyi hesaplamak için ekok, ebob(a, b) metodunu çağırır: yığında 3 çerçeve.

main()println(ekok(12, 18))ekoka12b18a / ebob(a, b) * beboba6b0kapandıreturn 6

ebob kendi döngüsünü çalıştırır: (12, 18) → (18, 12) → (12, 6) → (6, 0) → return 6. Adları aynı olsa da ebob’un a, b’si ayrı kutulardır.

main()println(ekok(12, 18))ekoka12b1812 / 6 * 18 = 36

Çağrının yerine 6 geçer: 12 / 6 * 18 = 2 * 18 = 36. Önce bölmek, a * b’nin taşmasını önler.

main()println(ekok(12, 18))ekoka12b18kapandıreturn 36

return 36: ekok’un çerçevesi kapanır.

main()println(36)

36 yazılır. Metot başka metodu çağırarak işini kısaltır: kod tekrarı yok.

static int ekok(int a, int b) {
    return a / ebob(a, b) * b;
}
// ebob: Öklid algoritmasıyla EBOB
System.out.println(ekok(12, 18));  // main

Örnekler · Kodu adım adım çalıştır

Yeniden kullanım: enBuyuk3(4, 9, 7)

main()println(enBuyuk3(4, 9, 7))

main, üç sayının en büyüğünü ister.

main()println(enBuyuk3(4, 9, 7))enBuyuk3a4b9c7

enBuyuk3 çerçevesi: a = 4, b = 9, c = 7.

main()println(enBuyuk3(4, 9, 7))enBuyuk3a4b9c7enBuyuk(enBuyuk(4, 9), 7)

İç içe çağrıda önce içteki hesaplanır: enBuyuk(4, 9).

main()println(enBuyuk3(4, 9, 7))enBuyuk3a4b9c7enBuyuk(enBuyuk(4, 9), 7)enBuyuka4b9

Yeni çerçeve (a = 4, b = 9): 4 > 9 → false.

main()println(enBuyuk3(4, 9, 7))enBuyuk3a4b9c7enBuyuk(enBuyuk(4, 9), 7)enBuyuka4b9kapandıreturn 9

return b → 9.

main()println(enBuyuk3(4, 9, 7))enBuyuk3a4b9c7enBuyuk(9, 7)

İfade sadeleşti: enBuyuk(9, 7). Aynı metot ikinci kez çağrılır.

main()println(enBuyuk3(4, 9, 7))enBuyuk3a4b9c7enBuyuk(9, 7)enBuyuka9b7kapandıreturn 9

Yeni çerçeve (a = 9, b = 7): 9 > 7 → true → return a → 9.

main()println(enBuyuk3(4, 9, 7))enBuyuk3a4b9c7kapandıreturn 9

enBuyuk3 de 9 döndürür.

main()println(9)

9 yazılır. Karşılaştırma mantığı tek yerde (enBuyuk): hata varsa tek yerde düzeltilir.

static int enBuyuk(int a, int b) {
    if (a > b) return a;
    return b;
}
static int enBuyuk3(int a, int b, int c) {
    return enBuyuk(enBuyuk(a, b), c);
}
System.out.println(enBuyuk3(4, 9, 7));  // main

Örnekler · Kodu adım adım çalıştır

double döndüren metotlar: sıcaklık dönüşümü

main()f = fahrenheit(25)

fahrenheit(25): int argüman 25, double parametreye 25.0 olarak genişletilir.

main()f = fahrenheit(25)fahrenheitc25.0

c = 25.0.

main()f = fahrenheit(25)fahrenheitc25.0kapandıreturn 77.0

25.0 × 9 = 225.0; / 5 = 45.0; + 32 = 77.0 → return.

main()f77.0f = 77.0

f = 77.0 (double).

main()f77.0

77.0 yazılır (double olduğu için .0 ile).

main()f77.0println(celsius(f))celsiusf77.0

celsius(f): f’nin değeri (77.0) kopyalanır.

main()f77.0println(celsius(f))celsiusf77.0kapandıreturn 25.0

(77.0 − 32) × 5 / 9 = 45.0 × 5 / 9 = 25.0. 5 / 9 * (f - 32) yazılsaydı 5 / 9 tam sayı bölmesiyle 0 olurdu!

main()f77.0println(25.0)

25.0 yazılır: iki metot birbirinin tersi (test için güzel bir kontrol).

static double fahrenheit(double c) {
    return c * 9 / 5 + 32;
}
static double celsius(double f) {
    return (f - 32) * 5 / 9;
}
double f = fahrenheit(25);          // main
System.out.println(f);
System.out.println(celsius(f));

Örnek

Saf Metot ve Yan Etki

  • Aynı girdi için aynı sonucu döndüren ve dış durumu değiştirmeyen metot daha kolay test edilir.
  • Hesaplama metodu ile ekrana yazma metodu ayrılabilir.
  • Gerektiğinde yan etki açıkça adlandırılmalı ve sınırlandırılmalıdır.
Safstatic int kare(int x) { return x * x; }

kare(4) her zaman 16; her yerde kullanılabilir.

Yan etkilistatic void kareYaz(int x) { System.out.println(x * x); }

Yalnızca ekrana yazar; sonuç başka hesapta kullanılamaz.

Özet

Bölüm Özeti

  • Metot bir görevi adlandırır, parametrelerle girdi alır ve sonuç döndürebilir.
  • Java'da argümanlar her zaman değer ile aktarılır.
  • Aşırı yüklemede aynı ad farklı parametre listeleriyle kullanılır.
  • Kapsam, değişkenin nerede erişilebilir olduğunu belirler.
  • Metot başka metodu çağırabilir (ekok → ebob, enBuyuk3 → enBuyuk); her çağrı yığında kendi çerçevesini açar.
  • Sonucu ekrana yazmak yerine döndüren metot daha kolay test edilir ve yeniden kullanılır.

Özet

Kontrol Soruları

  1. Parametre ile argüman arasındaki fark nedir?
  2. void metot hangi durumda kullanılır?
  3. artir(sayi) çağrısından sonra sayi neden değişmez?
  4. Aşırı yüklemede hangi bölüm farklı olmalıdır? int f(int) ile double f(int) neden birlikte olamaz?
  5. ciftMi neden ekrana yazmak yerine boolean döndürür?

Özet

Alıştırmalar

  1. static boolean artikYil(int yil) yazın (4/100/400 kuralı) ve 1900, 2000, 2024 ile deneyin.
  2. static long faktoriyel(int n) ve bunu kullanan static long kombinasyon(int n, int r) = n! / (r! (n − r)!) yazın.
  3. static int tersCevir(int sayi) ve onu çağıran static boolean palindromMu(int sayi) yazın.
  4. static double ortalama(int a, int b, int c): neden (a + b + c) / 3 yanlış sonuç verebilir? Düzeltin.
  5. Aşırı yükleme: enBuyuk(double, double) ekleyin; enBuyuk(3, 4.5) hangisini çağırır?
  6. asalMi ile 1..100 arasındaki ikiz asalları (5–7, 11–13 …) listeleyen bir main yazın.

Özet

Kaynaklar

Son

Metotlar
Sonraki sunum: Diziler · Çalışma soruları · Simülatör: Metot Çağrı Yığını · Terim sözlüğü
1 / 1Sercan KÜLCÜ, Tüm hakları saklıdır.