ÖNEMLİ : Kendim için aldığım notlar. Umarım size de bir faydası olur. Kullanılan her bir makale referans olarak eklenmiştir.

Java'da Hafıza Modeli Serisi


  1. Java’da Hafıza Modeli 1 - İlkel Veri Tipleri(Primitive Types)
  2. Java’da Hafıza Modeli 2 - Nesneler
  3. Java’da Hafıza Modeli 3 - Nesneler
  4. Java’da Hafıza Modeli 4 - Kapsam(Scope)
  5. Java’da Hafıza Modeli 5 - Pass By Value / Pass By Reference
  6. Java’da Hafıza Modeli 6 - Java’da Statik ve Statik Olmayan Değişken ve Metotların Hafıza Yönetimi
  7. Java’da Hafıza Modeli 7 - String Interning Nedir, String Pool Nedir, == operatörü ve equals metodu Arasındaki Fark
  8. Java’da Hafıza Modeli 8 - Java’da Static Initializer nedir? - Java statik ilklendirici
  9. Java’da Hafıza Modeli 9 - Java’da Instance Initializer Nedir? - Java örnek ilklendirici
  10. Java’da Hafıza Modeli 10 - Java’da Neden BAZI durumlarda metot kullanmak yerine initializer’ı tercih ederiz?

Java Hafıza Modeli Örnek 1

Dilerseniz bir önceki yazıda değindiğimiz örneği bir adım öteye taşıyalım.

1
2
3
4
5
6
7
 public class Sample {
     public static void main(String[] args) {
         int m = 11;
         SampleTest sample1 = new SampleTest(1,m);
         SampleTest sample2 = new SampleTest(3,sample1.y);
     }
 }
1
2
3
4
5
6
7
8
9
10
 public class SampleTest {
     private int x;
     private int y;

     public SampleTest(int xx, int yy){
         this.x = xx;
         this.y = yy;
     }
     // ....
 }

Sizce bu sorunun cevabı hangisi olurdu?


Java reference variable assignment(java referans değişkeni atama)


Java reference variable assignment(java referans değişkeni atama)

Görüleceği üzere 2 adet new, bize heap alanında 2 farklı nesnenin oluştuğunu söylüyor. Burası önemli!!! Her yeni bir new anahtar kelimesi bize yeni bir nesneyi işaret etmektedir. Bu sebepten ötürü A şıkkını elemeliyiz. Çünkü iki nesne de heap de tek bir nesneyi işaret etmektedir. Halbuki bize 2 farklı nesne gerekiyor.

B ve D seçeneklerinde de bir terslik var. Bir önceki bölümden de hatırlarsanız, biz, okla gösterimi heap alanındaki nesneyi stack’te kimin temsil ettiğini göstermek için kullanıyorduk. Yani @ işareti ile başlayan nesnenin id’si stack’teki referansın içinde tutmak yerine, bu gösterimi ok ile yapmıştık. Ama bu seçeneklerde ilkel bir tipe sahip olan m değişkeninin değerini heap’te yarattığımız nesnelere vermeye çalışıyoruz. Yani bir ilkel değişken atama söz konusu! Bu sebeple C seçeneği doğru seçenektir.

Doğru seçenek olan C cevabını scope dersine geçmeden önce bir adım öteye taşıyarak açıklamak istiyorum. Birinci kod bloğunun 3.satırında m isminde bir değişkene bir int ilkel tipli bir sayı atıyoruz. Buraya kadar her şey normal! 4.satırda ise aslında bildiğimiz gibi heap'de bir nesne yaratma işlemi vardır. Yalnız burada bir şeye değinmek istiyorum. Nesne oluştururken nesnenin aldığı parametreler için hiç görsel sunmadık. SampleTest sınıfı constructor’ına iki tane parametre almaktadır. Bunlar xx ve yy parametreleridir. 4.satırda nesne oluştururken parametrelerden yy olanına dikkat ettiyseniz m değişkeninin sahip olduğu değeri atamışız. Diğerine ise normal bir sayı!!! Yani bu değerlere stack alanında atama yapıldıktan sonra, constructor aracılığı ile heap’de yer alan nesnenin x ve y değerleri ilklendirilmektedir. Sonrasında ise bu xx ve yy parametreleri stack’den silinir. Aslında bu kısım tam olarak böyle değil, scope konusunda, kurucuları(constructor) da işin içine katıp daha farklı bir görsel resim sunmak istiyorum. Buradaki xx ve yy parametreleri geçici değişkenlerdir. Bazen intermediate değişkenler olarak da anılır. Ben ise bazen kullan-at değişkenleri diyorum. Çünkü asıl işleri olan constructor ilklendirmesini yaptıktan sonra yok olacaklardır. Scope konusunda henüz geçmediğimiz için şimdilik böyle olduğunu varsayın.


