Packages

Java’daki paket mantığını tamamen aynı olmasa da işletim sistemimizde kullandığımız dizin yapısına benzetebiliriz. Arkadaşımızdan aldığımız harici diskten müzik ve fotoğraf kopyalayacağımızı düşünelim. Diskteki dosyalar karışık olsalar bile kendi bilgisayarımıza kopyalarken müzik dosyalarını ayrı bir klasöre, resim dosyalarını ayrı bir klasöre kopyalar, saklarız. Hatta aradığımız dosyalara daha hızlı erişebilmek için türkçe müzikler için ayrı bir klasör, yabancı müzikler için ayrı bir klasör açarız.

Kod yazarken de bütünlüğü korumak adına sınıflarımızı farklı paketlerde saklarız. Mantıksal olarak benzer işler yapan sınıflar aynı pakette bulunurlar.

Bir sınıfın ait olduğu paketi belirtmek için “package” saklı kelimesinden sonra sınıfın içinde bulunduğu paketin ismi yazılır. Paket tanımı mutlaka ilk komut olarak yazılmalıdır.

Aslında bütün sınıflar bir pakete ait olmak zorundadır. Hiç bir isim verilmediğinde o sınıf isimsiz “default package“da kabul edilir. Paketi belirtilmemiş bütün sınıflar aynı paketin sınıfları sayılır. Fakat sadece örnek olsun diye yazılan bu gibi sınıflara başka paketlerden erişilemez. Hatta derlenemez durumda bırakılan test sınıfları bile yine paketsiz olan başka bir sınıfın derlenmesini engelleyebilir.

package spor;

public class Bilardo {

      // sınıf kodları

}

Bir sınıfın kendisiyle aynı pakette olmayan sınıfı kullanabilmesi için, o sınıfı kullandığını derleyiciye söylemesi gerekir. Bunun için paket tanımı ile sınıf tanımı arasına import saklı kelimesini kullanarak o sınıfı ekler. Bu sadece kullanılan sınıfların tam olarak hangi pakette olduğunu söylemek anlamına gelir. Gerekli olan metot ya da değişken kullanıldığında çalışacak olan kodun nerede olduğu bilgisini JVM’e (Java Virtual Machine) söylemiş oluruz.

package bnmPaketim;

import spor.Bilardo;

public class MasaTenisi {

    // sınıf kodları

}

 “bnmPaketim” paketindeki MasaTenisi sınıfının spor paketindeki Bilardo sınıfını kullanacağı anlamına gelir. Aynı paketteki sınıfların birbirlerini ‘import’ etmeleri gerekmez.

İç içe paketler tanımlanabilir. Bu gibi durumlarda alt paketler altındaki sınıflara paketler arasına nokta konularak ulaşılır. Örneğin spor paketi altına bir de bireysel adında bir paket daha tanımlayalım. İçerisinde de Bilardo sınıfımız olsun. Başka bir paketten Bilardo sınıfına erişebilmek için;

import spor.bireysel.Bilardo;

yazılmalıdır.

java.lang‘ paketi özel bir pakettir. Bu paketteki sınıfları kullanmak için import ifadesine gerek yoktur. Bu paket olmadan hiç bir Java programı yazılamayacağı için import edilmiş varsayılır. Örneğin “String” sınıfı “java.lang” paketinde olduğu için her bir String kullandığımızda başına java.lang.String yazmamıza ya da java.lang paketini sınıfa import etmemize gerek kalmaz.

Bir paketteki bütün sınıfları import etmek için ‘*‘ operatörü kullanılabilir.

package bnmPaketim;

import spor.*;

public class Araba {

     // sınıf kodları

}

Örnek kodumuzda Araba sınıfı spor paketindeki tüm sınıfları kullanabilir. Çok dikkat edilmesi gereken bir konu ise Araba sınıfının spor paketindeki ‘bireysel’ paketi altındaki Bilardo sınıfını kullanamayacağıdır. Bir paket import edildiğinde sadece o paket altındaki sınıflara erişilebilir. Aynı paket altında başka paketler varsa, o paketlerdeki sınıflar import edilmiş olmaz. İç içe paketler tanımlamanın amacı bir paket altındaki sınıf sayısını mantıksal bütünlüğü koruyarak azaltmaktır.

* kullanmak alt alta çok sayıda import ifadesi yazmaktan daha kolay gibi gelebilir. Bazı programcılar okunurluğu arttırmak için böyle bir yola gitmektedirler. Ama bence okunurluğu arttırmaktan ziyade paket içerisindeki hangi sınıfın çalıştığını görmek daha işlevsel olacaktır. * kullandığımızda kullanılmayan sınıfların da gereksiz yere kendi sınıfımıza eklendiği gibi bir durum söz konusu değildir. Yani performans kaybına yol açmaz fakat yine de kodumuzu yazarken sadece kullandığımız sınıfları import etmeliyiz.

package bnmPaketim;

import tasit.*;

public class Test {

    // sınıf kodu içerisinde
    // hem Gemi
    // hem Otobus
    // hem Tren
    // hem Ucak sınıfları kullanılacak

}

 yerine

package bnmPaketim;

import tasit.Gemi;
import tasit.Otobus;
import tasit.Tren;
import tasit.Ucak;

public class Test {

    // sınıf kodu içerisinde
    // hem Gemi
    // hem Otobus
    // hem Tren
    // hem Ucak sınıfları kullanılacak

}

Aslında her sınıf paket ismiyle birlikte adlandırılır. Örneğin, ‘tasit’ isimli bir pakette ‘Araba’ isimli bir sınıfın tam nitelendirilmiş ismi ‘tasit.Araba’ dır. import ifadesi, sadece yazılımcıyı her sınıf ismini böyle uzun yazmaktan kurtarmaktadır. Söylemek istediğim şey hiçbir import ifadesi kullanmadan da gerekli sınıfları tam ismiyle çağırabiliriz.

package bnmPaketim;

public class Test {

    public static void main(String[] args) {

        tasit.Gemi gemi = new tasit.Gemi();

        // diğer kodlar

    }

}

Yukarıdaki gibi “tasit” paketinde olan Gemi sınıfının instance’ını “import tasit.Gemi;” ya da “import tasit.*;” diyerek kullanmak istersek;

Gemi gemi = new Gemi();

şeklinde yaratabiliriz. Hiç import kullanmazsak instance yaratmak için ;

tasit.Gemi gemi = new tasit.Gemi();

yazabiliriz.

Java’nın kendi uygulama programlama arayüzü bir çok sınıftan oluştuğu için bir çok paket altında gruplandırılmıştır. Bunların çoğu ‘java.’ ve ‘javax.’ la başlar. ‘javax’ ile başlayanlar sonradan ekleme paketler için kullanılır. Önceden eklenti olan paketler daha sonra standart API’ye dahil edilmişlerdir.

           İsimlendirme Geleneği :

Paket isimlerinin rastgele verilmesi bazı sorunlara yol açabilir. Örneğin bir sistemde farklı kurumlara ait paketler olsun. Aynı paket ismini başka bir kurum da kullandıysa sunucuya yüklenen kodlardan hangisi önce bulunur ve hafızaya yüklenirse o kod çalışır.

Bu sorunlarla karşılaşmamak için paket isimlerinde standart bir yöntem uygulanır. Bu isimlendirme standartı SUN şirketinin belirlediği bir standarttır. Uygulama içerisindeki paketler isimlendirilirken kurumun sahip olduğu internet domain ismi tersten yazılır.

Örneğin ‘www.infopark.com’a sahip olan kurum veya kişiler, mesajlasma ile ilgili sınıflarını ‘com.infopark.mesajlasma’ diye bir pakete koyabilirler. SUN firması da kendi paketlerini ‘com.sun’ şeklinde başlatmaktadır. Genelde özel kuruluşlar com, ticari olmayan kurumlar da org ile başlarlar.

Java’da İsimlendirme Standartları

Proje İsimleri  :

–          Küçük ya da büyük harfle başlayabilir.

–          Genellikle büyük harfle başlatılır.

–          Eğer birden fazla kelimeden oluşuyorsa sonraki kelimelerin baş harfleri büyültülür.

–          Geri kalan kısmı küçük yazılır.

Paket İsimleri :

–          Küçük harfle başlar.

–          Birden fazla kelimeden oluşuyorsa diğer kelimelerin sadece baş harfleri büyültülür.

–          Paket isimlendirmeleri yapılırken domain ismi tersten yazılır.

Örnek :

tr.com.infopark.business.*         gibi

Sınıf isimleri :

–          Büyük harfle başlar küçük harfle devam eder.

–          Eğer birden fazla kelimeden oluşuyorsa diğer kelimelerin baş harfleri büyültülür.

–          Sınıf isminin dosya ismi ile aynı olması gerekir.

Metot isimleri :

–          Küçük harfle başlar.

–          Birden fazla kelimeden oluşuyorsa diğer kelimelerin sadece baş harfleri büyültülür.

Değişken isimleri :

–          Küçük harfle başlar.

–          Birden fazla kelimeden oluşuyorsa diğer kelimelerin sadece baş harfleri büyültülür.

–          $ ve _ dışında değişken ismi başında, başka herhangi bir karakter kullanılamaz.

–          Değişken ismi içinde sayısal bir ifade kullanılacaksa değişken isminin başında kullanılamaz. Ortasında ya da sonunda sayısal ifade geçebilir.

Örnek :

int sayi1;         gibi kullanılabilir.

int 1sayi;         şeklinde kullanılamaz !

 

