Logo
Ana Sayfa
ÖZEL KODLAMA DERSLERİ
Yazılım Özel Ders
Tüm birebir programlara genel bakış
Python Yazılım Kursu
Sıfırdan ileri seviyeye birebir Python
Java Yazılım Kursu
OOP odaklı birebir Java eğitimi
AP Computer Science Principles
AP CSP sınav hazırlığı
GRUP DERSLERİ
Python & Django Masterclass
SINIRLI KONTENJAN
Java & Spring Boot Masterclass
SINIRLI KONTENJAN
C# .NET Masterclass
SINIRLI KONTENJAN
VİDEO DERSLER
Sıfırdan Temel Python Kursu
Kendi Hızında Öğren
ÜCRETSİZ
Seviye Testi
Ücretsiz — Python, Java, algoritma seviye testleri
Kariyerini Keşfet
Sertifika Doğrula
Belge numarası ve soyad ile doğrulama

Java'da Static Nested Class ile Inner Class Arasındaki Fark

Yazar: Berk Keskin 29.08.2026 ~11 dk okuma 2 Okunma
java-static-nested-class-inner-class-farki

Java'da static nested class ile inner class arasındaki temel fark, iç içe tanımlanan sınıfın dış sınıfla kurduğu bağın niteliğidir: static nested class dış sınıftan bağımsız, kendi başına örneklenebilen bir yapıdır; inner class ise yalnızca var olan bir dış sınıf nesnesi üzerinden örneklenebilen, o nesneye örtük bir referans taşıyan bağımlı bir yapıdır. Bu tek fark, syntax'tan bellek yönetimine, erişim kurallarından tasarım tercihlerine kadar birçok sonucu beraberinde getirir. Aşağıdaki bölümlerde bu farkın her boyutu somut örneklerle ele alınıyor.

Nested Class Nedir? Genel Çerçeve

Java'da bir sınıfın gövdesi içinde tanımlanan her sınıfa nested class (iç içe sınıf) denir. Bu şemsiye terim, sınıfı mantıksal olarak yalnızca kullanıldığı yere ait kılmak, kod okunabilirliğini artırmak ve gereksiz sınıf kirliliğini önlemek amacıyla kullanılır. Java dil spesifikasyonu nested class'ları iki ana kategoriye ayırır: static nested class ve non-static nested class. İkinci kategori genellikle "inner class" olarak anılır ve bu yazının odağı da bu iki türün birbirinden ayrıldığı noktalardır; local class ve anonymous class gibi daha özel alt türler bu çerçevenin dışında tutulmuştur.

Nested class kullanmanın pratik gerekçesi çoğunlukla kapsülleme ile ilgilidir. Bir yardımcı sınıf yalnızca tek bir dış sınıf tarafından kullanılıyorsa, bu sınıfı ayrı bir dosyada tutmak yerine dış sınıfın içine gömmek, ilişkiyi kod düzeyinde de görünür kılar. Örneğin bir LinkedList implementasyonundaki Node sınıfı ya da bir Map implementasyonundaki Entry sınıfı, tipik olarak nested class olarak tasarlanır çünkü bu sınıfların dış sınıf dışında anlamlı bir varlığı yoktur. Hangi türün seçileceği ise doğrudan sınıfın dış sınıfa ne kadar bağımlı olması gerektiğine bağlıdır.

Bu ayrımı kavramak, nesne yönelimli programlamada sınıflar arası ilişkileri doğru modellemenin temel taşlarından biridir ve özellikle koleksiyon sınıfları, builder desenleri ve iterator implementasyonları gibi sık karşılaşılan senaryolarda pratik önem taşır. Konuyu sıfırdan ve uygulamalı biçimde öğrenmek isteyenler için birebir Java dersleri kapsamında bu tür nesne yönelimli tasarım konuları adım adım ele alınır. İlerleyen bölümlerde syntax farkından başlayarak, dış sınıf referansı taşıma davranışına ve bunun bellek üzerindeki etkilerine kadar her ayrım tek tek incelenecek.

Syntax Farkı: static Anahtar Kelimesi