Java reference variable assignment(java referans değişkeni atama)

5.satırda da benzer şekilde bir nesne oluşturma işlemi gerçekleşmektedir. Aynı şekilde SampleTest sınıfı constructor’ına iki tane parametre almaktadır. Bunlar bildiğiniz gibi xx ve yy parametreleridir. Yalnız bu sefer yy parametresi, sample1 değişkeninin/referansının işaret ettiği nesnenin y değikeninin sahip olduğu değeri almaktadır. Yalnız yeşil okla gösterdiğim hafıza modelimizin içinde yer almamaktadır. Buradaki amacım, constructor’da ilklendirme yapıldığını göstermek ve bu işlem sonrasında xx ve yy değerlerinin silindiğini belirtmektir. Aslında scope konusuna giriş yapınca bazı şeyler kafanızda daha da netleşecektir. Şimdilik aşağıdaki şekilden ne söylemek istediğimi daha net anlayabilirsiniz.


Java reference variable assignment(java referans değişkeni atama)

Java Hafıza Modeli Örnek 2

Benzer bir soruyu çözmeye çalışalım. Sizce cevap nedir?

1
2
3
4
5
6
7
8
9
public class Sample {
    public static void main(String[] args) {
        SampleTest sample1 = new SampleTest(1,2);
        SampleTest sample2 = new SampleTest(3,4);
        sample1 = sample2;
        sample1.x = 20;
        System.out.println(sample2.x + ", "+ sample2.y);
    }
}
1
2
3
4
5
6
7
8
9
10
public class SampleTest {
    private int x;
    private int y;

    public SampleTest(int xx, int yy){
        this.x = xx;
        this.y = yy;
    }
    // ....
}

Birinci kod bloğunun 3. ve 4. satırlarında hafıza modeli aşağıdaki gibidir.


Java reference variable assignment(java referans değişkeni atama)

Yalnız 5. satırda bir atama işlemi yapılmaktadır. Yani sample1 referansının sahip olduğu id sample2‘nin id‘si ile değiştiriyoruz. Yani heap alanında sample1 referansının işaret ettiği nesne 4.satırda oluşturduğumuz nesneyi işaret etmektedir. Yani okla göstermeden önce @ işareti ile başlayan id ile gösterelim.


Java reference variable assignment(java referans değişkeni atama)

Id ile gösterimi gözünüzde canlandırabildiyseniz, okla gösterimden devam edebiliriz. Ama tekrar hatırlatmakta yarar var. Aslında okla gösterim az önceki @ işareti ile başlayan sayıyının ne anlama geldiğini resmetmektedir. Yani bu sayı bir nevi objenin heap alanındaki lokasyonunu bize verir. Gerçekte sayı ile gösterim daha doğrudur. Ama okla yaptığımız gösterim, arka planda olanı daha net anlamanıza yardımcı olacağını düşünüyorum.


Java reference variable assignment(java referans değişkeni atama)

Buraya kadar olan biteni anladığınızı umuyorum. Artık 2 referans da tek bir nesneyi işaret etmektedir. Haliyle ilk oluşturduğumuz nesne heap alanında boşta kalacaktır ve tam da bu noktada garbage collector devreye girer. Hatırlarsanız garbage collector’un görevi boşta kalan bu nesneleri temizlemekti.

Kod bloğunun sample1.x = 20; 6.satırı olan bu yerde ise yeni bir atama işlemi ile karşılaşıyoruz. sample1 referansı artık sample2 referansı ile aynı nesneyi işaret ettiğine göre sample.x ile yaptığımız aslında aşağıdaki işlemdir. Yani ikinci nesnenin x değeridir.


Java reference variable assignment(java referans değişkeni atama)

Son satırda ise sample2 referansının işaret ettiği nesnenin x ve y değerlerini ekrana yazdırma işlemi bulunmaktadır. Bir önceki satırda yaptığımız işlem aslında sample2 referansının tuttuğu nesneyi de etkilediği için ekrana yazdıracağımız sonuç aşağıdaki gibi olacaktır.

1
20, 4

Referanslar