Bölüm 3.2: Fonksiyonlar
Giriş
Öğrenme Çıktıları
Erişim belirleyici, dönüş tipi, ad ve parametre listesiyle bir metot yazmak; argümanlarla çağırıp dönüş değerini kullanmak.
Çağrı yığınında (call stack) çerçevelerin nasıl açılıp kapandığını, argümanların değer olarak kopyalandığını adım adım göstermek.
Aynı adlı metotları parametre listesiyle ayırmak; derleyicinin hangi sürümü seçtiğini argüman tiplerinden öngörmek.
System.out ve Math metotlarını doğru kullanmak; Java kütüphanesinin sık kullanılan sınıflarını ve paketlerini tanımak.
Yerel değişkenlerin, sınıf alanlarının ve iç içe blokların kapsamını ve yaşam süresini açıklamak.
Soyutlama, genelleme, DRY ve tek sorumluluk ilkeleriyle iyi metot tasarlamak; problemi metotlara bölmek.
Fonksiyon Kavramı
Fonksiyon Nedir?
Fonksiyon (function), bir işi yapan, adı olan ve tekrar tekrar kullanılabilen kod parçasıdır. Java'da fonksiyonlar her zaman bir sınıfın içinde yazılır ve metot (method) adını alır.
- Aldığı parametreler ve dönüş değeri tipi ile tanımlanır.
- Kodun okunabilirliğini artırır, kod tekrarını azaltır.
- Modüler ve düzenli kod yazmayı teşvik eder.
- Programı küçük, yönetilebilir parçalara ayırır.
"Çay demle" bir tariftir: bir kez yazılır, istendiği kadar uygulanır. Malzemeler parametre, ortaya çıkan çay dönüş değeridir. Tarifi kullanan, her adımı yeniden düşünmek zorunda kalmaz.
main da bir metottur; System.out.println(...) ise hazır bir metot çağrısıdır.Fonksiyon Kavramı
Girdi – İşlem – Çıktı
Her fonksiyon üç aşamada düşünülebilir:
Fonksiyona veri sağlanır: parametreler. Fonksiyonun ne üzerinde çalışacağını belirler.
Fonksiyon, gövdesindeki deyimlerle girdiyi işler ve belirli bir görevi yerine getirir.
İşlem sonunda bir sonuç üretilir ve return ile çağırana geri döndürülür.
Matematikteki f(x) = x² gibi: x girdi, kare alma işlem, x² çıktıdır. Bazı fonksiyonların girdisi ya da çıktısı olmayabilir (void).
Tanım ve Çağrı
Fonksiyon Tanımı
public | Erişim belirleyici (access modifier): metodu kimlerin çağırabileceğini söyler. |
int | Dönüş değeri tipi: metodun geri vereceği değerin tipi; değer döndürmüyorsa void. |
toplama | Metot adı: fiil ya da fiil öbeği, küçük harfle başlar (camelCase). |
(int sayi1, int sayi2) | Parametreler: metodun girdileri; her birinin tipi ve adı yazılır. |
{ ... } | Kod bloğu (gövde): metot çağrıldığında çalışacak deyimler. |
toplama metodu, sayi1 ve sayi2 adlı iki girdi parametresi alır, bunları toplar ve sonucu geri döndürür.
Tanım ve Çağrı
Fonksiyon Çağırma
public class ToplamaOrnegi { public static int toplama(int sayi1, int sayi2) { int sonuc = sayi1 + sayi2; return sonuc; } public static void main(String[] args) { int sonuc = toplama(5, 3); System.out.println("Toplam: " + sonuc); } }
Toplam: 8
toplama(5, 3)bir çağrıdır (call): program akışı metoda gider, metot bitince çağrının yapıldığı yere geri döner.- Çağrıdaki
5ve3argümandır (argument); tanımdakisayi1,sayi2ise parametredir (parameter). - Çağrı 8 değerini döndürür; bu değer
sonucdeğişkenine atanır. - Argüman sayısı, sırası ve tipleri parametrelerle uyuşmalıdır.
static: metot nesne oluşturmadan, doğrudanmain'den çağrılabilir.
Tanım ve Çağrı · Adım adım kod izleme
Çağrı ve Dönüş: Adım Adım
Program her zaman main metodundan başlar. Yığında yalnızca main çerçevesi vardır.
toplama(5, 3) çağrılır: yeni bir çerçeve (frame) açılır, argümanlar parametrelere kopyalanır.
Gövde çalışır: sonuc = 5 + 3 = 8. Bu sonuc, toplama'nın yerel değişkenidir.
return sonuc; 8 değerini çağırana gönderir ve metodu bitirir; çerçeve yığından silinir.
Akış çağrının yapıldığı satıra döner: dönen 8, main'in sonuc değişkenine atanır. İki sonuc farklı değişkenlerdir.
println de bir metot çağrısıdır: ekrana Toplam: 8 yazılır.
static int toplama(int sayi1, int sayi2) { int sonuc = sayi1 + sayi2; return sonuc; } public static void main(String[] args) { int sonuc = toplama(5, 3); System.out.println("Toplam: " + sonuc); }
Tanım ve Çağrı
Örnek Fonksiyonlar
public class OrnekFonksiyonlar { // Toplama fonksiyonu public static int toplama(int sayi1, int sayi2) { return sayi1 + sayi2; } // Kare hesaplama fonksiyonu public static double kareHesapla(double sayi) { return sayi * sayi; } // Merhaba dünya fonksiyonu public static void merhabaDunya() { System.out.println("Merhaba, Dünya!"); } public static void main(String[] args) { System.out.println(toplama(2, 7)); System.out.println(kareHesapla(1.5)); merhabaDunya(); } }
9 2.25 Merhaba, Dünya!
| Metot | Girdi | Çıktı |
|---|---|---|
toplama | 2 × int | int |
kareHesapla | 1 × double | double |
merhabaDunya | yok | yok (void) |
Değer döndüren metodun sonucu bir ifadede kullanılır; void metot ise tek başına bir deyim olarak çağrılır.
Tanım ve Çağrı
return ve void
return ifade;değeri çağırana verir ve metodu hemen bitirir; sonraki satırlar çalışmaz.- Dönen değerin tipi, bildirilen dönüş tipiyle uyumlu olmalıdır (
int→doublegenişlemesi serbesttir). - Değer döndüren metotta her yol bir
returnile bitmelidir; yoksa derleyicimissing return statementder. voidmetot değer döndürmez; erken çıkmak için tek başınareturn;yazılabilir.
public class Erken { static void bolumYazdir(int bolunen, int bolen) { if (bolen == 0) { System.out.println("Sıfıra bölünemez!"); return; // metottan hemen çık } System.out.println(bolunen / bolen); } public static void main(String[] args) { bolumYazdir(10, 2); bolumYazdir(7, 0); } }
5 Sıfıra bölünemez!
Tanım ve Çağrı
static ve Nesne Üzerinden Çağrı
static int toplama(int sayi1, int sayi2) { return sayi1 + sayi2; } // main içinde, doğrudan: int sonuc = toplama(5, 3);
static metot sınıfa aittir; nesne gerekmez. Başka sınıftan SinifAdi.metot() biçiminde çağrılır: Math.sqrt(16) gibi.
public class Hesap { int toplama(int sayi1, int sayi2) { return sayi1 + sayi2; } public static void main(String[] args) { Hesap hesap = new Hesap(); int sonuc = hesap.toplama(5, 3); System.out.println(sonuc); // 8 } }
static olmayan metot bir nesne üzerinden çağrılır: önce new ile nesne oluşturulur, sonra hesap.toplama(5, 3).
static yokken main'den doğrudan toplama(5, 3) yazmak derleme hatasıdır:non-static method toplama(int,int) cannot be referenced from a static contextTanım ve Çağrı · Adım adım kod izleme
Değer ile Aktarım (Pass by Value)
Metot, kendisine verilen değişkeni değiştirebilir mi?
main'de sayi = 5.
Çağrıda değerin kopyası (5) gönderilir. arttir'in sayi'si ayrı bir kutudur; adlarının aynı olması önemsizdir.
Yalnızca kopya değişir: arttir'deki sayi 15 olur, main'deki hâlâ 5.
arttir içinde 15 yazılır.
arttir bitti, çerçevesi ve kopyası silindi. main'deki sayi 5 kaldı: Java argümanları değer ile aktarır (pass by value).
static void arttir(int sayi) { sayi = sayi + 10; System.out.println("arttir: " + sayi); } public static void main(String[] args) { int sayi = 5; arttir(sayi); System.out.println("main: " + sayi); }
Tanım ve Çağrı · Adım adım kod izleme
Referansın Kopyası: Kodu Adım Adım İzle
a bir referans: dizi nesnesi heap'te durur, a onun adresini tutar.
x = 1: ilkel değer doğrudan çerçevede saklanır.
Çağrı: d'ye a'daki referansın kopyası, x'e 1'in kopyası verilir. d ve a aynı diziyi gösterir.
d[0] = 50: ortak dizi değişir; main da bu değişikliği görecek.
x = 50: yalnızca degistir'in kopyası değişir.
d = new int[2]: d artık yeni bir diziyi gösterir. a etkilenmez; bağ koptu.
d[1] = 50 yeni diziye yazılır; main'in dizisi değişmez.
Metot bitti; çerçevesi silindi. Yeni dizi artık hiçbir referansla gösterilmiyor (çöp toplayıcı temizleyecek).
50 2 1: dizinin içeriği değişti, x değişmedi. Java her şeyi değerle aktarır; referans da kopyalanan bir değerdir.
static void degistir(int[] d, int x) { d[0] = 50; x = 50; d = new int[2]; d[1] = 50; } public static void main(String[] args) { int[] a = {1, 2}; int x = 1; degistir(a, x); System.out.println(a[0] + " " + a[1] + " " + x); }
Tanım ve Çağrı
Metot Aşırı Yükleme
public class AsiriYukleme { static int topla(int a, int b) { return a + b; } static double topla(double a, double b) { return a + b; } static int topla(int a, int b, int c) { return a + b + c; } public static void main(String[] args) { System.out.println(topla(2, 3)); System.out.println(topla(2.5, 1.2)); System.out.println(topla(1, 2, 3)); } }
5 3.7 6
Aşırı yükleme (overloading): aynı adlı birden fazla metot, parametre listeleri farklı olduğu sürece aynı sınıfta bulunabilir.
- Farklılık: parametre sayısı, tipi ya da sırası.
- Derleyici, çağrıdaki argümanlara bakarak hangi metodun çalışacağına derleme zamanında karar verir.
- Yalnızca dönüş tipi farklı olan iki metot aşırı yükleme değildir:
method topla(int,int) is already definedhatası verir. printlnda aşırı yüklenmiştir:println(int),println(String),println(double)…
Tanım ve Çağrı · Adım adım kod izleme
Hangi topla Çalışır? Adım Adım
Aynı adlı üç topla var. İlk çağrının argümanları (int, int): üç parametreli sürüm elenir; (int, int) tam eşleşme olduğu için o seçilir.
topla(int, int) çalışır: a = 4, b = 6.
10 döner ve yazdırılır.
(int, double): 2.5 int'e örtük dönüşemez, (int, int) elenir. 4, 4.0'a genişletilir → topla(double, double).
a = 4.0, b = 2.5: parametreler double.
6.5 döner ve yazdırılır.
Üç argüman: yalnızca üç parametreli sürüm uyar.
a = 7, b = 1, c = 2.
10 döner ve yazdırılır.
(char, int): char hem int'e hem double'a genişleyebilir; derleyici en özel olanı, (int, int)'i seçer.
'A' → 65: a = 65, b = 1.
66 döner ve yazdırılır. Seçim derleme zamanında, yalnızca argüman tiplerine bakılarak yapılır.
static int topla(int a, int b) { return a + b; } static double topla(double a, double b) { return a + b; } static int topla(int a, int b, int c) { return a + b + c; } public static void main(String[] args) { System.out.println(topla(4, 6)); System.out.println(topla(4, 2.5)); System.out.println(topla(7, 1, 2)); System.out.println(topla('A', 1)); }
Fonksiyon İçinde Fonksiyon
Fonksiyon İçinde Fonksiyon
public class IcIce { public static int kareAl(int sayi) { return sayi * sayi; } public static int topla(int sayi1, int sayi2) { return sayi1 + sayi2; } public static int ikiKareToplami(int sayi1, int sayi2) { return topla(kareAl(sayi1), kareAl(sayi2)); } public static void main(String[] args) { int sonuc = ikiKareToplami(3, 4); System.out.println(sonuc); } }
25
- Bir fonksiyon, başka bir fonksiyonu çağırabilir.
- Karmaşık görev küçük parçalara bölünür:
ikiKareToplami, işikareAlvetopla'ya yaptırır. - Kod okunabilir ve yönetilebilir olur; her parça ayrı ayrı test edilebilir.
topla(kareAl(sayi1), kareAl(sayi2))ifadesinde önce argümanlar hesaplanır (soldan sağa), sonra dış çağrı yapılır.
Fonksiyon İçinde Fonksiyon · Adım adım kod izleme
ikiKareToplami(3, 4): Çağrı Yığını
main, ikiKareToplami(3, 4) çağrısını yapar.
topla çağrılmadan önce argümanları hesaplanmalı: önce kareAl(sayi1).
Üçüncü çerçeve açılır: kareAl(3) → 3 × 3 = 9 döner.
kareAl çerçevesi kapandı; ilk argüman (arg1) = 9. Sıradaki: kareAl(sayi2).
kareAl(4) → 4 × 4 = 16 döner.
Argümanlar hazır: topla(9, 16) çağrılır → 25. Buradaki sayi1 = 9; ikiKareToplami'nınki hâlâ 3.
topla'nın sonucu, ikiKareToplami'nın dönüş değeri olur: 25 döner.
main'e dönüldü: sonuc = 25.
Ekrana 25 yazılır. En fazla 3 çerçeve aynı anda yığındaydı.
static int kareAl(int sayi) { return sayi * sayi; } static int topla(int sayi1, int sayi2) { return sayi1 + sayi2; } static int ikiKareToplami(int sayi1, int sayi2) { return topla(kareAl(sayi1), kareAl(sayi2)); } public static void main(String[] args) { int sonuc = ikiKareToplami(3, 4); System.out.println(sonuc); }
Hazır Metotlar
En Sık Kullanılan Metotlar (Java API)
| Alan | Sınıflar | Örnek metotlar | Paket |
|---|---|---|---|
| Ekrana yazma | System.out | print, println, printf | java.lang |
| Matematik | Math | sqrt, abs, max, pow | java.lang |
| Metin | String | length, charAt, substring, equals | java.lang |
| Dizi | Arrays | sort, copyOf, binarySearch, equals | java.util |
| Kullanıcı girişi | Scanner | nextInt, nextLine, close | java.util |
| Dosya | File, FileWriter | createNewFile, write, close | java.io |
| Veri tabanı | DriverManager, Statement | getConnection, executeQuery, executeUpdate | java.sql |
| Veri yapıları | ArrayList | add, remove, get, size | java.util |
| Zaman | LocalDateTime, DateTimeFormatter | now, ofPattern, format | java.time |
| Web / grafik | URI, URL, JFrame | URI.create, openConnection, setVisible | java.net, javax.swing |
java.lang otomatik içe aktarılır; diğerleri için import gerekir, ör. import java.util.Scanner;
Hazır Metotlar
Ekrana Yazdırma
public class Yazdirma { public static void main(String[] args) { System.out.println("Merhaba, Dünya!"); System.out.print("Bir "); System.out.print("satır"); System.out.println(); int yas = 20; System.out.println("Yaş: " + yas); System.out.printf("Pi yaklaşık %.2f%n", Math.PI); } }
Merhaba, Dünya! Bir satır Yaş: 20 Pi yaklaşık 3,14
System.out.println(x): x'i yazar, alt satıra geçer.System.out.print(x): x'i yazar, aynı satırda kalır.+ile metin ve değer birleştirilir:"Yaş: " + yas.printf: biçimli yazma;%.2f2 ondalık basamak,%dtam sayı,%smetin,%nsatır sonu.printfyerel ayarı kullanır: Türkçe sistemde ondalık ayırıcı virgüldür (3,14).
Hazır Metotlar
Math Sınıfı
double kareKok = Math.sqrt(16); double mutlakDeger = Math.abs(-17.2); double maksimum = Math.max(3, 5); System.out.println(kareKok); System.out.println(mutlakDeger); System.out.println(maksimum); System.out.println(Math.pow(2, 10)); System.out.println(Math.round(2.6)); System.out.println(Math.min(-4, 7)); System.out.println(Math.max(3, 5));
Mathsınıfı matematiksel işlemler içindir; metotlarıstaticolduğundanMath.sqrt(16)biçiminde çağrılır.Math.max(3, 5)intdöndürür (5);doubledeğişkene atanınca 5.0 olur.sqrtvepowher zamandoubledöndürür.
4.0 17.2 5.0 1024.0 3 -4 5
Kapsam
Yerel Değişken
public int carpma(int sayi1, int sayi2) { int sonuc = sayi1 * sayi2; // 'sonuc' bir yerel değişkendir return sonuc; } public void baskaMetot() { carpma(2, 3); System.out.println(sonuc); // HATA }
error: cannot find symbol
System.out.println(sonuc);
^
symbol: variable sonuc- Yerel değişken (local variable): metodun ya da bloğun içinde tanımlanır; parametreler de yereldir.
- Yalnızca fonksiyon çalışırken var olur; fonksiyon dışından erişilemez.
sonuc, sadececarpmayürütülürken vardır; metot dönünce silinir.- Değeri dışarı taşımanın yolu
return:int s = carpma(2, 3);
Kapsam
Kapsam
Kapsam (scope), bir değişkenin tanımlandığı ve kullanılabildiği kod bölgesidir.
- Her değişkenin bir kapsamı vardır: Java'da kapsam, değişkenin tanımlandığı süslü parantez bloğudur.
- Kapsam, değişkenin erişilebilirliğini ve yaşam süresini belirler.
- Yerel ve genel (global) kapsamlar farklı erişim kurallarına sahiptir.
- İç içe kapsamda iç kapsam, üst kapsamdaki değişkenlere erişebilir; dış kapsam içtekini göremez.
- Aynı adın farklı kapsamlarda kullanılması isim çakışmasına yol açabilir; doğru kullanılmayan kapsam hatalara neden olur.
Kapsam
Yerel ve Global Kapsam
public class IcKapsam { static int globalDegisken = 10; // global (sınıf alanı) static void fonksiyon() { int disDegisken = 10; // yerel kapsam { int icDegisken = 5; // disDegisken ve icDegisken burada erişilebilir System.out.println(disDegisken + icDegisken + globalDegisken); } // icDegisken burada YOK } public static void main(String[] args) { fonksiyon(); } }
25
10 + 5 + 10 = 25: iç blok, hem metodun hem sınıfın değişkenlerini görür.
Metot ya da blok içinde; yaşam süresi o bloğun çalışma süresi kadar.
Her yerden erişilir, program boyunca yaşar. Java'da bu rolü sınıf alanları üstlenir.
Kapsam içinde kapsam; iç kapsam dıştakinin değişkenlerine erişir.
Kapsam
İsim Çakışması
Bloğun içinde aynı ad: hata
public void fonksiyon() { int disDegisken = 10; { int disDegisken = 5; // HATA } }
error: variable disDegisken is already
defined in method fonksiyon()Java, iç bloğun dıştaki yerel değişkenle aynı adı kullanmasına izin vermez.
Yerel değişken alanı gölgeler
public class Golge { static int deger = 10; // sınıf alanı static void goster() { int deger = 5; // alanı gölgeler System.out.println(deger); System.out.println(Golge.deger); } public static void main(String[] args) { goster(); System.out.println(deger); } }
5 10 10
Yerel deger, aynı adlı alanı gölgeler (shadowing); alana Golge.deger ile ulaşılır.
Kapsam · Adım adım kod izleme
Gölgeleme: Kodu Adım Adım İzle
Sınıf alanı deger = 10 program başlarken oluşur ve program boyunca yaşar. main, goster()'i çağırır.
goster için yeni bir çerçeve açılır; henüz yerel değişkeni yok.
Yerel deger = 5 tanımlanır. Aynı ad artık bu metot içinde yereli gösterir: alan gölgelendi.
deger adı önce en içteki kapsamda aranır → yerel 5 yazdırılır.
Golge.deger sınıf adıyla alana ulaşır → 10.
goster bitti, yerel deger silindi. main'de yerel deger yok: ad alanı gösterir → 10.
public class Golge { static int deger = 10; // sınıf alanı static void goster() { int deger = 5; // alanı gölgeler System.out.println(deger); System.out.println(Golge.deger); } public static void main(String[] args) { goster(); System.out.println(deger); } }
Kapsam · Adım adım kod izleme
Değişkenler Ne Zaman Doğar, Ne Zaman Ölür?
Sınıf alanı cagriSayisi program başında oluşur ve program boyunca yaşar. carpma(2, 3) çağrılıyor.
Metot, sınıf alanına erişebilir: cagriSayisi 1 olur.
Yerel sonuc şimdi doğar: 6.
carpma döndü: sayi1, sayi2, sonuc yok oldu. Değer, ilk'e atandı.
Yeni çerçeve: sonuc = 24, sayaç 2.
ikinci yalnızca iç blokta yaşayan bir yerel değişkendir.
Blok içinde ikinci erişilebilir: 24 yazılır.
Blok bitti, ikinci yok oldu: 6 2.
static int cagriSayisi = 0; // sınıf alanı static int carpma(int sayi1, int sayi2) { cagriSayisi++; int sonuc = sayi1 * sayi2; return sonuc; } public static void main(String[] args) { int ilk = carpma(2, 3); { int ikinci = carpma(ilk, 4); System.out.println(ikinci); } System.out.println(ilk + " " + cagriSayisi); }
Soyutlama ve Tasarım
Soyutlama
Soyutlama (abstraction), karmaşıklığı azaltmak için ayrıntıları yok saymaktır.
Kodun okunabilirliğini artırır, işlemi basitleştirir; büyük ve karmaşık programları anlaşılır kılar.
Kodu parçalara ayırır; her parça ayrı ayrı düşünülür. Bir metodu kullanan, onun içini bilmek zorunda değildir.
Günlük benzetme: arabayı sürmek için motorun içini bilmek gerekmez; direksiyon ve pedallar bir "arayüzdür".
Soyutlama ve Tasarım
Fonksiyonel Soyutlama
Hesaplamalar üzerinde soyutlama, işlevsel ya da yordamsal soyutlama (procedural abstraction) olarak da bilinir.
- Bir fonksiyonun nasıl hesapladığından çok ne hesapladığını bilmek önemlidir.
- Görevi bilindiği sürece, nasıl yaptığı umursanmaz.
- Fonksiyonun gerçeklemesi (gövdesi) hakkında endişelenilmez.
- Gövde değişse bile (daha hızlı bir algoritma), çağıran kod aynı kalır.
System.out.println("Merhaba");Fonksiyon, verilen metni konsola yazar; bunu nasıl yaptığını (karakter kodlama, işletim sistemi çağrıları…) bilmek gerekmez.
// Kullanan yalnızca imzayı bilir: static boolean asalMi(int sayi) // "sayi asal ise true döner" if (asalMi(17)) { ... }
Soyutlama ve Tasarım
Genelleme
Bağlam (context):
- bir sayının, bir denklem içindeki diğer unsurlarla ilişkisi,
- bir kelimenin anlamının cümledeki yeri ve durumuyla ilişkisi,
- bir kod bloğu içindeki durum ve etkileşimler.
Bir ifadenin anlamı, çevresindeki diğer kelimelerden etkilenebilir.
Genelleme (generalization):
- bir bağlama ait bir çözümü başka bağlamlara uygun hâle getirmek,
- bir ürünü daha genel ve çok amaçlı kullanılabilir yapmak.
Kodda genellemenin aracı parametredir: sabit değerler parametreye dönüşür.
public class Genelleme { // Özel: yalnızca 10 tane '-' yazar static void cizgiCiz() { System.out.println("----------"); } // Genel: uzunluğu ve karakteri parametre static void cizgiCiz(int uzunluk, char karakter) { for (int i = 0; i < uzunluk; i++) { System.out.print(karakter); } System.out.println(); } public static void main(String[] args) { cizgiCiz(); cizgiCiz(5, '*'); cizgiCiz(12, '='); } }
---------- ***** ============
Soyutlama ve Tasarım
Ayrıştırma
Problemi küçük parçalara ayırmak (decomposition), programlamanın temel adımıdır. Her parça bir fonksiyon olur: kod düzenli, okunur, yeniden kullanılabilir ve sürdürülebilir olur.
// notlariOku ve harfNotu da ayrı metotlardır static double ortalamaHesapla(int[] notlar) { int toplam = 0; for (int n : notlar) { toplam += n; } return (double) toplam / notlar.length; } public static void main(String[] args) { Scanner giris = new Scanner(System.in); int[] notlar = notlariOku(giris, 3); double ort = ortalamaHesapla(notlar); System.out.println("Ortalama: " + ort + " -> " + harfNotu(ort)); }
Ortalama: 81.66666666666667 -> BB
main bir "içindekiler" gibi okunur: ne yapıldığı görünür, nasıl yapıldığı alt fonksiyonlardadır.
Soyutlama ve Tasarım
Ne Zaman Fonksiyon?
Bir kural: DRY (Don't Repeat Yourself, kendini tekrar etme). Kodu kopyalayıp yapıştırma ihtiyacı doğduğu an, o kod bir fonksiyon olmaya adaydır.
Tekrarlı kod
double ort1 = (70 + 80 + 90) / 3.0; System.out.println(ort1); double ort2 = (55 + 60 + 100) / 3.0; System.out.println(ort2); // formül değişirse her yerde // ayrı ayrı düzeltmek gerekir
Fonksiyonla
static double ortalama(int a, int b, int c) { return (a + b + c) / 3.0; } System.out.println(ortalama(70, 80, 90)); System.out.println(ortalama(55, 60, 100));
80.0 71.66666666666667
Tekrar kullanılabilirlik ve bakım kolaylığı için önemlidir. İyi bir fonksiyon tek bir işi yapar ve okunaklıdır.
Soyutlama ve Tasarım
İyi Fonksiyon Tasarımı
Her fonksiyon yalnızca bir işi yapmalı. "ve" ile anlatılıyorsa (oku ve hesapla ve yazdır) bölünmeli.
Ne yaptığını anlatan fiil: ortalamaHesapla, asalMi, notlariOku. islem2 gibi isimler bir şey anlatmaz.
Gerekli verileri parametrelerle almalı; gizlice dış değişkenlere bağlı olmamalı. Az sayıda parametre okunurluğu artırır.
Sonucu açıkça return ile döndürmeli. Hesaplayan metot yazdırmamalı; yazdırma işini çağıran yapsın.
Bir ekrana sığan, birkaç satırlık fonksiyonlar anlaşılır ve kolay test edilir.
Fonksiyon yalnızca gerektiği yerde çağrılmalı; aynı sonucu döngüde tekrar tekrar hesaplamak gereksiz iştir.
Soyutlama ve Tasarım
Değişken Adlandırma
Her değişken tek bir şeyi temsil etmeli
- Bir değişken yalnızca bir nesneyi ya da bir veriyi tutmalı; aynı değişkenin önce yaş, sonra toplam için kullanılması kafa karıştırır.
- Kodun okunurluğunu ve yeniden kullanılabilirliğini artırır, mantıksal hataları azaltır.
İyi isim
- Açıklayıcı ve anlamlı olmalı; temsil ettiği verinin doğasını yansıtmalı.
- İçeriği ve kullanımı anlatmalı; anlamsız ya da tek harfli isimler okunurluğu düşürür (döngü sayacı
ive matematiktekixistisnadır). - Java geleneği: camelCase (
ogrenciSayisi), sınıflar büyük harfle (Kitap), sabitlerMAKS_DEGER.
int ogrenciSayisi; // iyi bir adlandırma int a; // anlamsız bir isim int yas = 25; String isim = "Ahmet"; double ortalama = 85.5; String kitapAdi;
| Kötü | İyi |
|---|---|
int x1, x2; | int vizeNotu, finalNotu; |
double d; | double daireAlani; |
boolean f; | boolean asalMi; |
Özet
Özet
| Konu | Hatırlanacaklar |
|---|---|
| Tanım | erişim [static] dönüşTürü ad(parametreler) { gövde }; imza = ad + parametre tipleri |
| Çağrı | argümanlar parametrelere kopyalanır (değer ile aktarım); her çağrı yığında yeni bir çerçeve açar |
| return / void | return değeri verir ve metodu bitirir; void değer döndürmez |
| static | static metot doğrudan / Sinif.metot(); değilse nesne.metot() |
| Aşırı yükleme | aynı ad, farklı parametre listesi; seçim derleme zamanında |
| Hazır metotlar | System.out, Math (static: Math.sqrt(16)); java.lang dışındakiler import ister |
| Kapsam | değişken tanımlandığı blokta yaşar; iç blok dışı görür, tersi değil; alanlar program boyunca |
| Tasarım | soyutlama (ne, nasıl değil), genelleme (parametre), ayrıştırma, DRY, tek sorumluluk |
Özet
İlgili Sayfalar
Simülatör: metoda ilkel değer, dizi ve nesne referansı geçirmek; çağrı yığını çerçeveleri ve heap nesneleri adım adım.
Asal sayı, kombinasyon, öğrenci numarası çözme gibi problemler; çağrı yığını ve gölgeleme izlemeleri.
Özet
Sık Yapılan Hatalar (1)
non-static method toplama(int,int) cannot be referenced from a static contextÇözüm: metot static yapılır ya da bir nesne oluşturulup onun üzerinden çağrılır.missing return statementif/else if zincirinde her olasılık bir return ile bitmeli; sona varsayılan bir return konur.incompatible types: void cannot be converted to intint x = selamla(); olmaz: void metot değer üretmez.method toplama in class ... cannot be applied to given types; required: int,int found: intArgüman sayısı ve tipleri imzayla aynı olmalı.Özet
Sık Yapılan Hatalar (2)
cannot find symbol … variable sonucDeğer return ile döndürülür.variable disDegisken is already defined in method fonksiyon()yerDegistir(int x, int y) yalnızca kopyaları takas eder; yerDegistir(dizi[0], dizi[2]) sonrası dizi aynı kalır. Dizi hücreleri için yerDegistir(int[] d, int i, int j).int f(int a) ve double f(int a) birlikte olamaz: method f(int) is already defined. İmzayı yalnız ad ve parametre tipleri belirler.arttir(sayi) sonrası sayi aynı kalır: kopya değişir. Yeni değer return ile döner.int k = Math.sqrt(16); → possible lossy conversion from double to int. sqrt ve pow double döndürür.Özet
Örnek Problemler (1)
static int f(int x) { x = x * 2; return x + 1; } public static void main(String[] args) { int a = 3; int b = f(a); System.out.println(a + " " + b); System.out.println(f(f(1))); }
static int kare(int n) { return n * n; } static int kup(int n) { return n * kare(n); } // main içinde: System.out.println(kup(2) + kare(3));
- Soldaki program ne yazdırır?
aneden değişmedi? - Sağdaki satır ne yazdırır?
kup(2)çalışırken yığında en çok kaç çerçeve olur (main dahil)?
Cevapları göster
- 3 7 ve 7.
f, a'nın kopyasını ikiye katlar; a = 3 kalır. f(f(1)) = f(3) = 7. - 8 + 9 = 17. main → kup(2) → kare(2): en çok 3 çerçeve.
Özet
Örnek Problemler (2)
static int topla(int a, int b) { return a + b; } static double topla(double a, double b) { return a + b; } // main içinde: System.out.println(topla(2, 3.0)); System.out.println(topla(2, 3)); System.out.println(Math.max(Math.abs(-8), Math.sqrt(49)));
- İlk iki
printlnhangitoplametodunu çağırır, ne yazdırır? - Son satır neden
8değil de8.0yazdırır?
Cevapları göster
topla(2, 3.0)→ double sürümü (2, double'a genişler): 5.0;topla(2, 3)→ int sürümü: 5.Math.sqrtdouble döndürür;max(int, double)double sürümünü seçer: 8.0.
Özet
Alıştırmalar
boolean ciftMi(int sayi): sayı çiftsetruedöndürsün.int enBuyuk(int a, int b, int c): üç sayının en büyüğünüMath.maxile bulsun.int usAl(int taban, int us): döngüyle üs hesaplasın (Math.powkullanmadan).int basamakToplami(int n): sayının rakamları toplamını döngüyle bulsun.double daireAlani(double r)yazın; sonucuprintfile 2 basamak yazdırın.- Aşırı yüklenmiş
double alan(double r)(daire) vedouble alan(double en, double boy)(dikdörtgen).
Cevaplar / ipuçları
return sayi % 2 == 0;→ ciftMi(7) = false, ciftMi(10) = true.return Math.max(a, Math.max(b, c));→ enBuyuk(4, 9, 2) = 9.int sonuc = 1; for (int i = 0; i < us; i++) sonuc *= taban; return sonuc;→ usAl(2, 10) = 1024.while (n != 0) { t += n % 10; n /= 10; }→ basamakToplami(2024) = 8.return Math.PI * r * r;→printf("%.2f%n", daireAlani(2))→ 12,57.alan(1)→ 3.14159…;alan(3, 4)→ 12.0. Hangi sürümün çağrılacağını argüman sayısı belirler.
Özet
Kaynaklar
- Oracle, The Java Tutorials: "Defining Methods", "Passing Information to a Method or a Constructor".
- J. Gosling ve diğ., The Java Language Specification, Java SE 21 Edition (Bölüm 8.4 Method Declarations, 6.3 Scope).
- P. Deitel ve H. Deitel, Java: How to Program, Early Objects, 11. baskı, Pearson, 2017 (Bölüm 6: Methods).
- K. Sierra ve B. Bates, Head First Java, 3. baskı, O'Reilly, 2022.
- C. S. Horstmann, Core Java, Volume I: Fundamentals, 12. baskı, 2022.
- A. B. Downey ve C. Mayfield, Think Java, 2. baskı, O'Reilly, 2019 (Bölüm 4: Methods and Testing).