24 Mart 2012 Cumartesi

Static


Sinif ve Obyekt Deyişenleri
Statik acar sozunu islederek yaradilan deyisenler obyekt deyiseni deyil “sinif deyiseni” olaraq adlandirilirlar.Bu deyisenler obyekte aid deyil,sinife aid melumatlari dasiyir.Sinif deyisenleri icinde teyin etdiyimiz sinifden hecbir obyekt yaratmamis olsa bele yaddasda yer tutar.Obyekt deyiskenleri ise ancaq bir obyekt teyin etdiyinde yaddasda yer tutar.Bu iki nov deyisenin ayrildigi bir basqa noqte de var.Bu odur ki,sinif deyiseni olan sinifden nece dene obyekt yaratsaq da yaddasda bir dene sinif deyiseni vardir.Indi bunlari bir misalda daha yaxsi anlamaga calisaq.
package com.javagelistir.meqale;

public class Telebe {
private String ad; // Obyekt deyiseni
private int yas;             // Obyekt deyiseni
private String TelebeNo; // Obyekt deyiseni
public static int TelebeSayi = 0; // Sinif deyiseni

public Telebe(String ad, int yas, String TelebeNo) {

this.ad = ad;
this.yas = yas;
this.TelebeNo =TelebeNo;

// Her obyekt yaradildiginda sinif deyisenini artiririq.
TelebeSayi++;
}
}
Burada 3 dene obyekt deyişeni, 1 dene de sınıf deyişeni ehtiva eden bir sinifimiz var ve bu sinifin her bir numunesi yaradildiginda yardiciı (constructor) metod içerisinde sinif deyişeninin deyerinin artırıldığını görürük. Indi asagidaki koda baxaq.
package com.javagelistir.meqale;

public class Program {

public static void main(String args[]) {

System.out.println("Baslangicda telebe sayi: " + Telebe.telebeSayi);

// iki dene telebe obyekti yaradaq
Telebe telebe 1 = new Telebe ("Obi-Wan Kenobi", 19, "2010001");
Telebe telebe 2 = new Telebe ("Anakin Skywalker", 16, "2010002");

int tlbSayi = Telebe. telebeSayi;
System.out.println("telebe sayi (Sinif ustunden): " + tlbSayi);

tlbSayi = telebe 1. telebeSayi;
System.out.println("telebe sayi (Ilk obyekt ustunden): " + tlbSayi);

tlbSayi = telebe 2. telebeSayi;
System.out.println("telebe sayi (Ikinci obyekt ustunden): " + tlbSayi);
}
}
Yuxaridaki kod isledildiyinde asagidaki netice alinacaq.
Baslangicda telebe sayi: 0
Telebe sayi (Sinif ustunden): 2
Telebe sayi (İlk obyekt ustunden): 2
Telebe sayi (İkinci obyekt ustunden): 2
Koddan da göreceyiniz kimi static sinif deyişkenlerine hem sinif adı ile, hem de o sinifden yaradılmış obyekt referansları ile catmaq mümkündür. Ancaq hansi yolla catsaqda, sinif deyişeni tek bir dene olduğu ucun catilan yaddas sahesi eynidir. Helelik hecbir obyekt yaradilmamisken sinif adi ile catdigimiz sinif deyiskenimiz ilk deyeri olan 0-I verecekdir.     Her bir obyekt yaratdigimizda ise sinif değyişkenimiz bir artmaqdadır. Sinif deyişkenleri bu numunede olduğu kimi yaradilan obyekt sayını tutmaq ucun tez tez istifade olunmaqdadir. Numunede 2 dene obyekt yaradib sinif deyisenimizin qiymetini 2 etmis oluruq. Daha sonra bu sıinif deyişkenine hem sinif adı ile, hem de obyekt referansları ile catib mezmunu yazdiririq ve neticede bu 3 catmada da eyni neticeni aliriq.Gorunurki artirila deyisken sinif deyiseni oldugu ucun etdiyimiz deyisiklik obyektde musteqildir.
Static Metodlar
Indi ise static acar sozunun başqa bir islenme qaydasi olan static metodlara baxaq. Normal halda bir sinifdeki bir metodu isletmek isteyirikse, evvelce o sinifi istifade ederek bir obyekt yaratmali, sonra bu obyekt referansı üzerinden metodu çağırmalıyıq. Ancaq deyişkenlerde olduğu kimi metotlar ucun de static kelmesini istifade ederek obyektlerden musteqil sinif metodlari yaza bilerik. Sinif metodlarını çağırmaq ucun o sinifden bir obyekt yaratmagimiz lazim gelmez. Deyişenlere catarmis kimi birbasa sinif adi ile bu metodları çağırmagımız mümkündür. Indi aşağıdaki kodu inceleyek.
package com.javagelistir.meqale;

