Bölüm 4: Nesne ve Sınıflar
Giriş
Öğrenme Çıktıları
Sınıfı bir taslak, nesneyi o taslaktan üretilmiş somut bir örnek olarak açıklamak; nitelik ve metotlarıyla bir sınıf yazmak.
new işlecini ve yapıcı metotları (constructor) kullanmak; varsayılan değerleri ve varsayılan yapıcıyı bilmek.
Örneğe ait ve static nitelik/metotları ayırt etmek; başlatıcı bloklarının çalışma sırasını izlemek.
Değişkenin nesneyi değil referansı tuttuğunu bellek çizimiyle göstermek; this, == ve equals farkını açıklamak.
Erişim düzenleyicileri, erişimci (get) ve değiştirici (set) metotlarla veri gizlemeyi uygulamak.
Wrapper sınıfları, record, enum ve iç sınıfları tanımak; iyi bir sınıf tasarımının üç unsurunu açıklamak.
Nesne Yönelimli Programlama
Nesne Yönelimli Programlama
- Nesne yönelimli programlama (Object-Oriented Programming, OOP), programı birbiriyle etkileşen nesneler olarak kuran bir yaklaşımdır.
- Nesne (object), gerçek dünyada açıkça tanımlanabilen bir varlığı temsil eder: bir öğrenci, bir masa, bir çember, ekrandaki bir düğme, hatta bir kredi.
- Her nesnenin durumu (verileri) ve davranışı (yapabildikleri) vardır.
| Nesne | Nitelikler (durum) | Davranışlar |
|---|---|---|
| Öğrenci | ad, numara, bölüm | derseKaydol(), notGor() |
| Masa | en, boy, malzeme | tasi() |
| Çember | merkez, yarıçap | alan(), cevre() |
| Düğme | yazı, renk, etkin mi | tikla() |
| Kredi | tutar, faiz, vade | taksitHesapla() |
Nesne Yönelimli Programlama
Nesneler: Nitelik ve Davranış
- Bir sınıfın üyeleri (members) vardır: nitelikler (fields), metotlar (methods) ve yapıcılar (constructors).
- Nesneler veri saklar: bu veri parçalarına nitelik (alan, field) denir.
- Nesneler işlem yapar: bu işlemlere davranış (metot, method) denir.
- Veriyi ve o veri üzerinde çalışan kodu bir araya getirmek, programı daha düzenli, yeniden kullanılabilir ve sezgisel yapar.
Nesne Yönelimli Programlama
Prosedürel ve Nesne Yönelimli
| Prosedürel (yordamsal) yaklaşım | Nesne yönelimli yaklaşım | |
|---|---|---|
| Temel birim | Fonksiyon (metot) | Nesne (veri + metotlar) |
| Veri | Ayrı değişkenlerde; her fonksiyon erişebilir | Nesnenin içinde; dışarıya kontrollü açılır |
| Örnek | alanHesapla(en, boy) | dikdortgen.alanHesapla() |
| Büyük programlar | Değişiklik birçok fonksiyonu etkiler | Değişiklik çoğunlukla bir sınıfın içinde kalır |
| Yeniden kullanım | Fonksiyonları kopyalayarak | Sınıfları kullanarak ve kalıtımla |
Şimdiye kadar yazdığımız static metotlu programlar prosedürel tarzdaydı. Java'da her kod bir sınıfın içindedir; bu bölümde sınıfları nesne üretmek için kullanmaya başlıyoruz.
Nesne Yönelimli Programlama
Üç Temel Özellik
Nesne, nitelik ve davranışlarının ayrıntısını diğer nesnelerden gizleyebilir. Dışarıya karşı kapalı bir kutu gibidir; yalnızca izin verilen metotlarla kullanılır.
Bir sınıf, başka bir sınıfın nitelik ve metotlarını miras alabilir. Kodun yeniden kullanımını ve sınıf hiyerarşisini sağlar.
Bir nesne birden fazla biçim (tür) alabilir; aynı çağrı farklı nesnelerde farklı davranır. Esneklik ve dinamik davranış sağlar.
Sınıf ve Nesne
Sınıf: Nesnenin Taslağı
- Sınıf (class), bir nesnenin taslağıdır (blueprint); bir sınıftan farklı verileri taşıyan birçok nesne üretilebilir.
- Sınıf, nesnenin taşıyacağı verileri (nitelikler) ve yapabileceği işlemleri (metotlar) belirtir.
- Bir nesne, bir sınıfın örneğidir (instance): sınıfın bellekteki somut hâlidir.
- Sınıflar, gerçek dünyadaki varlıkları modellemeyi sağlar: bir
Arabasınıfı her otomobili temsil edebilir; her marka ve model bu sınıftan üretilen bir nesnedir.
Benzetme: sınıf kurabiye kalıbı, nesneler o kalıpla kesilen kurabiyelerdir.
Sınıf ve Nesne
Örnek: Araba Sınıfı
Marka, Model, Yıl, Renk
Hareket et (ilerle), Dur, Sinyal ver
Aynı sınıftan üretilen iki nesne aynı nitelik adlarına ama farklı değerlere sahiptir.
UML sınıf diyagramı: ad / nitelikler / metotlar; - private, + public. Nesne adları altı çizili yazılır.
Sınıf ve Nesne
Sınıf Tanımlama
public class Araba { // Nitelikler (fields) String marka; String model; int yil; String renk; // Metotlar (methods) void ilerle() { System.out.println(marka + " ilerliyor."); } void dur() { System.out.println(marka + " durdu."); } void sinyalVer() { System.out.println(marka + " sinyal veriyor."); } }
classanahtar kelimesi ve sınıf adıyla başlar; gövde{ }arasındadır.- Sınıf adı büyük harfle başlar (
Araba,BankaHesabi);publicbir sınıf, aynı adlı dosyada (Araba.java) bulunmalıdır. - Nitelikler sınıf gövdesinde, metotların dışında tanımlanır; her metot bu nitelikleri doğrudan kullanabilir.
- Metotların önünde
staticyok: her biri belirli bir arabanın (nesnenin) metodudur. - Bu sınıfta
mainyok; tek başına çalışmaz, başka bir sınıf onu kullanır.
Sınıf ve Nesne
Sınıfın Kullanımı
public class AracTesti { public static void main(String[] args) { Araba araba1 = new Araba(); araba1.marka = "Toyota"; araba1.model = "Corolla"; araba1.yil = 2022; araba1.renk = "Gri"; Araba araba2 = new Araba(); araba2.marka = "Ford"; araba2.model = "Mustang"; araba2.yil = 2023; araba2.renk = "Mavi"; araba1.ilerle(); araba2.sinyalVer(); araba1.dur(); } }
Toyota ilerliyor. Ford sinyal veriyor. Toyota durdu.
new Araba()bir nesne üretir;araba1onu gösterir.araba1.marka = "Toyota";: nokta (.) ile nesnenin niteliğine erişilir.araba1.ilerle(): metot, araba1'in verileriyle çalışır;araba2.sinyalVer()ise araba2'ninkilerle.- Nitelikleri dışarıdan böyle doğrudan değiştirmek iyi bir alışkanlık değildir; doğrusu yapıcı ve erişim metotları kullanmaktır.
Sınıf ve Nesne
Sınıfın Üyeleri
Nesnelerin taşıyabileceği verileri temsil eder. Örnek: bir Ogrenci sınıfında ad ve soyad.
Nesnelerin gerçekleştirebileceği işlemleri tanımlar. Örnek: bir Kopek sınıfında havla() ve kos().
Her üye private, protected, varsayılan (yazılmaz) veya public olabilir: kimin kullanabileceğini belirler.
Her üye nesneye ait (instance, varsayılan) veya static ile sınıfa ait olabilir.
Yapıcı metotlar da sınıfın içinde yazılır; ama yalnızca nesne oluşturulurken çalışırlar ve teknik olarak metot değil, ayrı bir üye türüdür. Sınıfın içinde başka sınıflar (iç sınıflar) da tanımlanabilir.
Sınıf ve Nesne
Erişim Düzenleyiciler
Erişim düzenleyiciler (access modifiers), bir sınıfa ve üyelerine sınıfın dışından nasıl erişilebileceğini belirtir.
| Düzenleyici | Anlamı | Aynı sınıf | Aynı paket | Alt sınıf (başka paket) | Her yer |
|---|---|---|---|---|---|
public | herkese açık | ✓ | ✓ | ✓ | ✓ |
protected | korumalı | ✓ | ✓ | ✓ | ✗ |
| (yazılmaz) varsayılan | paket düzeyi (package-private) | ✓ | ✓ | ✗ | ✗ |
private | özel | ✓ | ✗ | ✗ | ✗ |
- Paket (package), birbiriyle ilgili sınıfların bulunduğu klasördür (
package objects;). - Varsayılan erişim için bir anahtar kelime yoktur:
defaultyazılmaz, hiçbir şey yazılmaz. - Genel kural: nitelikler
private, dışarıya sunulan metotlarpublic.
Yapıcı Metotlar
Yapıcı Metotlar
- Yapıcı metot (constructor), nesne oluşturmak için kullanılan özel bir metottur;
newile nesne oluşturulduğunda otomatik çağrılır. - Görevi, niteliklere ilk değerlerini vermek ve varsa başka hazırlık işlerini yapmaktır.
- Adı sınıf adıyla aynıdır (büyük-küçük harf dahil).
- Dönüş türü yoktur,
voidbile yazılmaz; değer döndüremez. - Genellikle
publictanımlanır; nesne oluşturmayı kısıtlamak içinprivateda olabilir (bkz. singleton). - Bir sınıfın birden çok yapıcısı olabilir (farklı parametrelerle).
public class Ogrenci { private String ad; private int numara; // Yapıcı: sınıfla aynı ad, dönüş türü yok public Ogrenci(String ad, int numara) { this.ad = ad; this.numara = numara; } } // Kullanımı: Ogrenci ogr = new Ogrenci("Ali", 2012);
Yapıcı Metotlar
Nesne Nasıl Oluşturulur?
SinifAdi nesneAdi = new SinifAdi(parametreler); Araba corolla = new Araba("Toyota", "Corolla", 2022); Scanner klavye = new Scanner(System.in); Kitap kitap = new Kitap();
import java.util.Scanner; public class Olusturma { public static void main(String[] args) { Scanner klavye = new Scanner(System.in); StringBuilder metin = new StringBuilder("Java"); String baslik = "Nesneler"; // kısayol String yazar = new String("Sercan"); // uzun yol metin.append(" 21"); System.out.println(metin + " / " + baslik); System.out.println(yazar.length()); System.out.println(klavye.nextInt() * 2); } }
Kısayol: String baslik = "Nesneler"; String nesnesi oluşturur; yalnızca String baslik; ise sadece referans tanımlar.
new, öbekte (heap) nesne için yer ayırır; nitelikler varsayılan değerleri alır.- Yapıcı metot çağrılır, ilk değerleri verir.
newifadesinin sonucu nesnenin referansıdır; değişkene atanır.
(girdi: 21) Java 21 / Nesneler 6 42
Yapıcı Metotlar
Yapıcı Örneği: Araba
public class Araba { private String model; private String renk; public Araba(String model, String renk) { this.model = model; this.renk = renk; } public void bilgiYazdir() { System.out.println(model + " - " + renk); } }
public static void main(String[] args) { Araba sporAraba = new Araba("2022", "KIRMIZI"); Araba klasikAraba = new Araba("2023", "BEYAZ"); sporAraba.bilgiYazdir(); klasikAraba.bilgiYazdir(); }
2022 - KIRMIZI 2023 - BEYAZ
Yapıcı Metotlar
Referanslar
- Bir nesne doğrudan kullanılamaz; ona yalnızca referans (reference, başvuru) ile erişilir. Değişkenlerde nesnenin kendisi değil, referansı saklanır.
- Referans, nesnenin bellekte nerede olduğunu gösteren bir adres gibi düşünülebilir.
int,double,booleangibi temel türlü değişkenler değeri kendileri tutar; sınıf türünden değişkenler (Araba,String,Scanner) referans tutar.- Hiçbir nesneyi göstermeyen referansın değeri
null'dır.
Yerel değişkenler yığında (stack), nesneler öbekte (heap) bulunur; ok = referans.
Yapıcı Metotlar · Kodu adım adım çalıştır
new Araba(...): Adım Adım
new öbekte yeni bir nesne ayırır; String nitelikler önce varsayılan değer null alır.
Yapıcı çağrılır: parametreler argümanların kopyasını alır, this yeni nesneyi gösterir.
this.model = model: soldaki nesnenin niteliği, sağdaki parametredir.
this.renk = renk: nesne artık hazır.
Yapıcı biter, çerçevesi silinir. new ifadesinin değeri olan referans sporAraba'ya atanır.
Aynı adımlar ikinci kez: ayrı bir nesne oluşur, kendi model ve renk kopyalarıyla.
sporAraba.bilgiYazdir(): metotta this = #1, bu yüzden #1'in alanları yazılır.
Aynı metot, bu kez this = #2. Kod tek, veriler nesne başına ayrıdır.
public class Araba { private String model; private String renk; public Araba(String model, String renk) { this.model = model; this.renk = renk; } public void bilgiYazdir() { System.out.println(model + " - " + renk); } public static void main(String[] args) { Araba sporAraba = new Araba("2022", "KIRMIZI"); Araba klasikAraba = new Araba("2023", "BEYAZ"); sporAraba.bilgiYazdir(); klasikAraba.bilgiYazdir(); } }
Yapıcı Metotlar
Varsayılan Yapıcı Metot
- Sınıfa hiç yapıcı yazılmamışsa derleyici varsayılan yapıcıyı (default constructor) ekler: parametresiz, gövdesi boş. Nesne oluşturulurken her zaman bir yapıcı çağrılır.
- Değer verilmeyen nitelikler varsayılan değer alır (yerel değişkenler almaz):
| Nitelik türü | Varsayılan değer |
|---|---|
byte short int long | 0 |
float double | 0.0 |
boolean | false |
char | '\u0000' (kod 0) |
Referans (String, diziler, nesneler) | null |
class Nokta3 { int x; double agirlik; boolean gorunur; char harf; String ad; } public class Varsayilan { public static void main(String[] args) { Nokta3 n = new Nokta3(); // varsayılan yapıcı System.out.println(n.x + " " + n.agirlik); System.out.println(n.gorunur + " " + n.ad); System.out.println((int) n.harf); } }
0 0.0 false null 0
Yapıcı Metotlar
Parametresiz ve Parametreli Yapıcı
public class Arac { private String marka; private String model; private int yil; public Arac() { // parametresiz yapıcı marka = "Bilinmiyor"; model = "Bilinmiyor"; yil = 0; } public Arac(String marka, String model, int yil) { this.marka = marka; this.model = model; this.yil = yil; } public void bilgiYazdir() { System.out.println(marka + " " + model + " " + yil); } public static void main(String[] args) { Arac a1 = new Arac(); Arac a2 = new Arac("Renault", "Clio", 2021); a1.bilgiYazdir(); a2.bilgiYazdir(); } }
Bilinmiyor Bilinmiyor 0 Renault Clio 2021
Arac(), kendi yazdığımız parametresiz yapıcıdır; nitelikleri anlamlı başlangıç değerlerine ayarlar.- İki yapıcı aynı adı taşır, parametreleri farklıdır: yapıcı aşırı yükleme. Hangisinin çalışacağını argümanlar belirler.
- Sınıfa herhangi bir yapıcı yazıldığında derleyici artık varsayılan yapıcı eklemez. Yalnızca parametreli yapıcı varsa
new Arac()derlenmez.
Nitelikler
Nitelikler ve Türleri
Nitelikler, sınıfın içinde (metotların dışında) tanımlanan veri değişkenleridir. İki temel türü vardır:
| Örneğe ait alan (instance field) | Sınıfa ait alan (static field) | |
|---|---|---|
| Tanım | private String ad; | private static int toplamHesapSayisi; |
| Kopya sayısı | Her nesnede ayrı bir kopya | Sınıfta tek kopya, tüm nesneler paylaşır |
| Ne zaman oluşur? | Her new ile | Sınıf belleğe yüklenirken, bir kez |
| Erişim | nesne.ad | SinifAdi.toplamHesapSayisi |
| Örnek | Ogrenci: ad, soyad | BankaHesabi: toplamHesapSayisi |
- Sabit (
final) alanlara değer bir kez verilir, sonra değiştirilemez. Sınıf sabitleri genelliklestatic finalve BÜYÜK_HARF yazılır:Math.PI. - Sınıfa ait başlatıcılar (
static { }) sınıf yüklenirken bir kez; örneğe ait başlatıcılar ({ }) her nesne oluşturulduğunda çalışır.
Nitelikler · Kodu adım adım çalıştır
static Sayaç: Adım Adım
Sınıf belleğe yüklenirken static alan bir kez oluşur ve 0 olur. Henüz hiç nesne yok.
İlk nesne: kendi hesapSahibi kopyası "Ali" olur; ortak sayaç 1'e çıkar.
h1 birinci nesneyi gösterir.
İkinci nesnenin ayrı bir hesapSahibi alanı var; sayaç ise aynı alan: 2.
Üç nesne, üç hesapSahibi; ama tek toplamHesapSayisi = 3.
h2.hesapSahibi: örnek alanı nesne üzerinden okunur.
static metot sınıf adıyla çağrılır; this'i yoktur, yalnızca static alanı okur.
Dönen 3, sayi'ya atanır ve yazdırılır.
public class BankaHesabi { private String hesapSahibi; private static int toplamHesapSayisi = 0; public BankaHesabi(String hesapSahibi) { this.hesapSahibi = hesapSahibi; toplamHesapSayisi++; } public static int getToplamHesapSayisi() { return toplamHesapSayisi; } public static void main(String[] args) { BankaHesabi h1 = new BankaHesabi("Ali"); BankaHesabi h2 = new BankaHesabi("Ayşe"); BankaHesabi h3 = new BankaHesabi("Can"); System.out.println(h2.hesapSahibi); int sayi = BankaHesabi.getToplamHesapSayisi(); System.out.println(sayi); } }
Nitelikler
Nitelik Tanımlamaları
public class Kitap { // Örneğe ait nitelikler private String baslik; private String yazar; private int sayfaSayisi; // Sınıfa ait alan private static int toplamKitapSayisi; // final tanımlanmış bir alan (sabit) public static final double PI = 3.14159265359; }
public class Alanlar { public int a; // genel int b = 1, c = 2; // varsayılan (paket) private double x; // özel private static int xx; // statik, özel public static int y; // statik, genel public final int CONST1 = 5; // değiştirilemez private static final int CONST2 = 6; // statik sabit }
- Söz dizimi:
[erişim] [static] [final] tür ad [= ilkDeğer]; - Aynı satırda birden çok alan:
int b = 1, c = 2; PIburada örnek olarak tanımlandı; Java'da hazır bir sabit vardır:Math.PI.finalalana yeniden değer atamak derleme hatasıdır:error: cannot assign a value to final variable CONST1
Nitelikler
Başlatıcı Blokları
static { ... } bloğu, sınıf belleğe ilk kez yüklenirken, yalnızca bir kez çalışır. Static alanlara karmaşık ilk değer vermek için kullanılır.
{ ... } bloğu, her nesne oluşturulduğunda, yapıcının gövdesinden önce çalışır. Tüm yapıcılarda ortak olan işleri yapar.
static bloklar → (2) new ile bellek ayrılır, alanlar varsayılan değer alır → (3) alan ilk değerleri ve örnek başlatıcı blokları (yazılış sırasıyla) → (4) yapıcının gövdesi.Sonraki slayttaki Kopek sınıfında her ikisi de var; çıktının sırasını tahmin edip sonra adım adım izleyin. İpucu: havla()'nın döndürdüğü değer yazdırılmıyor; System.out.println(d2.havla()); yazılsaydı son satır "Gece haw haw haw!" olurdu.
Nitelikler · Kodu adım adım çalıştır
Kopek: Başlatıcı Sırası
main çalışmadan önce sınıf yüklenir: static blok bir kez çalışır. (var, Java 10+: türü sağdan çıkarır; String... = String[].)
new Kopek("Kara"): nesne için yer ayrılır, adi = null.
Yapıcının gövdesinden önce örnek başlatıcı bloğu çalışır.
Şimdi yapıcı gövdesi: this.adi = adi.
Yapıcı adı yazdırır: Kara.
İkinci nesne: başlatıcı + yapıcı yeniden; static blok tekrar çalışmaz.
havla() bir metin döndürür ama değer kullanılmıyor: hiçbir şey yazılmaz.
public class Kopek { String adi; // nitelik Kopek(String adi) { // yapıcı metot this.adi = adi; System.out.println(adi); } String havla() { // örneğe ait metot return adi + " haw haw haw!"; } static { // sınıfa ait başlatıcı System.out.println("Köpekler!"); } { // örneğe ait başlatıcı System.out.println("Köpek oluşturuluyor."); } public static void main(String... strings) { var d1 = new Kopek("Kara"); var d2 = new Kopek("Gece"); d2.havla(); } }
Metotlar
Metot Türleri
- Metotlar, sınıf içinde tanımlanan, belirli bir işi yapan kod bloklarıdır; sınıfın davranışını tanımlar.
- Örneğe ait metotlar (instance methods) bir nesneyle ilişkilidir:
telefon.aramaYap(...). O nesnenin niteliklerini kullanır. - Sınıfa ait metotlar (
static) sınıfın kendisiyle ilişkilidir, tüm nesnelerde ortaktır:CepTelefonuüzerinden. - Static metotlar belirli bir nesneye bağlı olmadığı için nesneye özgü verilere (
modelgibi) doğrudan erişemez.
public class CepTelefonu { private String model; private static String isletimSistemi = "Sürüm 1"; // Örneğe ait metot public void aramaYap(String numara) { System.out.println(model + " arıyor: " + numara); } // Örneğe ait metot public void mesajGonder(String alici, String mesaj) { System.out.println(alici + " <- " + mesaj); } // Sınıfa ait metot (static) public static void sistemiGuncelle(String yeniSurum) { isletimSistemi = yeniSurum; } }
Metotlar
Metot Tanımlama
- Metot, sınıf içinde belirli bir görevi yapan kod bloğudur; kodun tekrar kullanılmasını ve düzenini sağlar.
- Genel biçim:
[erişim] [dönüş türü] ad([parametreler])ve{ gövde }. - Ad + parametre türleri metodun imzasıdır (signature).
| Öğe | Belirlediği | Örnek |
|---|---|---|
| Erişim düzeyi (access modifier) | Başka sınıfların metoda nasıl erişebileceği | public, private, protected, varsayılan |
| Dönüş türü (return type) | Geri döndürülen değerin türü | int, String, void, bir sınıf |
| Metot adı (method name) | Çağırırken kullanılan ad | hesapla, verileriGoster, kameraAc |
| Parametreler (parameters) | Metoda aktarılan girdiler | int sayi1, int sayi2, String ad |
Metotlar
Metot Örneği: Eposta
public class Eposta { public boolean gonder(String alici, String konu, String icerik) { // Gerçek gönderim yerine bir benzetim if (alici == null || !alici.contains("@")) { return false; // başarısız } System.out.println(alici + " <- " + konu); return true; // başarılı } public static void main(String[] args) { Eposta e = new Eposta(); boolean s1 = e.gonder("ali@ornek.com", "Ödev", "Ek"); boolean s2 = e.gonder("ali.ornek.com", "Ödev", "Ek"); System.out.println(s1 + " " + s2); } }
- Ad:
gonder - Parametreler: üç
String: alıcı, konu, içerik - Dönüş türü:
boolean, gönderim başarılı mı?
ali@ornek.com <- Ödev true false
boolean döndüren metodun her yolu bir return ile bitmelidir; gövdesi yalnızca yorum olan bir metot missing return statement hatası verir.
Metotlar
Örneğe Ait Nitelikler ve Metotlar
- Sınıf içinde
staticanahtar kelimesi olmadan tanımlanırlar. - Her nesne, niteliklerin kendi kopyasına sahiptir; nesneler farklı verilere sahip olabilir.
- Nitelikler nesnenin özelliklerini, metotlar o nesnenin davranışını temsil eder.
- Kullanabilmek için önce nesne oluşturmak gerekir:
new, sonranesne.metot(). - Metot kodu tüm nesneler için tektir; her çağrıda hangi nesnenin verisiyle çalışacağını
thisbelirler.
| Örneğe ait | static | |
|---|---|---|
| Kime ait? | Nesneye | Sınıfa |
| Çağrı | nesne.metot() | Sinif.metot() |
| Nesne gerekir mi? | Evet | Hayır |
this var mı? | Evet | Hayır |
| Örnek | str.length() | Math.sqrt(x) |
Metotlar
Nokta Operatörü
public class Telefon { String numara; public Telefon(String numara) { this.numara = numara; } public void aramaYap(Telefon telefon) { System.out.println(numara + " arıyor: " + telefon.numara); } public void mesajGonder(Telefon telefon, String mesaj) { System.out.println(telefon.numara + " <- " + mesaj); } public void kameraAc() { System.out.println(numara + " kamera açtı."); } public static void main(String[] args) { Telefon telefon1 = new Telefon("5551234567"); Telefon telefon2 = new Telefon("5051234567"); telefon1.aramaYap(telefon2); telefon2.mesajGonder(telefon1, "Merhaba!"); telefon1.kameraAc(); } }
5551234567 arıyor: 5051234567 5551234567 <- Merhaba! 5551234567 kamera açtı.
- Nesne oluşturulduktan sonra nitelik ve metotlarına nokta operatörü ile erişilir:
nesne.metot(...),nesne.nitelik. telefon1.aramaYap(...): telefon1 arar; metottanumaratelefon1'in,telefon.numaratelefon2'nin numarasıdır.- Bir nesne başka bir nesneyi parametre olarak alabilir.
Metotlar
Dikdörtgen Sınıfı
public class Dikdortgen { private double uzunluk; // dikdörtgenin uzunluğu private double genislik; // dikdörtgenin genişliği // Yapıcı metot public Dikdortgen(double uzunluk, double genislik) { this.uzunluk = uzunluk; this.genislik = genislik; } public double alanHesapla() { // alanı hesaplar return uzunluk * genislik; } public double cevreHesapla() { // çevreyi hesaplar return 2 * (uzunluk + genislik); } }
- Nitelikler
private: dışarıdan yalnızca metotlarla kullanılır. - Yapıcı, iki kenarı alır ve nesneye kaydeder.
alanHesapla()vecevreHesapla()parametre almaz: ihtiyaç duydukları veriler nesnenin içinde.- Prosedürel karşılığı
alanHesapla(5.0, 3.0)olurdu; nesneyledikdortgen.alanHesapla().
Metotlar · Kodu adım adım çalıştır
Dikdörtgen: Adım Adım
İki nesne, her biri kendi uzunluk ve genislik değerleriyle.
dikdortgen.alanHesapla(): this = #1, sonuç 5.0 × 3.0 = 15.0.
alan = 15.0. cevreHesapla(): 2 × (5.0 + 3.0) = 16.0.
double değerler 15.0 biçiminde yazılır.
Aynı metotlar, bu kez this = #2 (kare): 25.0 ve 20.0. Eski değerlerin üzerine yazılır.
İkinci satır yazdırılır. Uzun bir deyim iki satıra bölünebilir; ; gelene kadar sürer.
public class DikdortgenTesti { public static void main(String[] args) { Dikdortgen dikdortgen = new Dikdortgen(5.0, 3.0); Dikdortgen kare = new Dikdortgen(5.0, 5.0); double alan = dikdortgen.alanHesapla(); double cevre = dikdortgen.cevreHesapla(); System.out.println("Alanı: " + alan + " Çevresi: " + cevre); alan = kare.alanHesapla(); cevre = kare.cevreHesapla(); System.out.println("Alanı: " + alan + " Çevresi: " + cevre); } }
Veri Gizleme
Erişimciler ve Değiştiriciler
public class BankaHesabi { private double hesapBakiyesi; private String hesapSahibi; // Erişimciler (get) public double getHesapBakiyesi() { return hesapBakiyesi; } public String getHesapSahibi() { return hesapSahibi; } // Değiştiriciler (set) public void setHesapSahibi(String sahip) { hesapSahibi = sahip; } public void setHesapBakiyesi(double yeniBakiye) { if (yeniBakiye >= 0) { // geçersizi reddet hesapBakiyesi = yeniBakiye; } } }
- Nitelikler, sınıf dışından doğrudan okunup değiştirilemesin diye
privatetanımlanır. - Erişimciler (accessors, getter): sınıfın dışından niteliklerin değerini okumak için; adı
get+ nitelik adı (boolean içinis...). - Değiştiriciler (mutators, setter): niteliklere değer atamak için; adı
set+ nitelik adı. - Değiştirici, değeri atamadan önce denetleyebilir: burada negatif bakiye reddedilir.
Veri Gizleme
get / set Kullanımı
BankaHesabi hesap = new BankaHesabi(); hesap.setHesapSahibi("Ayşe"); hesap.setHesapBakiyesi(1500.0); System.out.println(hesap.getHesapSahibi()); System.out.println(hesap.getHesapBakiyesi()); hesap.setHesapBakiyesi(-200); // reddedilir System.out.println(hesap.getHesapBakiyesi());
Ayşe 1500.0 1500.0
-200reddedildi: bakiye 1500.0 olarak kaldı. Nesne kendi verisini korur.- Alana doğrudan erişmeye çalışmak derlenmez:
BankaHesabi hesap = new BankaHesabi();
hesap.hesapBakiyesi = -500;error: hesapBakiyesi has private access in BankaHesabi
Veri Gizleme
Veri Gizleme
- Veri gizleme (data hiding), nesnenin verilerini korumaya ve onlara güvenli erişmeye yardımcı olur.
- Sınıfların dış dünyayla etkileşimini düzenler ve nesnenin bütünlüğünü korur (örneğin negatif bakiye olmaz).
- Bir nesnenin niteliklerine yalnızca kendi sınıfının metotları doğrudan erişip değişiklik yapabilir.
- Dışarıdan erişmek veya değiştirmek için sınıfın
publicmetotları kullanılır.
Veri gizleme, sarmalamanın (encapsulation) temelidir; bir sonraki bölümde ayrıntılı işlenir.
static Üyeler
Statik Değişkenler ve Metotlar
public class Matematik { // Statik toplama metodu public static int toplama(int sayi1, int sayi2) { return sayi1 + sayi2; } public static void main(String[] args) { int sonuc = Matematik.toplama(5, 3); System.out.println("Toplama Sonucu: " + sonuc); System.out.println(Math.max(4, 9)); System.out.println(Math.sqrt(16.0)); } }
staticanahtar kelimesiyle tanımlanır; sınıfa aittir.- Statik üyelere erişmek için nesne oluşturmaya gerek yoktur; sınıf adı ve nokta kullanılır:
SinifAdi.alanAdi,SinifAdi.metotAdi(argumanlar). - Nesne üzerinden de erişilebilir (
nesne.alanAdi), ama tercih edilmez: okuyan kişi üyenin nesneye ait olduğunu sanır. - Hazır örnekler:
Math.max(),Math.sqrt(),Math.PI,Integer.parseInt()vemain.
Toplama Sonucu: 8 9 4.0
static Üyeler
static Kuralları
| Nereden → | Örnek alan/metot kullanımı | static alan/metot kullanımı |
|---|---|---|
| Örneğe ait metottan | ✓ doğrudan (ad, this.ad) | ✓ doğrudan |
static metottan (main dahil) | ✗ ancak bir nesne üzerinden (ogr.ad) | ✓ doğrudan |
public class Selam { private String ad = "Ali"; public void selamVer() { System.out.println("Merhaba " + ad); } public static void main(String[] args) { selamVer(); } }
error: non-static method selamVer() cannot be referenced from a static context
public class Selam2 { private String ad = "Ali"; public static void yaz() { System.out.println(ad); } }
error: non-static variable ad cannot be referenced from a static context
Çözüm: nesne üzerinden çağırın (new Selam().selamVer();) ya da metodu static yapın.
Referanslar ve this
Referans Atama
- Java'da nesneler referanslar (adresler) aracılığıyla işlenir.
araba2 = araba1;nesneyi kopyalamaz, referansı kopyalar: iki değişken aynı nesneyi işaret eder (takma ad, alias).- Biri üzerinden yapılan değişiklik diğerinden de görünür.
public class Araba { private String marka; public Araba(String marka) { this.marka = marka; } public String getMarka() { return marka; } public void setMarka(String marka) { this.marka = marka; } }
Referanslar ve this · Kodu adım adım çalıştır
Referans Atama: Adım Adım
Bir nesne oluşturulur; araba1 onu gösterir.
araba2 = araba1: referans kopyalanır. Hâlâ tek nesne var.
İki değişken aynı nesneyi okur: ikisi de Toyota.
araba2.setMarka("Ford") ortak nesneyi değiştirir.
araba1 üzerinden okuyunca da Ford: değişiklik paylaşılır.
araba1 = null: yalnızca bu değişkenin bağı kopar; nesne silinmez, araba2 onu göstermeye devam eder.
Nesneyi gösteren son referans da kaybolursa nesne çöp toplayıcı (garbage collector) tarafından silinir.
public static void main(String[] args) { Araba araba1 = new Araba("Toyota"); Araba araba2 = araba1; System.out.println("Araba 1: " + araba1.getMarka()); System.out.println("Araba 2: " + araba2.getMarka()); araba2.setMarka("Ford"); System.out.println("Araba 1: " + araba1.getMarka()); araba1 = null; System.out.println("Araba 2: " + araba2.getMarka()); }
Referanslar ve this
null ve NullPointerException
public class Bos { String ad; public static void main(String[] args) { Bos b = null; System.out.println(b.ad.length()); } }
Exception in thread "main" java.lang.NullPointerException: Cannot read field "ad" because "<local1>" is null
at Bos.main(Bos.java:6)Yerel değişken hiç değer verilmeden kullanılırsa program derlenmez: error: variable sb might not have been initialized
null, referans değişkeninin hiçbir nesneyi göstermediği anlamına gelir.nullbir referans üzerinden nitelik okumak ya da metot çağırmak çalışma zamanındaNullPointerExceptionfırlatır.- Önlem: kullanmadan önce kontrol edin:
if (b != null) { ... } - Hiçbir referansın göstermediği nesneler JVM'in çöp toplayıcısı tarafından otomatik silinir; Java'da nesneyi elle silmek gerekmez.
Referanslar ve this
this Anahtar Kelimesi
public class Golge { private String ad; public Golge(String ad) { ad = ad; // this unutuldu! } public static void main(String[] args) { Golge g = new Golge("Ali"); System.out.println(g.ad); } }
null
this, metodun çağrıldığı nesneyi işaret eden referanstır.staticmetotlarda kullanılamaz (orada nesne yoktur).- En sık yapıcılarda, nitelik adı ile parametre adı aynı olduğunda kullanılır:
this.ad = ad; - Soldaki kodda
thisunutulmuş:ad = ad;parametreyi kendine atar, niteliknullkalır. Derleyici hata vermez! this(...)ise aynı sınıfın başka bir yapıcısını çağırır.
Referanslar ve this
this ile Nesneyi Aktarmak
public class Takim { private String ad; public Takim(String ad) { this.ad = ad; } public void oyuncuEkle(Oyuncu oyuncu) { oyuncu.takimaKatil(this); // bu nesne } public String getAd() { return ad; } public static void main(String[] args) { Takim takim = new Takim("Giresunspor"); Oyuncu oyuncu = new Oyuncu("Mert"); takim.oyuncuEkle(oyuncu); } }
this, o anki nesneyi başka bir metoda parametre olarak iletmek için kullanılır.takim.oyuncuEkle(oyuncu)içindethis=takimnesnesi;takimaKatil(this)ile oyuncuya verilir.- Aynı dosyada ikinci sınıf (
publicdeğil):
class Oyuncu { private String ad; Oyuncu(String ad) { this.ad = ad; } void takimaKatil(Takim takim) { String t = takim.getAd(); System.out.println(ad + " -> " + t); } }
Mert -> Giresunspor
Referanslar ve this · Kodu adım adım çalıştır
this ile Selam: Adım Adım
Yapıcıda this yeni nesnedir: this.ad (nitelik) = ad (parametre).
İkinci nesne de aynı yapıcıyla oluşur; o sırada this = #2 idi.
ogrenci1.selamVer(): noktanın solundaki nesne this olur → "Ali".
Aynı kod, farklı this → "Ayşe". Burada this.ad yerine ad yazmak da aynıdır.
public class Ogrenci { private String ad; public Ogrenci(String ad) { this.ad = ad; } public void selamVer() { System.out.println("Merhaba, ben " + this.ad); } public static void main(String[] args) { Ogrenci ogrenci1 = new Ogrenci("Ali"); Ogrenci ogrenci2 = new Ogrenci("Ayşe"); ogrenci1.selamVer(); ogrenci2.selamVer(); } }
Metot Aşırı Yükleme
Metot Aşırı Yükleme
public class HesapMakinesi { // İki tamsayıyı topla public int topla(int sayi1, int sayi2) { return sayi1 + sayi2; } // İki ondalık sayıyı topla public double topla(double sayi1, double sayi2) { return sayi1 + sayi2; } // Üç tamsayıyı topla public int topla(int sayi1, int sayi2, int sayi3) { return sayi1 + sayi2 + sayi3; } public static void main(String[] args) { HesapMakinesi hm = new HesapMakinesi(); System.out.println(hm.topla(5, 3)); System.out.println(hm.topla(3.5, 2.5)); System.out.println(hm.topla(4, 6, 8)); System.out.println(hm.topla(2, 3.5)); } }
8 6.0 18 5.5
- Aşırı yükleme (method overloading): farklı veri türü veya sayıda parametreyle aynı işi yapan, aynı adlı metotlar.
- Hangisinin çalışacağına derleyici argümanlara bakarak karar verir.
topla(2, 3.5): 2,double'a genişletilir. - Yalnızca dönüş türü farklıysa olmaz:
error: method topla(int,int) is already defined in class Hesap2
Nesneleri Karşılaştırma
== ve equals()
- Değişkenler yalnızca nesnelere ait referansları saklar.
==işleci nesnelerin nitelikleri yerine bellek adreslerini karşılaştırır: iki değişken aynı nesneyi mi gösteriyor?- İki nesnenin içerik eşitliği için tüm özellikleri karşılaştıran
equals()kullanılır; kendi sınıflarımızda yeniden yazılmalıdır. Stringve wrapper'lar da nesnedir: klavyeden okunan "Java" ile"Java"sabiti==ile false,equalsile true verdi.
| İfade | Sonuç |
|---|---|
k1 == k3 | true: aynı nesne |
k1 == k2 | false: farklı nesneler |
k1.equals(k2) | true: aynı içerik* |
* equals yeniden yazıldıysa; yoksa Object'in sürümü == gibi davranır.
Nesneleri Karşılaştırma
equals() Metodunu Yazmak
public class Kisi { private String ad; private int yas; public Kisi(String ad, int yas) { this.ad = ad; this.yas = yas; } @Override public boolean equals(Object obj) { // Aynı referansa sahipse, eşittir. if (this == obj) return true; // Null kontrolü yapılır, nesne türü karşılaştırılır. if (obj == null || getClass() != obj.getClass()) return false; // Kisi nesnelerinin alanları karşılaştırılır. Kisi kisi = (Kisi) obj; return yas == kisi.yas && ad.equals(kisi.ad); } @Override public int hashCode() { return 31 * ad.hashCode() + yas; } }
k1, k2 = new Kisi("Ali", 20), k3 = k1 için çıktı:
k1 == k2 | false |
k1.equals(k2) | true |
k1 == k3 | true |
k1.equals(null) | false |
k1.hashCode() == k2.hashCode() | true |
- Parametre türü
Objectolmalıdır;@Overrideimzayı derleyiciye denetletir. nullkontrolü hatayı önler.equalsyazılıncahashCodeda yazılmalıdır: eşit nesneler eşit hash vermeli.
Nesneleri Karşılaştırma
getClass() ve instanceof
class Hayvan { } class Kopek extends Hayvan { } public class TurKontrol { public static void main(String[] args) { Hayvan h = new Kopek(); Hayvan h2 = new Hayvan(); Hayvan yok = null; System.out.println(h.getClass().getSimpleName()); System.out.println(h.getClass() == Hayvan.class); System.out.println(h instanceof Kopek); System.out.println(h instanceof Hayvan); System.out.println(h2 instanceof Kopek); System.out.println(yok instanceof Hayvan); if (h instanceof Kopek k) { // Java 16+ System.out.println("Köpek: " + k.getClass()); } } }
Kopek false true true false false Köpek: class Kopek
- getClass():
Object'te tanımlıdır; nesnenin çalışma zamanındaki gerçek sınıfını döndürür. - instanceof: nesne o türden veya alt sınıfından ise true;
nulliçin false. Tür dönüşümünden (cast) önce kullanılır. extends(kalıtım) ile herKopekbirHayvan'dır; ayrıntısı Kalıtım bölümünde.
Nesneleri Karşılaştırma
toString() Metodu
class Ogrenci { private String ad; private int numara; Ogrenci(String ad, int numara) { this.ad = ad; this.numara = numara; } @Override public String toString() { return "Ogrenci [ad=" + ad + ", numara=" + numara + "]"; } } public class YaziTesti { public static void main(String[] args) { Ogrenci ogr = new Ogrenci("Ali", 2012); Ogrenci yok = null; System.out.println(ogr); // toString() System.out.println("Kayıt: " + ogr); // birleştirme System.out.println(yok); // null System.out.println(new Ders()); // Object'inki } }
Ogrenci [ad=Ali, numara=2012] Kayıt: Ogrenci [ad=Ali, numara=2012] null Ders@87aac27
- Nesnenin metin temsilini döndüren
Objectmetodu;printlnve+onu otomatik çağırır. - Yeniden yazılmazsa
SinifAdi@hashKodudöner (çalıştırmaya göre değişir);Derssınıfı toString yazmamıştır.
Wrapper Sınıflar
Wrapper Sınıflar
| Temel tür | Wrapper sınıf |
|---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
- Wrapper (sarmalayıcı) sınıflar, temel veri türlerini nesne olarak temsil eder.
- Bazı yerlerde nesne gerekir:
ArrayList<Integer>gibi generic koleksiyonlar temel tür alamaz. - Temel türe
nullatanamaz; wrapper değişkene atanabilir ("değer yok"). - Yardımcı metotlar sağlar:
Integer.parseInt("12"),Integer.MAX_VALUE,Character.isDigit(c). - Temel türler daha hızlı ve az bellek kullanır; gerekmedikçe temel türü tercih edin.
- Autoboxing ve unboxing dönüşümlerine dikkat edilmelidir.
Wrapper Sınıflar
Autoboxing ve Unboxing
public class Sarmalayici { public static void main(String[] args) { // int tipinde bir değişken int sayi = 42; // Integer wrapper sınıfı kullanımı Integer wrapperSayi = Integer.valueOf(sayi); // Autoboxing (otomatik ambalajlama) Integer wrapperSayi2 = sayi; // Unboxing (açık ve otomatik) int sayi2 = wrapperSayi2.intValue(); int sayi3 = wrapperSayi2; System.out.println(sayi2 + sayi3); System.out.println(wrapperSayi.equals(wrapperSayi2)); System.out.println(Integer.parseInt("123") + 1); System.out.println(Integer.MAX_VALUE); System.out.println(Character.isDigit('7')); System.out.println(Double.parseDouble("2.5") * 2); Integer bos = null; // int bos = null; derlenmez System.out.println(bos); } }
- Autoboxing: temel tür → wrapper, otomatik. Unboxing: wrapper → temel tür.
- Açık biçimleri:
Integer.valueOf(sayi),w.intValue().
84 true 124 2147483647 true 5.0 null
Wrapper Sınıflar
Wrapper Tuzakları
import java.util.ArrayList; public class Tuzaklar { public static void main(String[] args) { ArrayList<Integer> liste = new ArrayList<>(); liste.add(5); // autoboxing: 5 -> Integer int ilk = liste.get(0); // unboxing: Integer -> int System.out.println(ilk + 1); Integer a = 127, b = 127; Integer c = 128, d = 128; System.out.println(a == b); System.out.println(c == d); System.out.println(c.equals(d)); Integer bos = null; int x = bos; // NullPointerException } }
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because "<local7>" is null
6 true false true
- Wrapper nesneleri
==ile karşılaştırmayın: referans karşılaştırır. −128…127 arası değerler önbellekten aynı nesne olarak gelir; 128 için false. - Her zaman
equals()kullanın. nullbir wrapper'ı açmak (unboxing)NullPointerExceptionfırlatır.
Kayıt ve enum
Kayıtlar (Records)
- Kayıt (record, Java 16+), yalnızca veri taşıyan sınıfları kısa ve temiz yazmak için tasarlanmış bir sınıf türüdür.
- Değişmez (immutable) nesneleri temsil eder: tüm nitelikler
private final'dır; set metodu yoktur. - Derleyici otomatik üretir: yapıcı, erişim metotları
x()vey()(adlarıgetile başlamaz),equals,hashCode,toString.
record Nokta(double x, double y) { }
Bu tek satır; iki alan, yapıcı, iki erişimci ve üç Object metodu içeren yaklaşık 30 satırlık bir sınıfa denktir.
public class KayitTesti { public static void main(String[] args) { Nokta nokta1 = new Nokta(1.0, 2.5); Nokta nokta2 = new Nokta(1.0, 2.5); boolean esitMi = nokta1.equals(nokta2); System.out.println(esitMi); System.out.println(nokta1 == nokta2); System.out.println(nokta1); System.out.println(nokta1.x() + nokta1.y()); } }
true false Nokta[x=1.0, y=2.5] 3.5
n.x = 3.0; → error: x has private access in Nokta
Kayıt ve enum
enum (Numaralandırma Türü)
enum HaftaGunleri { PAZARTESI, SALI, CARSAMBA, PERSEMBE, CUMA, CUMARTESI, PAZAR } public class GunTesti { public static void main(String[] args) { HaftaGunleri[] tumGunler = HaftaGunleri.values(); HaftaGunleri persembe = HaftaGunleri.valueOf("PERSEMBE"); System.out.println(tumGunler.length + " gün"); System.out.println(persembe + " " + persembe.ordinal()); for (HaftaGunleri gun : tumGunler) { boolean haftaSonu = gun == HaftaGunleri.CUMARTESI || gun == HaftaGunleri.PAZAR; if (haftaSonu) { System.out.println(gun + ": hafta sonu"); } } } }
7 gün PERSEMBE 3 CUMARTESI: hafta sonu PAZAR: hafta sonu
- enum, sabit ve sınırlı değerleri temsil eden özel bir türdür.
values()tüm değerleri dizi olarak verir; üzerinde döngü kurulabilir.valueOfmetinden değere çevirir;ordinal()0'dan başlayan sıra. Değerler==ile karşılaştırılır.
İç Sınıflar
İç Sınıflar (Inner Classes)
- İç sınıf, bir sınıfın içinde tanımlanan sınıftır. Dış sınıfın niteliklerine ve metotlarına (
privateolanlar dahil) doğrudan erişebilir. - Yalnızca bir sınıfın işine yarayan yardımcı sınıfları gruplamak için kullanılır; grafik arayüzlerde olay dinleyici (listener) sınıfları için çok yaygındır.
| Tür | Nerede tanımlanır? | Nasıl oluşturulur? |
|---|---|---|
| Statik iç sınıf | Sınıf gövdesinde, static ile | Dış sınıf nesnesi olmadan: new Outer.StaticInner() |
| Üye iç sınıf | Sınıf gövdesinde, static olmadan | Bir dış sınıf nesnesi üzerinden: outer.new MemberInner() |
| Yerel iç sınıf | Bir metodun içinde | Yalnızca o metodun içinden |
| Anonim iç sınıf | Bir ifadenin içinde, adsız | Tanımlandığı yerde tek nesne; bir arayüzü veya soyut sınıfı gerçekler |
İç Sınıflar
Statik İç Sınıf
public class Outer { // Dış sınıfın içinde statik bir iç sınıf static class StaticInner { void display() { System.out.println("Statik İç Sınıf"); } } public static void main(String[] args) { // Dış sınıf örneği oluşturmadan erişim Outer.StaticInner staticInner = new Outer.StaticInner(); staticInner.display(); } }
Statik İç Sınıf
staticanahtar kelimesiyle tanımlanır.- Dış sınıfın bir nesnesi olmadan oluşturulabilir:
new Outer.StaticInner(). - Dış sınıfın yalnızca
staticüyelerine doğrudan erişebilir.
İç Sınıflar
Üye İç Sınıf
public class Outer { private int sayi = 5; // dış sınıfın özel alanı class MemberInner { // üye iç sınıf void display() { System.out.println("Üye İç Sınıf, sayi = " + sayi); } } public static void main(String[] args) { // Dış sınıf örneği üzerinden üye iç sınıfa erişim Outer outer = new Outer(); Outer.MemberInner memberInner = outer.new MemberInner(); memberInner.display(); } }
Üye İç Sınıf, sayi = 5
- Dış sınıfın bir üyesi olarak (
staticolmadan) tanımlanır. - Her üye iç sınıf nesnesi bir dış nesneye bağlıdır:
outer.new MemberInner(). Bu yüzdenprivate sayi'yi okuyabilir. mainiçinde doğrudannew MemberInner()derlenmez:
error: non-static variable this cannot be referenced from a static context
İç Sınıflar
Yerel İç Sınıf
public class Outer { void outerMethod() { class LocalInner { // metodun içinde tanımlanır void display() { System.out.println("Yerel İç Sınıf"); } } // Yerel iç sınıfa yalnızca bu metodun içinden erişilir LocalInner localInner = new LocalInner(); localInner.display(); } public static void main(String[] args) { Outer outer = new Outer(); outer.outerMethod(); } }
Yerel İç Sınıf
- Bir metodun içinde tanımlanır; yalnızca o metodun içinden kullanılabilir.
- Metot dışında
LocalInneradı bilinmez. - Bir metodun içinde birkaç kez gereken küçük bir yardımcı tür için kullanılır.
İç Sınıflar
Anonim İç Sınıf
interface MyInterface { void myMethod(); } public class Outer { public static void main(String[] args) { // Genellikle arayüzleri veya soyut sınıfları uygular MyInterface myInterface = new MyInterface() { @Override public void myMethod() { System.out.println("Anonim İç Sınıf"); } }; myInterface.myMethod(); } }
Anonim İç Sınıf
- Adı olmayan sınıftır; tanımlandığı yerde tek bir nesnesi oluşturulur.
- Genellikle bir arayüzü (interface) veya soyut sınıfı gerçekler:
new ArayuzAdi() { ... };Sondaki;atama deyimine aittir. - Tek metotlu arayüzler için Java 8+ lambda daha kısadır:
() -> ...
Sınıf Türleri ve Tasarım
Sınıflar ve Türler
interface Printable { ... } interface Runner { ... } class Hayvan implements Printable, Serializable { ... } class Kopek extends Hayvan implements Runner { ... } var kazanan = new Kopek(...);
- Bir nesne tek bir sınıfa ait olabilir, ama birçok türe sahip olabilir.
kazananyalnızcaKopeksınıfına aittir.- Ama türleri:
Kopek,Runner,Hayvan,Printable,Serializable,Object; hepsi içininstanceoftrue verir. - Bu, çok biçimliliğin temelidir.
Düz çizgi + boş üçgen: kalıtım (extends); kesikli: gerçekleme (implements).
Sınıf Türleri ve Tasarım
Sınıf Çeşitleri
Sınıf, bir nesnenin yapısını ve davranışını tanımlayan bir şablondur. Amaçlarına göre farklı sınıf çeşitleri vardır:
| Çeşit | Özellik | Örnek |
|---|---|---|
| Numaralandırma (enum) | Sabit bir nesne kümesine sahiptir | enum Gun { PAZARTESI, SALI, ... } |
| Singleton | Yalnızca bir nesnesi oluşturulabilir | private yapıcı + static tek nesne |
| Soyut (abstract) | Kendi nesnesi oluşturulamaz | abstract class Sekil |
| Mühürlü (sealed, Java 17+) | Alt sınıfları sabit bir kümedir | sealed interface Hareket permits Yuru, Kos |
| Final | Alt sınıf türetilemez | final class String |
| Veri (record) | Nesneleri değiştirilemez (immutable) | record Nokta(double x, double y) |
| Araç (utility) | Yalnızca static metotlar içerir | Math, Arrays |
| Uygulama (application) | main metodunu içerir | Programın başladığı sınıf |
Sınıf Türleri ve Tasarım
Sınıf Çeşitleri: Örnek
final class Araclar { // araç ve final sınıf private Araclar() { } // nesne oluşturulamaz static int kare(int x) { return x * x; } } class Ayarlar { // singleton private static final Ayarlar TEK = new Ayarlar(); private Ayarlar() { } static Ayarlar getir() { return TEK; } } abstract class Sekil { // soyut sınıf abstract double alan(); } // mühürlü (sealed, Java 17+) sealed interface Hareket permits Yuru, Kos { } final class Yuru implements Hareket { } final class Kos implements Hareket { } public class Cesitler { // uygulama sınıfı public static void main(String[] args) { System.out.println(Araclar.kare(7)); System.out.println(Ayarlar.getir() == Ayarlar.getir()); } }
49 true
Araclar:privateyapıcı ile nesne oluşturulamaz, yalnızca static metot;finalile türetilemez.Ayarlar: tek nesne her seferinde aynıdır, bu yüzden==true.new Sekil()derleme hatası verir (soyut);Hareket'i yalnızcaYuruveKosgerçekleyebilir.
Sınıf Türleri ve Tasarım
Sınıf Tasarımı
Sınıfları tasarlarken üç temel unsura dikkat edilmelidir:
Kullanıcı yalnızca bu "sözleşmeyi" bilir.
private tutulmalı, dış dünyaya sınıfın iç yapısı hakkında bilgi verilmemelidir.Temsil değişse bile kullanıcı kodu bozulmaz.
Sonraki slaytta üç unsur tek bir sınıfta.
Sınıf Türleri ve Tasarım
Tasarım Örneği: RasyonelSayi
public class RasyonelSayi { // Temsil: gizli alanlar private int pay, payda; // Tanımlama: public yapıcı ve metotlar public RasyonelSayi(int pay, int payda) { int e = ebob(Math.abs(pay), Math.abs(payda)); this.pay = pay / e; this.payda = payda / e; } public RasyonelSayi topla(RasyonelSayi d) { int yeniPay = pay * d.payda + d.pay * payda; return new RasyonelSayi(yeniPay, payda * d.payda); } @Override public String toString() { return pay + "/" + payda; } // Uygulama ayrıntısı: gizli yardımcı metot private static int ebob(int a, int b) { while (b != 0) { int k = a % b; a = b; b = k; } return a; } }
- Tanımlama:
publicyapıcı,topla,toString. - Temsil:
private int pay, payda; yapıcı kesri sadeleştirir. - Uygulama: metot gövdeleri ve gizli
ebobyardımcısı (Öklid algoritması). toplamevcut nesneyi değiştirmez, yeni bir nesne döndürür.
a = new RasyonelSayi(8, 10), b = new RasyonelSayi(2, 3); println(a) ve println(a.topla(b)):
4/5 22/15
Özet
Özet
| Kavram | Özü |
|---|---|
| Sınıf / nesne | Sınıf taslaktır; nesne new ile üretilen örneğidir. |
| Yapıcı | Sınıfla aynı ad, dönüş türü yok; yazılmazsa varsayılan yapıcı eklenir. |
| Örnek / static üye | Örnek alanı her nesnede ayrı; static alan sınıfta tek ve ortak. |
| Başlatıcılar | static { } bir kez; { } her nesnede, yapıcı gövdesinden önce. |
| Erişim ve gizleme | Nitelikler private; get/set ile kontrollü erişim. |
| Referans | Değişken nesneyi değil referansı tutar; atama referansı kopyalar. |
this | Metodun çağrıldığı nesne; static metotta yok. |
== / equals | Aynı nesne mi? / aynı içerik mi? |
| Wrapper | int ↔ Integer: autoboxing ve unboxing. |
| record / enum | Değişmez veri sınıfı / sabit değer kümesi. |
| İç sınıflar | Statik, üye, yerel, anonim. |
Özet
Sık Yapılan Hatalar (1)
error: non-static method selamVer() cannot be referenced from a static context Önce nesne oluşturun (new Selam().selamVer()) ya da metot gerçekten nesneye bağlı değilse static yapın.error: constructor Hata1 in class Hata1 cannot be applied to given types; public void Hata1(String m) yapıcı değil, sıradan metottur. Yapıcının dönüş türü olmaz.error: constructor Urun in class Urun cannot be applied to given types; Bir yapıcı yazınca varsayılan yapıcı eklenmez; gerekiyorsa parametresiz yapıcıyı da yazın.error: cannot find symbol symbol: method Urun(String)Nesne oluşturmak için new Urun("Kalem") yazılmalıdır.Özet
Sık Yapılan Hatalar (2)
error: hesapBakiyesi has private access in BankaHesabi Sınıfın get/set metotlarını kullanın.error: non-static variable this cannot be referenced from a static context Static metodun bir nesnesi yoktur.ad = ad; // derlenir, nitelik null kalırParametre niteliği gölgeler; this.ad = ad; yazın.error: method topla(int,int) is already defined in class Hesap2 Parametre listesi farklı olmalıdır.Özet
Sık Yapılan Hatalar (3)
k1 == k2 // falseİçerik için equals() kullanın; String ve wrapper'lar dahil.NullPointerExceptionNesne oluşturulmadan veya null atandıktan sonra metot çağrılamaz; önce kontrol edin.error: x has private access in Nokta Record değişmezdir; yeni değerle yeni bir nesne oluşturun.error: non-static variable this cannot be referenced from a static context outer.new MemberInner() yazın ya da iç sınıfı static yapın.Özet
Örnek Problemler (1)
Problem 1. Ne yazdırır?
class Sayac { static int toplam = 0; int adet = 0; void arttir() { toplam++; adet++; } } public class Problem1 { public static void main(String[] args) { Sayac a = new Sayac(), b = new Sayac(); a.arttir(); a.arttir(); b.arttir(); System.out.print(a.adet + " " + b.adet); System.out.println(" " + Sayac.toplam); } }
Problem 2. Ne yazdırır?
class Kutu { int deger; } public class Problem2 { public static void main(String[] args) { Kutu k1 = new Kutu(); k1.deger = 5; Kutu k2 = k1; k2.deger = 9; Kutu k3 = new Kutu(); k3.deger = 9; System.out.println(k1.deger); System.out.println(k1 == k2); System.out.println(k2 == k3); } }
Cevapları göster
- 2 1 3.
adether nesnede ayrıdır (a: 2, b: 1);toplamstatic olduğu için üç çağrının hepsini sayar: 3. - 9, true, false.
k2 = k1aynı nesneyi gösterir:k2.deger = 9sonrasık1.degerda 9.k3ayrı nesnedir; değerleri eşit olsa da==false.
Özet
Örnek Problemler (2)
Problem 3. Ne yazdırır?
class A { static { System.out.print("S"); } { System.out.print("I"); } A() { System.out.print("C"); } } public class Problem3 { public static void main(String[] args) { System.out.print("M"); new A(); new A(); System.out.println(); } }
Problem 4. Ne yazdırır?
class Kutu { int deger; } public class Problem4 { static void degistir(Kutu k) { k.deger = 100; k = new Kutu(); k.deger = 7; } public static void main(String[] args) { Kutu x = new Kutu(); x.deger = 1; degistir(x); System.out.println(x.deger); } }
Cevapları göster
- MSICIC. Önce
main"M" yazar.Asınıfı ilknew A()'da yüklenir: static blok bir kez (S); sonra her nesne için örnek başlatıcı (I) ve yapıcı (C). - 100.
degistir, referansın kopyasını alır:k.deger = 100asıl nesneyi değiştirir;k = new Kutu()yalnızca yerel kopyayı başka bir nesneye yöneltir,xetkilenmez.
Özet
Örnek Problemler (3)
Problem 5. Ne yazdırır?
record Para(int lira) { } public class Problem5 { public static void main(String[] args) { Para p1 = new Para(10); Para p2 = new Para(10); Integer i1 = 1000, i2 = 1000; System.out.println(p1.equals(p2)); System.out.println(p1 == p2); System.out.println(i1.equals(i2)); System.out.println(p1); } }
Problem 6. Ne yazdırır?
class Nokta { int x, y; Nokta(int x, int y) { this.x = x; this.y = y; } } public class Problem6 { public static void main(String[] args) { Nokta a = new Nokta(1, 2); Nokta b = new Nokta(1, 2); System.out.println(a.equals(b)); System.out.println(a.x == b.x); } }
Cevapları göster
- true / false / true / Para[lira=10]. Record'ın
equals'ı içeriği,==referansı karşılaştırır;Integeriçinequalsher zaman güvenlidir. - false / true.
equalsyazılmamış:Object'inki referans karşılaştırır.a.x == b.xikiintdeğerdir.
Özet
Alıştırmalar
Kitapsınıfı:privatebaslik,yazar,sayfaSayisi; üç parametreli yapıcı, get metotları vetoString().Kitap'a statictoplamKitapSayisisayacı ve yalnızca pozitif değeri kabul edensetSayfaSayisiekleyin.Dairesınıfı:yaricap,alan(),cevre().new Daire(3)için iki basamakla yazdırın.Mevsimenum'unun değerlerini sıra numaralarıyla yazdırın.OgrenciKaydi(String ad, int numara)record'unu yazıp bir nesnesini yazdırın.
Cevaplar / ipuçları
this.baslik = baslik; ...;toString()→Nutuk (Atatürk, 600 s.)- Yapıcıda
toplamKitapSayisi++;, setter'daif (sayfaSayisi > 0) .... −5 sayfalı ikinci kitapta sayfa 0 kalır, sayaç 2:0 2 Math.PI * yaricap * yaricap,2 * Math.PI * yaricap;printf("%.2f %.2f%n", ...)→28,27 18,85(Türkçe yerel ayarda virgül).for (Mevsim m : Mevsim.values())→0:ILKBAHAR 1:YAZ 2:SONBAHAR 3:KISrecord OgrenciKaydi(String ad, int numara) { }→OgrenciKaydi[ad=Ali, numara=7]
Özet
Kaynaklar
- Oracle, The Java Tutorials: "Classes and Objects", "Nested Classes", "Enum Types", "Record Classes", "Autoboxing and Unboxing".
- J. Gosling ve diğ., The Java Language Specification, Java SE 21 Edition (Bölüm 8 Classes: 8.3 Fields, 8.6–8.7 Initializers, 8.8 Constructors, 8.9 Enum, 8.10 Record).
- P. Deitel ve H. Deitel, Java: How to Program, Early Objects, 11. baskı, Pearson, 2017 (Bölüm 3 ve 8: Classes and Objects).
- K. Sierra ve B. Bates, Head First Java, 3. baskı, O'Reilly, 2022.
- C. S. Horstmann, Core Java, Volume I: Fundamentals, 12. baskı, 2022 (Bölüm 4: Objects and Classes).
- A. B. Downey ve C. Mayfield, Think Java, 2. baskı, O'Reilly, 2019 (Bölüm 10–11).
- J. Bloch, Effective Java, 3. baskı, Addison-Wesley, 2018 (equals, hashCode, toString maddeleri).