İki yapı arasındaki en görünür fark, sınıf tanımının başına static anahtar kelimesinin eklenip eklenmediğidir. Bir nested class tanımlanırken static kullanılırsa bu sınıf static nested class olur; kullanılmazsa varsayılan olarak inner class (non-static nested class) kabul edilir. Bu tek kelimelik fark, derleyicinin sınıfı nasıl ele alacağını baştan belirler.

Aşağıdaki örnek, aynı dış sınıf içinde tanımlanmış iki farklı nested class'ı göstermektedir:

public class Kutuphane {
    private String kutuphaneAdi = "Merkez Kutuphane";

    // static nested class: dis sinifa bagimsiz
    static class Rapor {
        void yazdir() {
            System.out.println("Rapor olusturuldu.");
        }
    }

    // inner class: dis sinifa bagli
    class Kitap {
        String baslik;
        Kitap(String baslik) {
            this.baslik = baslik;
        }
        void bilgiGoster() {
            System.out.println(baslik + " - " + kutuphaneAdi);
        }
    }
}

Burada Rapor sınıfı static anahtar kelimesiyle tanımlandığı için dış sınıftan tamamen bağımsız davranır; Kitap sınıfı ise bu kelimeden yoksun olduğu için dış sınıfın bir üyesi gibi çalışır ve dış sınıfın kutuphaneAdi alanına doğrudan erişebilir. Syntax düzeyinde tek fark bir anahtar kelime olsa da, bu kelimenin varlığı ya da yokluğu derleyicinin arka planda ürettiği bytecode'u ve sınıfın örneklenme kurallarını kökten değiştirir. Bir sonraki bölümde bu farkın en somut sonucu olan dış sınıf referansı taşıma davranışı ele alınacaktır.

Dış Sınıf Referansı Taşıma Farkı

İnner class ile static nested class arasındaki en kritik ayrım, inner class'ın her örneğinin kendisini oluşturan dış sınıf örneğine örtük (implicit) bir referans taşımasıdır. Bu referans derleyici tarafından otomatik olarak eklenir ve inner class örneğinin dış sınıfın alanlarına, metotlarına doğrudan erişebilmesini sağlar. Static nested class ise böyle bir referans taşımaz; çünkü tanımı gereği dış sınıfın belirli bir örneğine değil, sınıfın kendisine bağlıdır. Bu yüzden static nested class yalnızca dış sınıfın static üyelerine erişebilir, örnek (instance) üyelerine erişemez.

Bu davranış farkı, örnekleme sözdiziminde de kendini gösterir. Bir inner class örneği oluşturmak için önce dış sınıfın bir örneğine sahip olmak gerekir:

Kutuphane kutuphane = new Kutuphane();
Kutuphane.Kitap kitap = kutuphane.new Kitap("Java Temelleri");
kitap.bilgiGoster();

Kutuphane.Rapor rapor = new Kutuphane.Rapor();
rapor.yazdir();

Görüldüğü gibi Kitap sınıfının bir örneğini yaratmak için kutuphane.new Kitap(...) söz dizimi kullanılır; bu, JVM'in arka planda dış sınıf referansını inner class örneğine bağladığının açık göstergesidir. Rapor sınıfı için ise böyle bir bağımlılık yoktur, doğrudan new Kutuphane.Rapor() ile örnek oluşturulabilir.

Bu örtük referansın taşınması, yalnızca sözdizimsel bir ayrıntı değildir; her inner class örneği bellekte dış sınıf örneğine bir işaretçi tuttuğu için, dış nesne gerekmediği hâlde çöp toplayıcı tarafından hemen temizlenemeyebilir. Bu davranış farkının pratikte nereye etki ettiğini, canlı örnekler üzerinden çalışarak görmek isteyenler video Java eğitimleri içindeki nesne yaşam döngüsü konularından faydalanabilir. Bir sonraki bölümde bu referans farkının örnekleme ve erişim kuralarına nasıl yansıdığı daha ayrıntılı biçimde ele alınacaktır.

Örnekleme ve Erişim Farkları

