Java'da constructor (yapıcı metot), bir sınıftan new anahtar kelimesiyle nesne oluşturulduğu anda otomatik olarak çalışan, sınıfla aynı ismi taşıyan ve dönüş tipi olmayan özel bir bloktur. Görevi, nesnenin hafızada var olduğu ilk anda alanlarına (field) başlangıç değerlerini vermek ve nesneyi kullanıma hazır hale getirmektir. Normal bir metot gibi çağrılmaz; nesne yaratılırken derleyici tarafından devreye sokulur. Bu yazıda default constructor'dan parametreli kullanıma, overloading'den this() ile zincirleme çağrılara kadar constructor mantığını adım adım, örneklerle inceleyeceğiz.
Constructor (Yapıcı Metot) Nedir?
Bir constructor, sınıfın adını taşıyan, dönüş tipi (void dahil) belirtilmeyen ve yalnızca new ile nesne oluşturma sırasında çalışan özel bir yapıdır. Örneğin Ogrenci adında bir sınıf varsa, bu sınıfın constructor'ı da Ogrenci() ismini taşır. Java bunu neden sıradan bir metot olarak değil de ayrı bir yapı olarak ele alır? Çünkü constructor'ın görevi metotlardan farklıdır: bir metot, zaten var olan bir nesne üzerinde işlem yapar; constructor ise nesnenin henüz var olmadığı, hafızada yer ayrıldığı ancak alanlarının anlamlı bir değere kavuşmadığı ilk kritik anı yönetir. Bu yüzden constructor çağrılmadan önce nesne "eksik" sayılır, çağrıldıktan sonra kullanıma hazır hale gelir.
Kavramı somutlaştırmak için bir form doldurma benzetmesi kullanılabilir. Boş bir form (nesne) tek başına anlam taşımaz; kişi ad, soyad, doğum tarihi gibi alanları doldurduğunda form kullanılabilir hale gelir. Constructor da tam olarak bu doldurma işlemini otomatikleştirir: nesne oluşturulur oluşturulmaz gerekli alanlara değerler atanır, böylece programcı her nesne için ayrı ayrı "şu alanı doldur, bu alanı doldur" demek zorunda kalmaz. Bu mantık, nesne yönelimli programlamanın temel taşlarından biridir ve ileride kalıtım, polimorfizm gibi konularla birleştiğinde daha da önem kazanır.
Yazılım öğrenme sürecinde bu tür temel OOP kavramlarının nerede kullanılacağını görmek, motivasyonu artıran önemli bir adımdır. Kendi öğrenme yolunuzu netleştirmek isterseniz ücretsiz kariyer değerlendirme testi ile hangi alanlara daha yatkın olduğunuzu görebilir, öğrenme planınızı buna göre şekillendirebilirsiniz. Constructor kavramını iyi kavramak, ilerideki daha karmaşık sınıf tasarımlarının da temelini oluşturur.
Default (Varsayılan) Constructor
Bir sınıf içinde hiçbir constructor tanımlanmazsa, Java derleyicisi geriye dönük uyumluluk ve kolaylık amacıyla otomatik olarak parametresiz, gövdesi boş bir default constructor üretir. Bu sayede her sınıftan sorunsuzca new ile nesne oluşturulabilir, programcı bunun için ekstra bir kod yazmak zorunda kalmaz.
Aşağıdaki örnekte Kitap sınıfında hiçbir constructor tanımlanmamıştır, dolayısıyla derleyici arka planda kendi default constructor'ını ekler:
public class Kitap {
String ad;
int sayfaSayisi;
}
public class Test {
public static void main(String[] args) {
Kitap k = new Kitap();
System.out.println(k.ad); // null
System.out.println(k.sayfaSayisi); // 0
}
}
Burada new Kitap() çağrısı derleyicinin ürettiği gizli constructor'ı çalıştırır. Alanlar açıkça bir değer almadığı için ilkel tipler (int, double, boolean gibi) kendi varsayılan değerlerini alır: sayısal tipler 0, boolean false olur; referans tipler ise (String, nesne türleri) null değeriyle başlar.
Burada dikkat edilmesi gereken kritik nokta şudur: programcı sınıfa kendi isteğiyle en az bir constructor eklediği anda, derleyicinin otomatik ürettiği default constructor devre dışı kalır. Yani bir sınıfa parametreli bir constructor eklenip parametresiz kullanım da isteniyorsa, parametresiz constructor'ın ayrıca ve elle yazılması gerekir. Aksi halde new Kitap() gibi parametresiz bir çağrı derleme hatası verir, çünkü artık ortada derleyicinin sunduğu bir "boş" seçenek yoktur. Bu davranış, constructor tasarımı yaparken sınıfın hem parametreli hem parametresiz kullanılıp kullanılmayacağının baştan planlanmasını gerektirir.
Parametreli Constructor ile Nesne Oluşturma