public class Telebe {

private String ad; // Obyekt deyiseni
private int yas;             // Obyekt deyiseni
private String TelebeNo; // Obyekt deyiseni
public static int TelebeSayi = 0; // Sinif deyiseni

public Telebe(String ad, int yas, String TelebeNo) {

this.ad = ad;
this.yas = yas;
this.TelebeNo =TelebeNo;

// Her obyekt yaradildiginda sinif deyisenini artiririq.
TelebeSayi++;
}
public static int getTelebeSayi () {
return TelebeSayi;
}
}
Bu kodun ilk verdiyim Telebe sinifinden tek ferqi elave olunan yeni bir static metod. İlk numunede public olaraq elan etdiyimiz sinif deyişenimize birbasa adiyla catarken, bu defe sinif deyişenini private edib static bir metod üzerinden catiriq.  Bu sinifi test etmek ucun aşağıdaki kodu isletecik.
package com.javagelistir.meqale;

public class Program {

public static void main(String args[]) {

System.out.println("Baslangicda telebe sayi: " + Telebe.getTelebeSayi());

// iki dene telebe obyekti yaradiriq
Telebe telebe1 = new Telebe("Obi-Wan Kenobi", 19, "2010001");
Telebe telebe2 = new Telebe("Anakin Skywalker", 16, "2010002");

int tlbSayi = Telebe.get Telebesayi();
System.out.println("Telebe sayi: " + tlbSayi);

}
}
Bu kodun cavabi aşağıdaki kimi olacaq.
Baslangicda telebe sayi: 0
Telebe sayi: 2
cavabini verecekdir.Telebe sinifinin içindeki getTelebeSayi() metodu static olduğu ucun, bu sinifin herhansi bir obyektini yaratmaqdan qabaq bu metodu cagirmagimiz mumkundur. Bu sinifden herhansi bir obyekt yaratdiqsa o obyekt referansi uzerinden de teyin etdiyimiz static metodu cagira bilerik,ancaq bu tovsiye edilmir. Eyni şekilde static deyişenlere catarken de obyekt referanslarını istifade ede bilirik,ancaq bunlara da sinif adi ile catmaq kodun oxuna bilmesini artirir.
Static metodlarla bagli bilinmesi lazim olan en önemli şey budur: static metodlar içinden static olmayan bir sinif elementine cata bilmerik!!! Eger bizim static metodumuzun içerisindeki telebesayi deyişeni static olmasaydı program sehv verecekdi. Static bir metod içerisinde static olmayan deyişenlere cata bilmediyimiz kimi, static olmayan metotları da çağıra bilmerik! Bu veziyyetde bele bir numune gosterek.
package com.javagelistir.meqale;