Gördüğünüz gibi sadece sınıf isimleri büyük harfle başlıyor. Bunun dışındaki tüm kavramlar küçük harfle başlıyor.

İSTİSNA : static ve final tanımlanan değişken isimlerinin tamamı büyük harfle yazılır. Eğer birden fazla kelimeden oluşuyorsa kelimeler arasında _ kullanılır.

Örnek :

static final int SABIT_SAYI = 3.14;


Primitive Types – Wrapper Classes

İlkel tipler uygulama yazarken çok fazla kullanılır. Bu sebeple ilkel tipleri heap alanında new anahtar kelimesi ile oluşturmak pek de avantajlı değildir.

Bunun yerine bu ilkel tiplerin stack alanında saklanması çok daha iyi performans verir.İlkel tiplerdeğerlerini kendi üzerlerinde taşırlar. Java’da 8 adet ilkel tip vardır. Bunlar 3 ana başlık altında incelenebilir.

Değişkenler tanımlanırken önce tip adı sonra boşluk bırakılarak değişkenin ismi yazılır. Sınıf değişkeni olarak tanımlanan değişkenlere ilk değer vermek mecburi değildir. Eğer verilmezse varsayılan değerlerini alırlar. İlkel tipler için varsayılan değerler aşağıdaki tabloda verilmiştir.

Eskiden bellek ihtiyacı çok daha fazlaydı. Programcılar uygulama geliştirirken ihtiyaçları kadar RAM tüketmeye özen gösterirlerdi. Bu yüzden tam sayı için bile 4 farklı tip geliştirilmiştir. Hepsinin hafızada kapladıkları yer farklıdır. 32 bitlik işletim sistemleri için :

byte : 8 bitlik yer kaplar. (-128’den 127’ye kadar değer alabilir. “0” da negatif kabul edilmiştir)

short : 16 bitlik yer kaplar.

int : Tamsayı tipleri için varsayılan tiptir ve hafızada 32 bitlik yer kaplar.

long : 64 bitlik yer kaplar.

public class Test {
      int deger = 20000000000;
}

Yukarıdaki kod sağ taraftaki değer int tipinin alabileceği değerden büyük olduğu için hata verecektir. Fakat bunun yerine “deger” ismindeki değişkenin tipini long yapmak da yetmeyecektir.

public class Test {
      long deger = 20000000000;
}

20000000000 long tipinin alabileceği bir değer olmasına rağmen varsayılan tip int olduğu için eşitliğin sağ tarafındaki değeri long değişkene atamaya çalışıyoruz. Sağ taraftaki değişkenin tipinin int değil, long olduğunu bir şekilde derleyiciye söylememiz gerekir. Bunun için sayısal değerin yanına küçük veya büyük harfle “L” yazmamız gerekir. Küçük “L” harfi, “bir” sayısına benzediği için büyük kullanmak tercih edilir. Doğru atama şu şekilde olacaktır.

public class Test {
      long deger = 20000000000L;
}

float : 32 bitlik yer kaplar.

double : 64 bitlik yer kaplar.

Ondalıklı sayılarda da varsayılan tip double olduğu için float değişkenlerini de tanımlarken sonlarına küçük ya da büyük harfle “F” yazarız.

char : 16 bitlik yer kaplar. ‘u’ unicode anlamına gelir. İlk sekiz bitte karakterin hangi ASCII tablosuna karşılık geldiği, ikinci sekiz bitte de ASCII tablosundaki kaçıncı karakter olduğu bilgisi saklanır. Bu sayede klavyeden giremeyeceğimiz karakterleri kullanmak da mümkün olur.

Bütün ilkel tiplerin birer adet sarmalıyıcı (wrapper) sınıfı bulunur. Sarmalayıcı sınıflar obje tipinde oldukları için eskiden mutlaka new saklı kelimesi ile yaratılmaları gerekiyordu. Fakat JDK 5.0 ile autoboxing özelliği dile eklendi. Bu sayede ilkel tiplerden sarmalayıcı sınıflara dönüşüm otomatik olarak gerçekleştirilebiliyor. Sarmalayıcı sınıflar içerisinde değişken ve metotlar bulunur.

Örneğin MIN_VALUE, MAX_VALUE gibi sabitler çağrılarak direk Integer nesnesinin alabileceği en büyük ve en küçük değerlere erişebilir.

Ayrıca tipler arası dönüşümler yapılacaksa yine sarmalayıcı sınıflar kullanılır.

public class Test {
      public static void main(String[] args) {
            Integer deger = 12;
            float f = deger.floatValue();
      }
}

Yukarıdaki gibi Integer bir tipi float’a dönüştürebiliyoruz. Bunun gibi diğer tüm sınıflarda bulunan hazır metotlar sayesinde tipler birbirlerine dönüştürülebilir.

Ayrıca nesneler null olabileceği için ilkel tiplere veremediğimiz null değerini sarmalayıcı sınıflarında kullanabiliriz.