Default constructor alanları boş bırakırken, parametreli constructor nesne oluşturulduğu anda alanlara doğrudan anlamlı değerler atanmasını sağlar. Böylece "önce nesneyi oluştur, sonra alanları tek tek doldur" yerine, nesne zaten dolu ve kullanıma hazır şekilde ortaya çıkar. Bu yaklaşım hem daha az kod yazmayı hem de nesnenin hiçbir zaman eksik/tutarsız bir durumda kalmamasını garanti eder.
Mantık şöyle işler: new ClassName(değer1, değer2) şeklinde bir çağrı yapıldığında, Java önce hafızada nesne için yer ayırır, ardından parantez içindeki değerleri sınıfta tanımlı constructor'ın parametre listesiyle eşleştirir ve constructor'ın gövdesini bu değerlerle çalıştırır. Örneğin Kitap sınıfında ad ve sayfaSayisi parametrelerini kabul eden bir constructor tanımlanırsa, gövde içinde bu parametreler doğrudan sınıfın alanlarına atanır; parametrelerin sırası ve tipi, çağrı sırasında verilen değerlerle birebir uyuşmak zorundadır. Yani parametre sayısı, tipi veya sırası yanlışsa derleyici hata verir; bu da constructor'ı kullanırken sınıfın "beklediği" veri şeklini net şekilde bilmeyi gerektirir.
Bu eşleştirme mantığı, ilk bakışta basit görünse de büyük projelerde çok sayıda alanı olan sınıflarda dikkatli tasarım ister; yanlış sırayla verilen değerler mantıksal hatalara yol açabilir. Bu tür sınıf tasarımı pratiklerini uygulamalı örneklerle pekiştirmek isteyenler, Java özel ders kapsamında birebir geri bildirimle constructor kullanımını adım adım öğrenebilir. Bir sonraki bölümde, tam ve derlenebilir bir kod örneğiyle parametreli constructor'ın alan atamalarını gövde içinde nasıl gerçekleştirdiğini detaylı biçimde göreceğiz.
Constructor Overloading: Aynı Sınıfta Birden Fazla Constructor
Bir sınıfın ihtiyaçları her zaman tek bir kalıba sığmaz. Bazen bir nesneyi hiçbir bilgi vermeden, bazen yalnızca birkaç alanla, bazen de tüm bilgilerle oluşturmak isteriz. İşte tam bu noktada devreye constructor overloading girer: aynı sınıfın, farklı parametre listelerine sahip birden fazla constructor'a sahip olabilmesi anlamına gelir. Constructor'ların isimleri her zaman sınıfla aynıdır, bu yüzden onları birbirinden ayıran şey parametre sayısı ve parametre tipleridir.
Bu yaklaşımın pratikte neden işe yaradığını bir örnekle düşünelim. Bir Ogrenci sınıfı yazdığınızı varsayın. Bazı durumlarda öğrenciyi hiç bilgi girmeden oluşturup bilgileri sonradan tamamlamak isteyebilirsiniz; bazen sadece adını bilirsiniz; bazen de ad ve yaş gibi tüm bilgiler elinizdedir. Overloading sayesinde tek bir sınıf, bu üç senaryonun hepsine hizmet edebilir:
- Parametresiz constructor: nesneyi varsayılan değerlerle oluşturur.
- Kısmi bilgiyle constructor: yalnızca bilinen alanları alır, kalanını mantıklı bir varsayılana bağlar.
- Tam bilgiyle constructor: tüm alanları doğrudan parametre olarak alır.
Java derleyicisi, siz new Ogrenci() ya da new Ogrenci("Ayşe") yazdığınızda hangi constructor'ın çalışacağına parametre sayısına ve tipine bakarak karar verir. Bu sürece overload resolution denir ve derleme anında, yani kod çalışmadan önce belirlenir; bu yüzden yanlış sayıda veya tipte parametre verirseniz kodunuz hiç derlenmez, çalışma zamanında değil derleme zamanında hata alırsınız. Aşağıdaki örnekte hem parametreli hem de birden fazla overload edilmiş constructor'ı, this() ile birlikte bir arada görebilirsiniz:
public class Ogrenci {
String ad;
int yas;
public Ogrenci() {
this("İsimsiz", 0);
}
public Ogrenci(String ad) {
this(ad, 18);
}
public Ogrenci(String ad, int yas) {
this.ad = ad;
this.yas = yas;
}
}
Burada dikkat edilmesi gereken nokta, üç constructor'ın da aslında tek bir asıl constructor'a (üç parametreli olana) yönlenmesidir. Bu tasarım, overloading'in tek başına değil, bir sonraki bölümde ele alacağımız this() mekanizmasıyla birleştiğinde ne kadar güçlü olduğunu gösterir.
this() ile Constructor Chaining (Yapıcı Zincirleme)