public class Telebe {
private String ad; // Obyekt deyiseni
private int yas;             // Obyekt deyiseni
private String TelebeNo; // Obyekt deyiseni
public static int TelebeSayi = 0; // Sinif deyiseni

public Telebe(String ad, int yas, String TelebeNo) {

this.ad = ad;
this.yas = yas;
this.TelebeNo =TelebeNo;

// Her obyekt yaradildiginda sinif deyisenini artiririq.
TelebeSayi++;
}
public int telebeSayiniTap() {
return telebeSayi;
}

public static int getTelebeSayi() {
return telebeSayiniTap();
}
}
Telebe sinifimize static olmayan telebeSayiniTap() adli yeni bir metot elave etdim. Bu metod sadece telebeSayi adli sinif deyişenimizi döndürür. Buraya diqqet çünki qaydamiz beledir: static metod içerisinden static olmayan bir elemente cata bilmerik. Burada ise static olmayan bir metoddan static bir elemente catiriq. Bu meqsedeuygun bir catmaqdir. Ancaq static metodumuz olan getTelebeSayi() metodu static olmayan telebeSayiniTap() adli metodu çağırır. Qaydamiza göre getTelebeSayi() static bir metot olduğu ucun static olmayan telebeSayiniTap() metodunu çağıra bilmez. Yuxarıdaki kodu compilyasiya etmeye çalışdığımızda “Cannot make a static reference to the non-static method telebeSayiniTap() from the type Telebe” sehvi alariq ve kodumuz islemez. Eyni şekilde getTelebeSayi() metodu içerisinden static olmayan bir deyişkene catmaga çalışsaydıq yene sehv alacaqdiq.
Bunun sebebini bele acixlaya bilerik. Static deyişkenler ve metodlar obyektlerden musteqildir. Yeni ortada heçbir obyekt olmadigi halda static metodlar çağırıla biler ve ya static deyişenlere (sinif degişkenleri) deyer teyin edile biler. Static olmayan sinif elementleri ise ancaq bir obyekt teyin etdiyinde var ola biler. Bu halda da static bir metod içerisinde static olmayan bir deyişene catilmaga çalışıldığında hansi obyektinin deyişenine catacaqdir? O anda ortada heç obyekt bele olmaya biler. Eyni hal static metod içerisinde static olmayan bir metod çağırılmaga çalışıldığında da keçerlidir. Bu sebeble static metodlar içerisinden ancaq static olan sinif elementlerine cata bilerik. Ancaq yuxarıdaki numunede etdiyimiz kimi static olmayan bir metod içinden static elementlere cata bilerik. Çünki static elementler obyekt yaradılmadan daha evvelonsuzda yaradılmışdı.
Static metod içerisinden static olmayan metodu çağıra bilmeyen kimi gedib diger metodu da static etmek o an ucun işe yaraya biler ancaq bu son derece pis bir cixis yoludur. Bele bir halda metodlarınızın dogrudan static olub olmaması lazim geldiyini arasdirmaq lazimdir.
Static Kod Blokları
Static kod blokları static deyişenlere bagli ilk değer qiymetini vermek ucun istifade olunur. Bunlara edebiyyatda “static initializer” deyirler. Static kod blokları sinif deyişenleri yaddasa yüklendikden sonra isledilirler. JVM, o sinife aid bir obyekt yaratmaqdan evvel static kod bloklarının işledilmesini garantiya eder.
package com.javagelistir.meqale;
import java.util.Random;

public class StaticInitializer {

private static int massiv[];
private static int boy = 10;

static {

massiv = new int[boy];
Random rnd = new Random();

for(int i=0; i < boy; i++)
massiv[i] = rnd.nextInt(100);
}
}
Yuxarıdaki koda baxdığımızda static kod bloku içerisinde 0 ile 99 arasında tesadufu teyin olunmus 10 dene saydan ibaret bir massiv yaratdigini görürük. Bu kod bloku sayesinde, bu sinifin deyişkeni olan massiv deyişeni yaradıldığı anda 10 dene tesadufi say ile doldurulur. Static kod blokları içerisinde de, static metodlarda olduğu kimi static olmayan sinif elementlerine catmaq mümkün deyil. Static kod blokları cox istifade olunmadiginda daha cox derinliklere getmeye ehtiyac yoxdur.
Static Import
Static metodların sinif adı istifade edilerek çağırıldığını bilirik. Numunenin Java'da "java.lang" paketinde olan "Math" sinifindeki butun metodlar static metodlardır ve bunları çağırmaq ucun Math.metodAdi() şeklinde bir kod yazmaq lazimdir. Math sinifindeki static metodları kodumuza import edib sinif adını istifade etmeden sadece metod adı ile static metodları çağırmaq isteyirikse aşağıdaki kimi static import istifade ede bilerik. Buradaki tek ferq normalda istifade etdiyimiz import kelmesinin yanına bir de static vermekdir.
package com.javagelistir.meqale;

import static java.lang.Math.*;

public class Program {

public static void main(String args[]) {

System.out.println("Karekok 25: " + sqrt(25));
System.out.println("Log(100): " + log(100));
System.out.println("Pi Sayisi" + PI);
}
}
Kodda görüldüyü kimi normalda Math.sqrt(), Math.PI yazaraq catmagimiz lazim gelen static metod ve deyişkenlere static import istifade edilerek birbasa catmaq sansına sahib olabilirik.

Hiç yorum yok: