18 Şubat 2012 Cumartesi

static block


Java da "static" anahtar  kelimesi kullanılarak; değişken,metot,blok ve hatta sınıf tanımlanabilir.
Sınıflar için "static" sadece inner class (iç sınıf) kullanımında geçerlidir.İnner classlar için ayrı bir yazı ele alacağım daha sonra.
Static değişkenler javada sınıf değişkenleri (class variable) olarak bilinir.Nesneye bağımlı değildir ve sınıfın ismiyle erişilir.
Static metodlar da sınıf metodlarıdır,nesne yaratmadan direk sınıf ismiyle çağırılır,tamami ile nesneden bağımsızdır.Static metotlar için en önemli nokta;static bir metot içerisinden static olmayan bir değişkene veya bir metoda erişilemeyeceğidir.Ama bunun tam tersi geçerlidir yani static olmayan bir metot içerisinden static bir değişkene veya metoda erişilebilir.
Bu önemli noktayı açıklamak gerekirse;bildiğiniz gibi normal static olmayan metotlar nesneye bağımlıdır ve nesne üzerinden çağrılırlar ama static metodlar yukarda bahsettiğimiz gibi nesneden bağımsızlardır.Bu yüzden static bir metot içerisinden nesneye bağımlı bir metot çağıramayız çünkü ortada nesne yoktur.
Ve bir önemli nokta daha static değişkenler,bloklar sınıf yüklenirken (class load)  oluşturulur ve sadece bir kez oluşturulur.
Gelelim asıl mevzuya yani static bloklara...
Static bloklar çok kullanılan bir yapı değildir,o yüzden çok bilinmezler.
Kullanım şekli :
public class Test {
    static{
           System.out.println("static block..");
     }
}
Static bloklar yukarda bahsedildiği gibi sınıf JVM (java virtual machine) tarafından class loader ile  yüklenirken çalıştırılır.
Ne için kullanılır ?
Static bloklar "initializer" gibi düşünülebilir,static değişkenlere ilk değerlerini vermek için kullanılır.
Örneğin:
public class Test {
    static int a;
    static{
           a = 5;
       }
}
Şöyle bir soru aklınıza gelebilir,neden static değişkeni oluştururken direk değerini vermiyoruz da blok içinde vermeye çalışıyoruz ?
Çünkü blok içinde dinamik birşey çalıştırmak isteyebilirz,örneğin if yapısını kullanabiliriz,bu yüzden değişkenin değeri bir koşula bağlı olabilir veyahut static bir dizi değişkenimizin olduğunu düşünelim,burdada for döngü yapısını kullanarak static bir dizinin ilk değerlerini vermek isteyebiliriz ve bunu sadece static blok kullanarak yapabiliriz.
Static blokları bir metot gibi düşünmek gerekir,sınıflar yüklenirken ve sadece bir kez çağrılan bir metot gibi...
Umarım faydalı olmuştur,başka bir yazıda görüşmek üzere...

synchronized method ve synchronized block


Java da 2 farklı senkronizasyon yöntemi vardır.Bunlar:
1- synchronized method : Bu da kendi içinde static-non static metod olarak ikiye ayrılır.Non static metodlar lock objesi olarak instance objesini tutarlar.Staticler ise class objesini lock olarak kullanır.
public synchronized void method(){
          ...
  }
public synchronized static void method(){
          ...
  }
2- synchronized block: Özel belirli bir lock objesi tutan statement lardır.
public void method(){
          synchronized (obj){
            ....
           }
  }
synchronized metodlar scope olarak bloklara göre daha geniştir.Bütün objeyi kilitlerler.Örneğin aşağıdaki kod parçasını incelersek:
public synchronized void method(){
          ...
  }
metod burda kilit olarak instance objesini kullanır,ve aşağıdaki kodla hemen hemen aynıdır:
public void method(){
          synchronized (this){
            ....
           }
  }
burda metod yerine blok kullanılmış,kilit objesi ise "this" anahtar sözcüğü ile objenin instance'i seçilmiştir.
Bu kullanımın bazı sakıncaları vardır,şöyleki;
eğer biz synchronized metod kullanırsak,kilit olarak objenin instance'ını seçmiş olacağız, bu da farklı bir threadin objenin diğer metodlarına erişmesini engelleyecek ve böylece istenmeyen bir durum ortaya çıkabilecek,bu durumda örnek vermek gerekirse,
Bir classın mesaj üreten bir  write metodu ve bu mesajların okunabilmesi için read metodu olsun,burda write metodunu tamamen synchronized edersek,bir thread write metodu içindeyken başka bir thread read metodunun içine giremez,diğer threadin write metodundaki işini bitirmesini beklemek zorundadır ve bu da hoş olmayan bir durumdur.Bu durumdan kurtulmanın en iyi yolu farklı 2 kilit objesi oluşturup synchronized block kullanmak.
public class Mesaj{

  public synchronized void write(String msg){
          ...
  }
  public synchronized void read(){
          ...
  }
}
bunun yerine :
public class Mesaj{
  private Object writeLock = new Object();
  private Object readLock = new Object();
  public void write(){
          synchronized(writeLock){
                ....
          }
  }
  public void read(){
          synchronized(readLock){
                ....
          }
  }
}
Bu ayrıntıya dikkat çekmek istedim,umarım faydalı olmuştur.
Diğer yazılarda görüşmek üzere...