this() ifadesi, bir constructor'ın içinden aynı sınıfa ait başka bir constructor'ı çağırmak için kullanılır. Yukarıdaki Ogrenci örneğinde parametresiz constructor, kendi gövdesinde alan atamaları yapmak yerine işi doğrudan iki parametreli constructor'a devretti. Bu zincirleme yaklaşıma constructor chaining denir ve nesne oluşturma mantığını tek bir yerde toplamayı sağlar.
Burada uyulması gereken katı bir kural vardır: this() çağrısı, bulunduğu constructor'ın ilk satırı olmak zorundadır. Derleyici bu sırayı zorunlu tutar çünkü nesnenin ilk kurulum adımının her zaman net ve öngörülebilir olması gerekir; this()'tan önce başka bir satır (bir alan ataması ya da metot çağrısı gibi) yer alamaz.
Bu deseni tercih etmenizin temel nedeni kod tekrarını azaltmaktır. Bir önceki bölümdeki örnekte, eğer this() kullanılmasaydı, her constructor kendi içinde ad ve yas alanlarına ayrı ayrı atama yapmak zorunda kalırdı; bu da aynı mantığın üç farklı yerde tekrarlanması, dolayısıyla ileride bir kural değiştiğinde üç yeri birden güncelleme riski demektir. this() ile bu mantık tek bir constructor'da toplanır, diğerleri yalnızca ona yönlendirme yapar. Böylece sınıfın "gerçek kurulum kuralları" tek bir yerde yaşar ve bakımı çok daha kolay hale gelir.
Constructor zincirleme mantığını gerçek kod üzerinde deneyerek pekiştirmek isteyenler, Java bilgi düzeyini ölçen kısa test ile bu konudaki kavrayışlarını hızlıca sınayabilir. Özellikle hangi constructor'ın hangi durumda çalışacağını kafada canlandırmak, ilk başta biraz pratik gerektiren bir beceridir.
this Anahtar Kelimesi: Parametre ve Alan İsim Çakışmasını Çözmek
Constructor yazarken parametre isimlerini sınıfın alan isimleriyle aynı seçmek son derece yaygın ve okunabilirlik açısından tercih edilen bir alışkanlıktır. Ancak bu durum bir belirsizlik doğurur: parametre de ad, alan da ad ise, constructor gövdesinde yazdığınız ad ifadesi hangisini kastediyor? Java bu çakışmayı, en yakın kapsamdaki tanımı (yani parametreyi) öncelikli sayarak çözer. Bu yüzden gerçek alana ulaşmak istediğinizde this.ad yazmanız gerekir; this, "bu sınıfın kendisine ait alanı" ifade eder.
this kullanılmadan yazılan ad = ad; satırı, gördüğünüz üzere bir hata vermez ama beklediğiniz işi de yapmaz. Bu satır, parametreyi kendi kendine atar; sınıfın gerçek alanı hiçbir zaman güncellenmez. Sonuç olarak nesne oluşturulur ama alanları hep varsayılan değerinde (metin için null, sayı için 0) kalır. Bu tür hatalar derleme sırasında yakalanmadığı için özellikle yeni başlayanların sıkça düştüğü, fark edilmesi zaman alan bir tuzaktır.
Aşağıdaki kısa karşılaştırma bu farkı netleştirir:
public Ogrenci(String ad) {
ad = ad; // hatalı: parametre kendine atanır, alan boş kalır
this.ad = ad; // doğru: gerçek alan güncellenir
}
Bu nedenle, parametre ve alan isimleri aynı olduğunda this.alanAdı = alanAdı; kalıbını kullanmak bir tercih değil, doğru çalışan bir sınıf yazmanın ön koşuludur. İsimler farklı olsaydı (örneğin parametre gelenAd, alan ad olsaydı) bu çakışma zaten oluşmazdı; ama sınıf tasarımında okunabilirlik genellikle aynı isimlendirmeyi tercih ettirir, dolayısıyla this kullanımı pratikte neredeyse her constructor'da karşınıza çıkar.
Constructor ile Normal Metot Arasındaki Farklar
Java'ya yeni başlayanların en çok karıştırdığı konulardan biri, constructor ile normal bir metodun birbirinden ne kadar farklı iki yapı olduğudur. Görünüşte ikisi de sınıf içinde tanımlanan kod bloklarıdır, ancak amaçları ve çalışma biçimleri tamamen farklıdır. Bir constructor'ın tek görevi, nesne oluşturulduğu anda o nesneyi kullanılabilir hale getirmektir; normal bir metot ise nesne zaten var olduktan sonra, o nesne üzerinde belirli bir işlemi gerçekleştirmek için çağrılır. Bu ayrımı net görebilmek için aşağıdaki karşılaştırmayı incelemek faydalı olacaktır.
| Özellik | Constructor | Normal Metot |
|---|---|---|
| İsimlendirme kuralı | Sınıf adıyla birebir aynı olmak zorundadır | Herhangi bir isim verilebilir |
| Dönüş tipi | Dönüş tipi yoktur, void bile yazılmaz | void veya belirli bir veri tipi mutlaka belirtilir |
| Çağrılma şekli | new anahtar kelimesiyle otomatik çalışır | Nesne üzerinden nokta operatörüyle manuel çağrılır |
| Sınıf başına sayı sınırı | Overloading ile birden fazla tanımlanabilir | Sınırsız sayıda tanımlanabilir |
| Miras alınabilirlik durumu | Alt sınıflara doğrudan miras kalmaz, super() ile çağrılır | Alt sınıflara miras kalır ve override edilebilir |
Bu iki yapının karıştırılmasının asıl nedeni, ikisinin de sınıf gövdesi içinde süslü parantezlerle çevrili birer kod bloğu gibi görünmesidir. Ancak constructor'ın dönüş tipinin olmaması ve isminin sınıfla birebir aynı olması, onu derleyici için tamamen özel bir yapı haline getirir. Bir metodun ne zaman çalışacağına siz karar verirsiniz; bir constructor'ın ne zaman çalışacağına ise nesnenin oluşturulma anı karar verir. Bu farkı kavramak, ileride kalıtım ve çok biçimlilik gibi daha karmaşık OOP konularına geçerken kafa karışıklığını büyük ölçüde azaltır.
Bir Sınıfa Constructor Nasıl Eklenir? Adım Adım Uygulama
Teoriyi öğrenmek başka, elle kod yazarak deneyimlemek başkadır. Bir sınıfa constructor eklerken izlenebilecek adımları aşağıdaki gibi sıralayabiliriz:
- Önce nesne olarak modellemek istediğiniz sınıfın adını belirleyin (örneğin Kitap).
- Bu sınıfın hangi bilgileri taşıyacağını, yani ihtiyaç duyulan alanları (field) tanımlayın.
- Constructor'ı sınıf adıyla birebir aynı isimde ve önüne hiçbir dönüş tipi yazmadan oluşturun.
- Nesne oluşturulurken dışarıdan hangi bilgilerin alınacağına karar verip parametreleri belirleyin.
- Constructor gövdesinde bu parametreleri, gerekirse this anahtar kelimesiyle, ilgili alanlara atayın.
- Farklı senaryolar için nesne oluşturmak isterseniz overloading ile ek constructor'lar tanımlayın.
- Son olarak new anahtar kelimesiyle nesne oluşturarak constructor'ın doğru çalıştığını test edin.
Bu adımları somut bir örnek üzerinde görelim:
public class Kitap {
private String baslik;
private String yazar;
private int sayfaSayisi;
public Kitap() {
this("Bilinmeyen Kitap", "Bilinmeyen Yazar", 0);
}
public Kitap(String baslik, String yazar) {
this(baslik, yazar, 0);
}
public Kitap(String baslik, String yazar, int sayfaSayisi) {
this.baslik = baslik;
this.yazar = yazar;
this.sayfaSayisi = sayfaSayisi;
}
public void bilgiGoster() {
System.out.println(baslik + " - " + yazar + " (" + sayfaSayisi + " sayfa)");
}
public static void main(String[] args) {
Kitap k1 = new Kitap();
Kitap k2 = new Kitap("Suç ve Ceza", "Dostoyevski");
Kitap k3 = new Kitap("1984", "George Orwell", 328);
k1.bilgiGoster();
k2.bilgiGoster();
k3.bilgiGoster();
}
}
Bu örnekte üç farklı constructor, this() ile birbirine zincirlenmiş ve her senaryoda nesnenin tutarlı biçimde oluşturulması sağlanmıştır. Adım adım ilerlerken bu tür küçük projeler üzerinde pratik yapmak, konuyu ezberlemek yerine gerçekten içselleştirmenin en etkili yoludur; birebir geri bildirim almak isteyenler için 1-1 özel ders kapsamında bu tarz alıştırmalar adım adım incelenebilir.
Constructor yazarken sıkça karşılaşılan üç hata özellikle dikkat gerektirir:
- Yanlışlıkla dönüş tipi yazmak: Constructor'a void ya da başka bir dönüş tipi eklendiğinde, Java bunu artık bir constructor olarak değil, sınıf adıyla aynı isimde sıradan bir metot olarak yorumlar. Bu metot new ile otomatik çağrılmaz; nesne oluşturulduğunda alanlar varsayılan değerleriyle kalır ve programcı bunun neden çalışmadığını anlamakta zorlanır.
- Constructor adını sınıf adından farklı yazmak: Java, isim uyuşmazlığını fark eder ve bu kod bloğunu constructor olarak değil, dönüş tipi eksik bir metot olarak algılamaya çalışır. Bu genellikle derleme hatasıyla sonuçlanır çünkü metodun bir dönüş tipi belirtilmemiştir.
- this() çağrısını ilk satır dışında kullanmak: Java, bir constructor içinde başka bir constructor'ı çağıran this() ifadesinin mutlaka ilk satırda olmasını zorunlu kılar. Aksi halde derleyici "constructor call must be the first statement" hatası verir, çünkü nesnenin başlatma sırası garanti altına alınamaz.
Bu üç hatanın ortak noktası, Java'nın constructor'ları çalışma zamanında değil derleme zamanında sınıfın yapısal bir parçası olarak ele almasıdır. Kuralları bir kez net anladıktan sonra bu hatalar hızla ortadan kalkar.
Sık Sorulan Sorular
Java'da constructor ile metot arasındaki en temel fark nedir?
Constructor'ın dönüş tipi yoktur ve sınıf adıyla aynı isme sahiptir; nesne new ile oluşturulduğunda otomatik çalışır. Normal metot ise ayrı bir isim ve dönüş tipi taşır, yalnızca nesne üzerinden manuel olarak çağrıldığında çalışır.
Bir sınıfta hiç constructor yazmazsam ne olur?
Java, derleme sırasında hiçbir parametre almayan boş bir default constructor'ı otomatik olarak ekler. Bu sayede nesne yine de new ile sorunsuz oluşturulabilir, ancak alanlara özel bir başlangıç değeri atanmaz.
Aynı sınıfta birden fazla constructor tanımlamak (overloading) neden gereklidir?
Farklı kullanım senaryolarında nesnenin farklı sayıda veya türde bilgiyle oluşturulmasına imkân tanımak için gereklidir. Bu sayede aynı sınıftan, elde bulunan veriye göre esnek biçimde nesne üretilebilir.
this() ifadesi ile this anahtar kelimesi arasındaki fark nedir?
this() aynı sınıf içindeki başka bir constructor'ı çağırmak için kullanılır ve constructor chaining'in temelidir. this anahtar kelimesi ise mevcut nesnenin kendisini temsil eder ve genellikle parametre ile alan ismi çakıştığında alana açıkça erişmek için kullanılır.
Constructor'a dönüş tipi yazarsam ne olur?
Dönüş tipi eklenen bir yapı artık constructor sayılmaz; sınıf adıyla aynı isme sahip sıradan bir metoda dönüşür. Bu metot new ile otomatik çağrılmaz, yalnızca nesne üzerinden manuel olarak çalıştırılabilir.
Constructor overloading yaparken en sık karşılaşılan hata nedir?
Birbirinden yalnızca parametre isimleriyle ayrılan, ama parametre tipi ve sayısı aynı olan iki constructor tanımlamaya çalışmaktır. Java, imzaları aynı olan bu tür constructor'ları ayırt edemediği için derleme hatası verir.
Constructor private olarak tanımlanabilir mi?
Evet, bir constructor private olarak tanımlanabilir; bu genellikle sınıfın dışarıdan doğrudan new ile örneklenmesini engellemek ve nesne oluşturmayı sınıf içindeki özel bir metoda veya statik bir yapıya bırakmak istendiğinde tercih edilir.
Constructor kavramı, Java'da nesne yönelimli programlamanın temel taşlarından biridir ve bu mantığı sağlam kurmak, ileride kalıtım, arayüzler ve daha karmaşık sınıf yapılarıyla çalışırken büyük kolaylık sağlar. Öğrendiklerinizi pekiştirmek isterseniz Java bilgi testi ile mevcut seviyenizi kısa bir şekilde ölçebilirsiniz.