İki yapı arasındaki en somut fark, bir nesne örneği oluşturulurken ortaya çıkar. static nested class dış sınıfın bir örneğine ihtiyaç duymadan doğrudan üretilebilirken, inner class örneklenmeden önce mutlaka var olan bir dış sınıf nesnesine bağlanmak zorundadır. Bu fark, derleyicinin ürettiği bytecode'a kadar yansır ve iki yapının birbirinin yerine geçemeyeceğini açıkça gösterir.

Örnekleme sürecini adım adım karşılaştırmak gerekirse:

  1. Outer.StaticNested nesne = new Outer.StaticNested(); satırında görüldüğü gibi static nested class, dış sınıf adı üzerinden doğrudan çağrılır; herhangi bir Outer örneğine gerek yoktur.
  2. Inner class için önce Outer outer = new Outer(); ile dış sınıftan bir örnek üretilir.
  3. Ardından Outer.Inner inner = outer.new Inner(); sözdizimiyle, üretilen bu dış örnek üzerinden inner class örneklenir.
  4. Bu ikinci adım atlanırsa derleyici hata verir; çünkü inner class'ın kurucusu arka planda dış sınıf referansını da parametre olarak taşır.

Erişim tarafında da benzer bir ayrım geçerlidir. Static nested class, dış sınıfın yalnızca static alanlarına ve metotlarına doğrudan erişebilir; dış sınıfın örnek (instance) değişkenlerine ulaşmak isterse, tıpkı bağımsız bir sınıf gibi, açıkça bir Outer nesnesi referansı almak zorundadır. Inner class ise dış sınıfın hem static hem de non-static üyelerine ekstra bir referans tanımlamadan, doğrudan erişebilir; çünkü kendi içinde örtük olarak Outer.this referansını taşır. Bu davranış, inner class'ı dış nesnenin durumuyla sürekli etkileşen yardımcı bileşenler için pratik kılar, ancak aynı zamanda bir sonraki bölümde ele alınacak bellek maliyetinin de kaynağıdır.

Bellek ve Tasarım Açısından Sonuçlar

Inner class'ın dış sınıfa örtük referans taşıması, sadece erişim kolaylığı sağlamakla kalmaz, aynı zamanda nesnenin yaşam döngüsünü doğrudan etkiler. Bir inner class örneği canlı kaldığı sürece, içinde tuttuğu gizli Outer.this referansı nedeniyle dış sınıf nesnesi de çöp toplayıcı (garbage collector) tarafından temizlenemez. Özellikle olay dinleyicileri (listener), geri çağırma (callback) nesneleri veya uzun ömürlü koleksiyonlara eklenen inner class örneklerinde bu durum, beklenmedik memory leak senaryolarına yol açabilir; dış nesne mantıksal olarak artık kullanılmıyor gibi görünse de bellekte tutulmaya devam eder.

Static nested class bu riski taşımaz. Dış sınıfla arasında herhangi bir örtük bağ olmadığı için, static nested class örneği kendi yaşam döngüsünü bağımsız sürdürür ve dış sınıf örneğinden tamamen ayrı olarak çöp toplamaya konu olabilir. Bu bağımsızlık, static nested class'ı hem daha hafif hem de daha öngörülebilir kılar; nesnenin ne zaman ve neden bellekte tutulduğunu izlemek, gizli bir dış referans olmadığı için çok daha kolaydır. Bu tür yapısal ayrımların pratikte nasıl bir performans ve tasarım farkı yarattığını daha iyi kavramak isteyenler, konuyu küçük örnekler üzerinde kendi başına test ederek pekiştirebilir; bu noktada seviyeni ölçmek için Java bilgi testi üzerinden nesne yaşam döngüsü ve OOP kavramlarına dair bilgini kontrol edebilirsin.

Tasarım açısından bakıldığında, bu bellek farkı bir tercih meselesinden çok bir sorumluluk meselesidir. Bir nested class dış nesnenin durumuna gerçekten ihtiyaç duymuyorsa, onu inner class olarak tanımlamak gereksiz bir bağımlılık ve gereksiz bir bellek maliyeti yaratır. Bu nedenle modern Java kod tabanlarında yaygın kabul gören yaklaşım, dış nesne durumuna erişim zorunlu değilse nested class'ı varsayılan olarak static tanımlamak, yalnızca gerçekten gerekiyorsa inner class'a yönelmektir.

