Bir önceki makalede statik bileşenler hakkında bilgiler vermiştik. Bu gün statik olmayan bileşenler hakkında bilgi aktarmaya çalışacağım.
İlk önce, en basit anlamda sınıf (class) ve nesne (object) tanımlarını yaparak konuya giriş yapalım.
Sınıf (Class): Oluşturulacak olan nesnelerin model/şablon/plan türüdür.
Nesne (Object): Sınıfın bir örneğidir. Sınıfın gerçek zamanlı bir kopyasıdır.
Yukarıdaki basit tanımlamalarla bir şey anlaşılmamış ise, aşağıdaki örneği okuyunuz. A sınıfı bir plandır. Bu plan ile istenilen sayıda nesne inşa edilebilir.
Statik olmayan değişkenler ve statik olmayan metotlar bir sınıfa ait statik olmayan bileşenlerdir. Bunlara aynı zamanda sınıfın örnek (instance) bileşenleri de denir. Statik olmayan bileşenler nesne belleğinde (Object memory) depolanırlar. Her bir nesne kedilerine ait statik olmayan bileşenlerin bir kopyasına sahip olacaklardır. Ancak statik bileşenler bu sınıftaki tüm nesneler için ortak olacaktır, kopyaları oluşturulmayacaktır.
Şimdi örneğimizi inceleyelim.
class A {
int statikOlmayanDegisken;
static int statikDegisken;
static void statikMetot() {
System.out.println(statikDegisken);
// System.out.println(statikOlmayanDegisken);
}
void statikOlmayanMetot() {
System.out.println(statikDegisken);
System.out.println(statikOlmayanDegisken);
}
}
class MainClass {
public static void main(String[] args) {
A.statikDegisken = 10;
// A.statikOlmayanDegisken = 10;
A.statikMetot();
// A.statikOlmayanMetot();
A a1 = new A();
A a2 = new A();
System.out.println(a1.statikOlmayanDegisken);
System.out.println(a1.statikDegisken);
a1.statikOlmayanMetot();
a1.statikMetot();
System.out.println(a2.statikDegisken);
a1.statikDegisken = 20;
System.out.println(a2.statikDegisken);
}
}
Yukarıdaki örneği adım adım inceleyerek bellek kullanımına bakalım.
Adım 1:
Eğer “java MainClass” komutunu çalıştırırsak, java komutu belleği stack ve heap olmak üzere iki parçaya böler. java komutu ilk çalışmaya başladığında MainClass’ı heap bellek içerisine koyar. MainClass’a rastgele biraz bellek alanı tahsis edilir. Bütün statik üyeler class memory’ye yüklenir. MainClass içinde sadece bir tane statik üye bulunmaktadır. Bu üye main() metodudur. Bu metot class memory içine yüklenir. Statik üyelerin yüklenmesinden sonra, SIB çalıştırılır. Ancak MainClass içinde SIB bulunmamaktadır. Bu sebeple java komutu direkt olarak main() metodunu çalıştırılması için çağıracaktır.
Adım 2:
main() metodu çalıştırılması için yığına (stack) alınır. İlk ifade (satır 18 A.statikDegisken = 10;
) A sınıfını referans eder. İlk aşamada A sınıfı heap hafızada yüklü olup olmadığı kontrol edilir. Eğer yüklü değilse A sınıfı heap belleğe yüklenir. A sınıfına rastgele biraz bellek alanı tahsis edilir. A sınıfının bütün statik üyeleri, yani statikDegisken ve statikMetot() bu bellek alanına yüklenir. “statikDegisken” in ilk varsıyılan değeri 0 (sıfır) dır. A sınıfı içinde hiç bir SIB bulunmamaktadır. Statik üylerin yüklenmesinden sonra, main() metodu, A sınıfı içindeki statikDegisken‘in değerini 10 olarak ayarlar.
main() metodu içindeki ikinci ifade (satır 19 // A.statikOlmayanDegisken = 10;
) yorum haline getirilmiştir. Çünkü, statik olmayan üyeler sınıf adı kullanılarak referans edilemezler. Statik olmayan üyeler nesne belleğinde tutulurlar. Bu sebeple sadece nesneler aracılığı ile örnekleri (instance) erişilebilir olur.
Adım 3:
20. satırda A sınıfı içindeki statikMetot çağrılıyor. statikMetot çalıştırılması için yığına aktarılıyor. statikMetot’un ilk ifadesi (satır 6 System.out.println(statikDegisken);
) consola statikDegisken’in değerini yazdırıyor. Yani consola “10” yazılıyor.
Bir sonraki ifade (satır 7 // System.out.println(statikOlmayanDegisken);
) yorumlanmıştır. Çünkü, statik olmayan üyeler statik metotlar içinden direkt olarak kullanılamazlar. Çünkü, statik olmayan üyeler nesne belleğinde depolanırlar. Bunları kullanmak için nesneleri oluşturmak gerekmektedir. Sadece nesneler aracılığı ile referans edilebilirler.
statikMetot içinde başka ifade kalmadığı için bu metot stack hafızadan atılır.
Adım 4:
main() metoduna geri geliyoruz. Bir sonraki ifade (satır 21 // A.statikOlmayanMetot();
) yorumlanmıştır. Çünkü, statik olmayan üyeler sınıf adı kullanılarak referans edilemezler. Bir sonraki ifade (satır 23 A a1 = new A();
) A sınıfı türünden bir nesne oluşturuyor. Rastgele biraz bellek alanı tahsil edilir. A sınıfına ait bütün statik olmayan üyeler (statikOlmayanDegisken ve statikOlmayanMetot()) bu nesne hafıza alanına yüklenirler. ‘statikOlmayanDegisken‘ bir global değişken olduğu için ilk varsayılan değeri 0 (sıfır) dır. A sınıfını referans eden değişkenin adı a1 dir. Bu değişken main() metodu içinde oluşturulur. Bu değişken yeni oluşturulan nesneyi işaret eder.
Aynı şekilde, a2 nesnesi oluşturuluyor (satır 24 A a2 = new A();
). Bir sonraki ifade ile (satır 26 System.out.println(a1.statikOlmayanDegisken);
) a1 e ait statikOlmayanDegisken değeri olan 0 (sıfır) yazdırılıyor. Bir sonraki ifade (satır 27 System.out.println(a1.statikDegisken);
) içinde statikDegisken değeri olan 10 yazdırılıyor.
27. satırda ilginç bir durum var. Bu satırda belirtilen statikDegisken’e A.statikDegisken seklinde erişilebilirken a1.statikDegisken seklinde kullanılmıştır. Burada bir hata oluşmaz. Derleyici bir sınıf örneği içerisinden statik bir üyeye erişmek için yazılmış olan kod ile karşılaşırsa, otomatik olarak o bölümü değiştirir. Yani a1.statikDegisken bölümü, derleyici tarafından A.statikDegisken olarak yorumlanır.
Bir sonraki ifadede a1 nesnesindeki statikOlmayanMetot() çağırılıyor.
Adım 5:
a1 e ait statikOlmayanMetot() çalıştırılmak üzere yığına gönderiliyor. İlk ifade (satır 11 System.out.println(statikDegisken);
) A sınıfındaki statikDegisken in değeri olan 10’u konsola yazdırır. İkinci ifade ise (satır 12 System.out.println(statikOlmayanDegisken);
) a1 nesnesine ait olan statikOlmayanDegisken değeri “0” (sıfır) konsola yazdırılıyor. statikOlmayanMetot() içinde başa bir ifade kalmadığı için yığından atılıyor.
Adım 6:
main() metodu tekrar kontrol ediliyor ve A sınıfı içerisinde bulunan statikMetot() çalıştırılmak üzere yığına atılıyor. statikMetot() ilk ifadesi (satır 6 System.out.println(statikDegisken);
) “statikDegisken” değişkeninin değeri konsola yazdırılıyor. statikDegisken değeri 10 dur. Bu ifade çalıştırıldıktan sonra statikMetot() bellekten atılıyor.
Adım 7:
main() metodu tekrar kontrol ediliyor. a2 nesnesine ait statikDegisken değeri konsola yazdırılıyor (satır 31 System.out.println(a2.statikDegisken);
). statikDegisken’in değeri 10 dur. Sonraki ifade ile a1‘e ait statikDegisken değeri 20 yapılıyor. a2‘ye ait statikDegisken değeri yazdırıldığında ekrana 20 yazdığı görülüyor. Yukarıda anlatıldığı gibi a1.statikDegisken ifadesi compiler tarafından A.statikDegisken olarak yorumlanır. Yani A sınıfından oluşturulan bütün nesnelerin statikDegisken degeri ortak olacaktır.
Son olarak çalıştırılacak başka bir satır kalmadığı için main() metodu hafızadan atılır.
Çıktı:
10
0
10
10
0
10
10
20
İlk Yorumu Siz Yapın