Metot Kavramı ve Tanımlama
Giriş — Neden Metot?
Şimdiye kadar tüm kodunu main metodunun içine yazdın. Küçük programlar için bu sorun değil. Ama program büyüdükçe main metodu binlerce satır olur ve bir şeyi değiştirmek, bulmak, test etmek imkansız hale gelir.
Düşün: her sabah kahvaltı yapıyorsun. Ama her seferinde "ocağı aç, tavayı koy, yağı ekle, yumurtayı kır, pişir, tabağa al" diye tüm adımları tekrar yazmak yerine, buna "yumurta yap" deyip geçsen güzel olmaz mı?
Metotlar tam da bunu yapar. Tekrarlayan veya mantıksal olarak bir bütün olan kodu bir isim altında paketler. İhtiyacın olduğunda o ismi çağırırsın.
Analoji: Metotları bir restoran mutfağı gibi düşün. "Sipariş ver" diyorsun (metodu çağır), mutfak çalışıyor (metot gövdesi), tabak gelir (dönüş değeri). Mutfakta ne olduğunu bilmene gerek yok — sadece ne istediğini söylüyorsun.
Metot Tanımlama
Java'da metot tanımlamak şöyle:
erişimBelirteci static dönüşTipi metotAdi(parametreler) {
// metot gövdesi
return değer; // void ise gerek yok
}Her parçanın anlamı:
Erişim belirteci:
public,private, vb. (şimdilikpublickullanacağız, OOP dersinde detaylandıracağız)`static`: main'den doğrudan çağırabilmek için (OOP öncesinde hep static kullanacağız)
Dönüş tipi: Metot ne tür bir değer döndürür (
int,String,double, vb.)Metot adı: Metodu çağırmak için kullanacağın isim
Parametreler: Metoda dışarıdan gönderilen veriler
`return`: Değeri döndürüp metottan çıkar
İlk Metot: Selamlama
public class MerhabaMetot {
public static void selamla() {
System.out.println("Merhaba, Java dünyasına hoş geldin!");
}
public static void main(String[] args) {
selamla(); // Metodu çağır
selamla(); // İstediğin kadar çağır
selamla();
}
}selamla() metodu 3 kez çağrıldı, her seferinde aynı mesajı yazdırdı. Kodu bir kez yazdık, üç kez kullandık.
Örnek: İki Sayıyı Toplayan Metot
public static int topla(int a, int b) {
int sonuc = a + b;
return sonuc;
}
public static void main(String[] args) {
int toplam = topla(5, 3);
System.out.println("5 + 3 = " + toplam); // 8
System.out.println("10 + 20 = " + topla(10, 20)); // 30
}topla metodu:
İki
intparametre alıyor (aveb)inttipinde bir değer döndürüyorreturn sonucile değeri geri gönderiyor
void — Değer Döndürmeyen Metotlar
Her metot bir değer döndürmek zorunda değil. Sadece bir iş yapıp biten metotlar void dönüş tipini kullanır.
public static void bilgiYazdir(String isim, int yas) {
System.out.println("İsim: " + isim);
System.out.println("Yaş: " + yas);
System.out.println("---");
}
public static void main(String[] args) {
bilgiYazdir("Ali", 25);
bilgiYazdir("Ayşe", 30);
}void metotlarda:
returnyazman gerekmez (metot sonunda otomatik döner)return;(değersiz) yazarak erken çıkabilirsin
public static void mesajGonder(String alici, String mesaj) {
if (alici == null || alici.isEmpty()) {
System.out.println("Hata: Alıcı belirtilmedi!");
return; // Erken çıkış — guard clause
}
System.out.println(alici + " kişisine gönderildi: " + mesaj);
}💡 İpucu: void metotlar genellikle bir yan etki (side effect) yapar: ekrana yazdırır, dosyaya yazar, değişken günceller. Değer döndüren metotlar ise genellikle bir hesaplama yapar. İkisini karıştırma — bir metot ya hesaplasın ya da iş yapsın.
Parametreler ve Argümanlar
Bu iki terim sık karıştırılır:
Parametre: Metot tanımındaki değişken (formal parameter)
Argüman: Metodu çağırırken gönderdiğin gerçek değer (actual argument)
// parametre parametre
public static int topla(int a, int b) {
return a + b;
}
// argüman argüman
int sonuc = topla(5, 3);a ve b parametre, 5 ve 3 argüman.
Birden Fazla Parametre
public static double ucgenAlani(double taban, double yukseklik) {
return taban * yukseklik / 2;
}
public static String tekrarla(String metin, int kez) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < kez; i++) {
sb.append(metin);
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println("Alan: " + ucgenAlani(5.0, 3.0)); // 7.5
System.out.println(tekrarla("Ha", 3)); // HaHaHa
}Parametre Sırası Önemli!
public static void bilgi(String isim, int yas) { ... }
bilgi("Ali", 25); // Doğru
bilgi(25, "Ali"); // DERLEME HATASI — tipler uyuşmuyorParametrelerin sırası, tanımdaki sırayla eşleşmeli.
Dönüş Tipi ve return
Metot bir değer döndürüyorsa:
Dönüş tipi belirtilmeli (
int,String,double, vb.)Metot gövdesinde
return değer;olmalıDöndürülen değer, belirtilen tiple uyumlu olmalı
Her Yolda return Olmalı
// DERLEME HATASI — else'te return yok!
public static String notHesapla(int puan) {
if (puan >= 50) {
return "Geçti";
}
// Peki puan < 50 ise? return yok!
}
// DOĞRU
public static String notHesapla(int puan) {
if (puan >= 50) {
return "Geçti";
}
return "Kaldı"; // Her koşulda bir return var
}Java derleyicisi tüm olası yolların bir return ifadesine ulaştığını kontrol eder. Eğer bir yol return'süz kalırsa derleme hatası verir.
return Birden Fazla Olabilir (Early Return)
public static char notHarfi(int puan) {
if (puan >= 90) return 'A';
if (puan >= 80) return 'B';
if (puan >= 70) return 'C';
if (puan >= 60) return 'D';
return 'F';
}İlk eşleşen return çalışır ve metottan çıkılır.
Dönüş Değerini Kullanmak Zorunda Değilsin
public static int topla(int a, int b) {
return a + b;
}
topla(3, 5); // Geçerli ama dönen değer kaybolur
int sonuc = topla(3, 5); // Değeri yakala
System.out.println(topla(3, 5)); // Değeri doğrudan kullanCall by Value — Java'nın Parametre Geçiş Mekanizması
Java'da parametreler her zaman değer kopyalanarak (call by value) geçirilir. Bu çok önemli bir kural.
Primitive Tipler — Kopya Geçer
public static void ikiyeKatla(int sayi) {
sayi = sayi * 2;
System.out.println("Metot içinde: " + sayi); // 20
}
public static void main(String[] args) {
int x = 10;
ikiyeKatla(x);
System.out.println("Metot sonrası: " + x); // 10 — değişmedi!
}x'in kopyası metoda gönderildi. Metot kopyayı değiştirdi ama orijinal x etkilenmedi.
Bu, bir arkadaşına bir belgenin fotokopisini vermek gibi. Fotokopi üzerinde ne yaparsa yapsın, senin orijinal belgen aynı kalır.
Referans Tipler — Referansın Kopyası Geçer
public static void elemanEkle(int[] dizi) {
dizi[0] = 999; // Orijinal diziyi değiştirir!
}
public static void main(String[] args) {
int[] sayilar = {1, 2, 3};
elemanEkle(sayilar);
System.out.println(sayilar[0]); // 999 — değişti!
}Durum! Dizi değişti mi? Ama "call by value" demiştik?
Açıklama: Referans tiplerinde referansın kopyası geçirilir. Yani hem sayilar hem metottaki dizi aynı diziye işaret eder. Referansı kopyalıyoruz, ama ikisi de aynı nesneye bakıyor.
public static void diziDegistir(int[] dizi) {
dizi = new int[]{100, 200, 300}; // Yeni dizi oluşturdu
System.out.println("Metot içinde: " + dizi[0]); // 100
}
public static void main(String[] args) {
int[] sayilar = {1, 2, 3};
diziDegistir(sayilar);
System.out.println("Metot sonrası: " + sayilar[0]); // 1 — değişmedi!
}Bu sefer değişmedi! Çünkü metot içinde dizi referansı yeni bir diziye yönlendirildi, ama orijinal referans (sayilar) hâlâ eski diziyi gösteriyor.
⚠️ Dikkat: Java'da call by reference yoktur. Referans tiplerinde bile referansın kopyası geçirilir. Bu, referans üzerinden nesnenin içeriğini değiştirebilirsin ama referansın kendisini (hangi nesneye baktığını) değiştiremezsin demektir.
Özet Tablo
| Tip | Metotta Değişiklik | Orijinale Etkisi |
|---|---|---|
int, double, vb. | Kopyayı değiştirir | Yok |
int[], String[] | İçeriği değiştirir | Var |
int[], String[] | Referansı yeniler (= new ...) | Yok |
String | Immutable, yeni nesne oluşur | Yok |
static Metotlar
Şimdiye kadar yazdığımız tüm metotlar static idi. Peki neden?
static metotlar, sınıfa aittir, herhangi bir nesneye değil. Nesne oluşturmadan doğrudan çağırabilirsin. main metodu static olduğu için, ondan çağırdığımız metotlar da static olmalı (ya da bir nesne üzerinden çağırmalıyız).
public class Hesaplama {
// static metot — sınıf üzerinden çağrılır
public static int topla(int a, int b) {
return a + b;
}
public static void main(String[] args) {
// Aynı sınıf içinden — direkt çağır
int sonuc = topla(3, 5);
// Başka sınıftan — sınıf adıyla çağır
// int sonuc = Hesaplama.topla(3, 5);
}
}Java'nın Kendi static Metotları
Zaten birçok static metot kullandın:
Math.sqrt(25); // Math sınıfının static metodu
Math.max(10, 20); // Math sınıfının static metodu
Integer.parseInt("42"); // Integer sınıfının static metodu
Arrays.sort(dizi); // Arrays sınıfının static metoduHepsi sınıf adıyla çağrılıyor, nesne oluşturmana gerek yok.
static vs Instance Metotlar (Kısa Bakış)
public class Kisi {
String isim;
// instance metot — nesneye ait
public String selamla() {
return "Merhaba, ben " + this.isim;
}
// static metot — sınıfa ait
public static String genelBilgi() {
return "Bu bir Kisi sınıfıdır.";
}
}
// Kullanım
Kisi ali = new Kisi();
ali.isim = "Ali";
ali.selamla(); // nesne üzerinden
Kisi.genelBilgi(); // sınıf üzerindenInstance metotları OOP dersinde detaylı göreceğiz. Şimdilik static metotlarla devam ediyoruz.
💡 İpucu: OOP öncesinde tüm metotları
public staticolarak yaz. Bu, main'den doğrudan çağırmanı sağlar. OOP konusuna geçtiğimizde static'i ne zaman kullanıp kullanmamayı öğreneceksin.
Metot Çağırma Akışı
Bir metot çağrıldığında neler olur?
Argümanlar hesaplanır ve parametrelere kopyalanır
Program akışı metot gövdesine atlar
Metot gövdesi çalışır
`return` ifadesine ulaşılır (veya metot sonu)
Dönüş değeri çağıran yere gönderilir
Program akışı çağrılan yerden devam eder
public static int kareAl(int n) {
System.out.println("kareAl çağrıldı, n=" + n);
return n * n;
}
public static void main(String[] args) {
System.out.println("1. satır");
int sonuc = kareAl(5); // → kareAl'a atla
System.out.println("Sonuç: " + sonuc); // kareAl'dan dön
System.out.println("Son satır");
}Çıktı:
1. satır
kareAl çağrıldı, n=5
Sonuç: 25
Son satırMetotlar Birbirini Çağırabilir
public static double dikdortgenAlani(double en, double boy) {
return en * boy;
}
public static double dikdortgenCevresi(double en, double boy) {
return 2 * (en + boy);
}
public static void dikdortgenBilgi(double en, double boy) {
System.out.println("En: " + en + ", Boy: " + boy);
System.out.println("Alan: " + dikdortgenAlani(en, boy));
System.out.println("Çevre: " + dikdortgenCevresi(en, boy));
}
public static void main(String[] args) {
dikdortgenBilgi(5, 3);
}dikdortgenBilgi metodu, dikdortgenAlani ve dikdortgenCevresi metotlarını çağırıyor. Metotlar birbirini çağırarak karmaşık işleri adım adım çözer.
Metot İmzası (Method Signature)
Java'da bir metot, imzası (signature) ile tanımlanır. İmza şunlardan oluşur:
Metot adı
Parametre tipleri ve sırası
Dönüş tipi imzanın parçası değildir!
// Bu üçü farklı imzaya sahip:
int topla(int a, int b) // topla(int, int)
double topla(double a, double b) // topla(double, double)
int topla(int a, int b, int c) // topla(int, int, int)
// Bu ikisi aynı imzaya sahip — DERLEME HATASI!
int topla(int a, int b)
double topla(int x, int y) // İmza aynı: topla(int, int)Parametre isimleri imzayı değiştirmez, sadece tipler ve sıralama önemlidir.
Pratik Örnekler
Örnek: Basit Hesap Makinesi
public static double hesapla(double a, double b, char islem) {
return switch (islem) {
case '+' -> a + b;
case '-' -> a - b;
case '*' -> a * b;
case '/' -> {
if (b == 0) {
System.out.println("Hata: Sıfıra bölme!");
yield 0;
}
yield a / b;
}
default -> {
System.out.println("Geçersiz işlem: " + islem);
yield 0;
}
};
}
public static void main(String[] args) {
System.out.println("10 + 3 = " + hesapla(10, 3, '+'));
System.out.println("10 / 3 = " + hesapla(10, 3, '/'));
System.out.println("10 / 0 = " + hesapla(10, 0, '/'));
}Örnek: Dizi İşlemleri
public static int diziBul(int[] dizi, int aranan) {
for (int i = 0; i < dizi.length; i++) {
if (dizi[i] == aranan) {
return i; // Bulunduğu index
}
}
return -1; // Bulunamadı
}
public static double diziOrtalama(int[] dizi) {
if (dizi == null || dizi.length == 0) {
return 0;
}
int toplam = 0;
for (int eleman : dizi) {
toplam += eleman;
}
return (double) toplam / dizi.length;
}
public static int[] diziFiltrele(int[] dizi, int esik) {
int sayac = 0;
for (int eleman : dizi) {
if (eleman >= esik) sayac++;
}
int[] sonuc = new int[sayac];
int idx = 0;
for (int eleman : dizi) {
if (eleman >= esik) {
sonuc[idx++] = eleman;
}
}
return sonuc;
}
public static void main(String[] args) {
int[] notlar = {45, 78, 92, 35, 67, 88, 54};
System.out.println("78'in indexi: " + diziBul(notlar, 78));
System.out.printf("Ortalama: %.1f%n", diziOrtalama(notlar));
int[] gecenler = diziFiltrele(notlar, 50);
System.out.print("50+ notlar: ");
for (int n : gecenler) System.out.print(n + " ");
}Örnek: String Yardımcı Metotları
public static boolean palindromMu(String metin) {
String temiz = metin.toLowerCase().replaceAll("[^a-z0-9ğüşıöç]", "");
int sol = 0, sag = temiz.length() - 1;
while (sol < sag) {
if (temiz.charAt(sol) != temiz.charAt(sag)) {
return false;
}
sol++;
sag--;
}
return true;
}
public static String basliklaCevir(String metin) {
if (metin == null || metin.isEmpty()) return metin;
String[] kelimeler = metin.split(" ");
StringBuilder sb = new StringBuilder();
for (String kelime : kelimeler) {
if (!kelime.isEmpty()) {
sb.append(Character.toUpperCase(kelime.charAt(0)));
sb.append(kelime.substring(1).toLowerCase());
sb.append(" ");
}
}
return sb.toString().trim();
}
public static void main(String[] args) {
System.out.println(palindromMu("kayak")); // true
System.out.println(palindromMu("java")); // false
System.out.println(basliklaCevir("merhaba DÜNYA")); // Merhaba Dünya
}Metotların Avantajları
Kod tekrarını azaltır — Aynı işi yapan kodu bir kez yaz, istediğin kadar çağır
Okunabilirlik —
siparisOnayla()yazmak 30 satır kodu okumaktan daha açıklayıcıTest edilebilirlik — Her metot bağımsız test edilebilir
Bakım kolaylığı — Bir şeyi değiştirmek için tek yere bakarsın
Soyutlama — Detayları gizler, büyük resmi gösterir
Call Stack — Metot Çağrı Yığını
Metotlar birbirini çağırdığında Java bir call stack (çağrı yığını) tutar. Her metot çağrısı yığına bir çerçeve (frame) ekler, metot bitince o çerçeve kaldırılır.
public static void a() {
System.out.println("a başladı");
b();
System.out.println("a bitti");
}
public static void b() {
System.out.println("b başladı");
c();
System.out.println("b bitti");
}
public static void c() {
System.out.println("c başladı");
System.out.println("c bitti");
}
public static void main(String[] args) {
a();
}Çıktı:
a başladı
b başladı
c başladı
c bitti
b bitti
a bittiCall stack'in durumu:
[main] → [main, a] → [main, a, b] → [main, a, b, c]
→ [main, a, b]
→ [main, a]
→ [main]⚠️ Dikkat: Call stack'in bir boyut sınırı var. Metotlar sonsuza kadar birbirini çağırırsa StackOverflowError alırsın. Bu konuyu Recursion dersinde detaylı göreceğiz.
Metot Tasarımında İlk Adımlar
İyi bir metot yazmak için şu soruları sor:
Bu metot ne yapıyor? — Tek cümleyle açıklayabiliyorsan iyi tasarlanmış.
Kaç parametre alıyor? — 3'ten fazla genellikle çok fazla.
Ne döndürüyor? — Hesaplama metotları değer, aksiyon metotları void döndürmeli.
Adı ne? — Fiille başlamalı:
hesapla,bul,kontrol,yazdir.
// İYİ — adı açıklayıcı, tek iş yapıyor
public static boolean asalMi(int sayi) { ... }
public static double daireAlani(double yaricap) { ... }
public static int enBuyukBul(int[] dizi) { ... }
// KÖTÜ — ne yaptığı belirsiz, çok iş yapıyor
public static void islemYap(int[] d, String m, boolean f) { ... }Bu konuyu Metot Tasarım İlkeleri dersinde derinlemesine işleyeceğiz.
Yaygın Hatalar
1. static Olmayan Metodu main'den Çağırmak
public class Hata {
public int topla(int a, int b) { // static DEĞİL!
return a + b;
}
public static void main(String[] args) {
topla(3, 5); // HATA! Non-static method cannot be
// referenced from a static context
}
}Çözüm: Ya metodu static yap, ya da nesne oluştur: new Hata().topla(3, 5).
2. return Sonrası Kod Yazmak
public static int topla(int a, int b) {
return a + b;
System.out.println("Bitti"); // DERLEME HATASI — unreachable code
}return'den sonra kod yazamazsın, çünkü orası ulaşılamaz (unreachable).
3. void Metotta Değer Döndürmek (veya Tam Tersi)
// HATA — void metot değer döndüremez
public static void selamla() {
return "Merhaba"; // Derleme hatası!
}
// HATA — int metot değer döndürmeli
public static int topla(int a, int b) {
System.out.println(a + b);
// return yok → derleme hatası!
}Özet
Metot, tekrarlayan kodu bir isim altında paketler — kodu yeniden kullanılabilir, okunabilir ve test edilebilir yapar.
Parametreler metoda veri gönderir, return metottan değer döndürür. void metotlar değer döndürmez.
Java'da call by value geçerlidir — primitive tipler kopyalanır, referans tiplerinde referansın kopyası geçer.
static metotlar sınıfa aittir, nesne oluşturmadan çağrılabilir. OOP öncesi her metodu static yap.
Metot imzası = metot adı + parametre tipleri. Dönüş tipi imzanın parçası değildir.
Her yolda return olmalı — Java derleyicisi bunu kontrol eder, eksik return derleme hatası verir.
AI Asistan
Sorularını yanıtlamaya hazır