Kullanım Senaryoları ve Karar Tablosu

Bu iki yapının hangi senaryoda tercih edileceği, büyük ölçüde nested class'ın dış nesnenin durumuna ihtiyaç duyup duymadığına bağlıdır. Builder deseni, static nested class kullanımının klasik örneğidir; çünkü builder nesnesi, henüz inşa edilmemiş bir dış nesnenin durumuna değil, kendi topladığı parametrelere dayanır. Bir Product sınıfının içine tanımlanan static class Builder, dış sınıf örneği olmadan adım adım nesne inşa etmeyi mümkün kılar ve bu bağımsızlık builder'ın amacıyla doğrudan örtüşür.

Buna karşılık, dış sınıfın iç durumuna sürekli erişmesi gereken yardımcı bileşenler için inner class daha uygun bir seçimdir. Bir koleksiyonun kendi iterator uygulamasını tanımlaması ya da bir arayüz bileşeninin kendi listener sınıfını barındırması, inner class'ın örtük dış referansından doğrudan fayda sağladığı durumlardır; iterator, dış koleksiyonun eleman dizisine ve indeksine erişmek zorunda olduğu için bu bağı ekstra parametre taşımadan kurabilmesi tasarımı sadeleştirir.

İki yapı arasındaki temel farkları özetleyen bir karşılaştırma aşağıdaki gibidir:

Özellik Static Nested Class Inner Class
Dış sınıf örneğine bağımlılık Yok Zorunlu
Örnekleme sözdizimi new Outer.Nested() outer.new Inner()
Dış sınıfın static üyelerine erişim Doğrudan Doğrudan
Dış sınıfın non-static üyelerine erişim Dolaylı (referans ile) Doğrudan
Bellek bağımsızlığı Yüksek Düşük (gizli referans nedeniyle)
Tipik kullanım alanı Builder deseni, yardımcı veri yapıları Iterator, listener, olay işleyicileri

Bu tablo, hangi yapının seçileceğine karar verirken sorulması gereken tek soruyu netleştirir: nested class, dış nesnenin durumuna gerçekten ihtiyaç duyuyor mu? Cevap evetse inner class, hayırsa static nested class daha tutarlı bir tasarım kararıdır.

Kod Örneğiyle İki Yapının Karşılaştırması

Teorik farkları somutlaştırmanın en net yolu, aynı dış sınıf içinde bir static nested class ile bir inner class'ı yan yana tanımlayıp ikisini de örneklemektir. Aşağıdaki Car sınıfı, aracın teknik özelliklerini tutan bağımsız bir Specification static nested class'ı ile dış sınıfın örnek alanlarına doğrudan erişen bir Engine inner class'ını bir arada barındırır.

public class Car {
    private String brand;
    private int horsePower;

    public Car(String brand, int horsePower) {
        this.brand = brand;
        this.horsePower = horsePower;
    }

    // Static nested class - dis sinif ornegine ihtiyac duymaz
    static class Specification {
        private String category;

        public Specification(String category) {
            this.category = category;
        }

        public String describe() {
            return "Kategori: " + category;
        }
    }

    // Inner class - dis sinif ornegine baglidir
    class Engine {
        public String describe() {
            return brand + " markasinin motoru " + horsePower + " beygir guce sahip.";
        }
    }

    public static void main(String[] args) {
        // Static nested class ornekleme: dis sinif nesnesi gerekmez
        Car.Specification spec = new Car.Specification("Sedan");
        System.out.println(spec.describe());

        // Inner class ornekleme: once dis sinif nesnesi olusturulur
        Car car = new Car("Toyota", 132);
        Car.Engine engine = car.new Engine();
        System.out.println(engine.describe());
    }
}

Bu kodda iki yapının pratikteki farkı satır satır görülebilir. Specification nesnesini oluştururken herhangi bir Car örneğine ihtiyaç duyulmaz; new Car.Specification("Sedan") ifadesi yeterlidir çünkü static nested class dış sınıfla yalnızca isim uzayı (namespace) düzeyinde ilişkilidir. Buna karşılık Engine sınıfını örneklemek için önce somut bir car nesnesi yaratılır, ardından car.new Engine() söz dizimiyle bu nesneye bağlı bir inner class örneği üretilir. Engine.describe() metodunun içinde brand ve horsePower alanlarına herhangi bir parametre geçirilmeden, sanki kendi alanlarıymış gibi erişilebilmesi, inner class'ın gizli sakladığı dış sınıf referansının işlevini gösterir.

Bu tür yapısal ayrımları küçük konsol örnekleriyle değil, gerçek sınıf hiyerarşilerine sahip projelerde deneyimlemek kalıcı öğrenmeyi sağlar; Java özel ders programı kapsamında bu tarz nested class senaryoları öğrencinin kendi yazdığı projeler üzerinden birebir işlenir. Kodu derleyip çalıştırdığınızda konsolda önce Specification nesnesinin kategori bilgisi, ardından Engine nesnesinin dış sınıf alanlarını kullanan açıklaması sırayla basılır; bu da iki sınıfın yaşam döngüsünün birbirinden bağımsız fakat aynı derleme biriminde yönetilebildiğini gösterir.

Sık Sorulan Sorular

Static nested class ile inner class arasındaki temel fark nedir?

Static nested class dış sınıfa yalnızca bildirim düzeyinde bağlıdır ve bağımsız örneklenir; inner class ise her örneğinde belirli bir dış sınıf nesnesine bağlanır ve o nesnenin alanlarına doğrudan erişebilir.

Inner class neden dış sınıf örneğine ihtiyaç duyar?

Inner class, derleyici tarafından içine gizli bir dış sınıf referansı gömülerek üretilir; bu referans olmadan dış sınıfın örnek alanlarına ve metotlarına erişim mümkün olmaz, bu yüzden örnekleme sırasında disNesne.new IcSinif() söz dizimi zorunludur.

Static nested class dış sınıfın static olmayan metoduna erişebilir mi?

Hayır, static nested class herhangi bir dış sınıf örneğine bağlı olmadığı için dış sınıfın örnek (static olmayan) alanlarına ve metotlarına doğrudan erişemez; erişim ancak dışarıdan bir Car nesnesi parametre olarak geçirilirse mümkün olur.

Hangi durumda static nested class tercih edilmeli?

Yardımcı sınıf dış sınıfın verisine değil yalnızca mantıksal gruplamasına ihtiyaç duyuyorsa, örneğin bir builder deseni ya da bağımsız bir veri taşıyıcı (DTO benzeri yapı) tasarlanıyorsa static nested class tercih edilir; bu yaklaşım gereksiz dış sınıf bağını ortadan kaldırır.

Inner class kullanımı memory leak'e nasıl yol açabilir?

Inner class örneği, içindeki gizli referans üzerinden oluşturulduğu dış sınıf nesnesini canlı tutar; inner class nesnesi bir koleksiyonda veya uzun ömürlü bir yapıda tutulup unutulursa, dış sınıf nesnesi artık kullanılmasa bile çöp toplayıcı tarafından temizlenemez ve bellekte gereksiz yere birikir.

Static nested class ile inner class arasındaki seçim, sonuçta sınıfın dış nesneye ne kadar bağımlı olması gerektiğine dair bilinçli bir tasarım kararıdır; bu ayrımı doğru kurmak, Java'da hem daha okunabilir hem de bellek açısından daha öngörülebilir kod yazmanın temel adımlarından biridir. Nested class kavramını OOP'nin diğer yapı taşlarıyla birlikte pekiştirmek isteyenler Java bilgi testi üzerinden mevcut seviyelerini ölçebilir.

Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

İlgili Eğitimler

Berk Keskin — Yazılım Geliştirici ve Eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; bugün öğrencinin seviyesine ve hedefine göre şekillenen sürdürülebilir öğrenme sistemleri tasarlıyor. 300'den fazla kişiye ezber değil, düşünerek kod yazmayı öğretti — Berk Akademi'de izlemeye değil üretmeye dayalı öğrenme kültürünü o kuruyor.

WhatsApp Hemen Ara