Java da Erişim

Erişim

Erişim konusu kütüphaneler için çok büyük bir önem taşımaktadır.Erişim konusunda iki taraf vardır , bir tanesi kütüphaneyi kullanan kişiler (client) , diğeri ise bu kütüphaneyi yazan kişilerdir. Olaylara kütüphaneleri kullanan kişilerin bakış açısından bakarsak , istenen durum , bir kütüphanenin ilk versiyonunu kullanan bir uygulamanın , bu kütüphanenin ikinci , üçüncü ,dördüncü.... n. inci versiyonlarında bile uygulamada herhangi bir uyumsuzluk sorununun yaşanmamasıdır. Kütüphanenin her yeni versiyonununu , -ki yeni versiyon demek daha az hatalı , daha gelişmiş bir kütüphane anlamına gelir , sistemimize entegre ettiğimizde , bu kütüphaneyi kullanan her uygulamayı değiştirmeye kalkışsak hayat çekilmez olurdu herhalde .
Olaylara birde kütüphaneleri yazan kişilerin bakış açısı ile bakalım . Bir kütüphane yazdınız , ve bunu kullanılması için internete koydunuz , bu kütüphane çok tutuldu , herkes tarafından tebrik mesajları geliyor herşey çok güzel .Fakat daha sonradan bu kütüphane içersinde bir hata olduğunu fark ettiniz veya bu kütüphane içersindeki bazı kısımları , daha hızlı çalışması için optimize etmek istiyorsunuz . Kütüphaneye yazan kişinin bu arzuları , bu kütüphane üzerinde nasıl bir etki oluşturur . Kütüphaneyi kullanan kişiler bundan zarar görebilir mi ? veya zarar görmemesi için ne yapılması gerekir.
Bu tür problemlerin çözümü için devreye erişim kavramı girir , Java toplam dört adet erişim belirliyicisi sunar . En erişilebilirden en erişilmeze doğru sıralarsak , public , protected , friendly , private dır. Bu erişim belirliyicileri sayesinde hem kütüphanleri yazan kişiler özgürlüklerini kavuşur , hemde kütüphaneyi kullanan kişiler kullandıkları kütüphanenin yeni bir versiyonunu rahatlıkla sistemlerini entegre edebilirler.
Kütüphaneleri tasarlayan kişiler , ileride değişebilecek olan sınıfları , veya sınıflara ait metodları , kullanıcı tarafından erişilmez yaparak , hem kütüphanenin rahatça gelişmesini sağlamış olurlar hemde kütüphaneyi kullanan kişiler endişelerini gidermiş olurlar."Herşey tamam ama paket ne anlama gelmektedir" , diyenler için gerekli açıklamaları yapalım.

Paket (package)

Paketler kütüphaneyi oluşturan elemanlardır . Paket mantığının var olmasında ana sebeblerden biri , isim karmaşasını çözmektir. Örneğin elimizde iki sınıf bulunsun X sınıfı ve Y sınıfı. Bu sınıflar içersinde aynı isimde iki metod olması , örneğin f() metodu , herhangi bir karmaşıklığa sebebiyet vermiyecektir.Sebebi ise bu aynı isimdeki metodların ayrı sınıflarda bulunmasıdır.Peki ya sınıf isimleri ? Sistemimizde bulunan aynı isimdeki sınıflar karmaşıklığa sebeb vermez eğer ki bu aynı isimdeki sınıflar değişik paketlerin içersinde bulunursa .
gösterim-1
import java.io.BufferedReader;
Yukarıdaki gösterimimizde BufferedReader sınıf isminin java.io paketinde tek olduğunu anlıyoruz (java.io paketi Java ile gelen standart bir pakettir.).Fakat başka paketlerin içersinde BufferedReader sınıf ismi rahatlıkla kullanılabilir. Paketin içersindeki tek bir sınıfı kullanmak yerine , paketin içersindeki tüm sınıfları tek seferde kullanmak için :
gösterim-2
import java.io.* ;
java.io paketinin içersinde sınıfları kendi uygulamalarımızda kullanmak için, sadece import java.io.* dememiz yeterli olacaktır.
ör-paket-kullanim
import java.io.*;
 
public class PaketKullanim {
 
    public static void main(String args[]) throws IOException{
               BufferedReader  sf = new BufferedReader(new InputStreamReader(System.in));
               System.out.print("Bilgi Giriniz : ");
               String bilgi = sf.readLine();
               System.out.println("bilgi --> " + bilgi);
    }
}
Yukarıda örneğimizde görmediğimiz yeni kavram mevcuttur , "throws Exception" . İstisnalar(Exception) konusunu ilerleyen bölümlerde detaylı bir şekilde inceliyecegiz.

Varsayılan Paket (Default Package)

Öncelikle şunu tekrardan belirtelim , .java uzantılı fiziksel dosyayı derlediğimiz zaman , .java uzantılı fiziksel dosyanın tam ismine karşılık gelen .class fiziksel dosyası elde ederiz (tabii *.java dosyasında hata olmadığını farzederek) .Eğer .java fiziksel dosyasında birden fazla sınıf tanımlanmış ise , tanımlanan bu her sınıf için ayrı ayrı .class fiziksel dosyaları Java tarafından üretilir.
ör-varsayılan-paket-1 - Test1.java
public class Test1 {
    
    public void kos() {
    }
}
 
class Test2 {
    
    public void kos() {
    }
}

Yukardaki örneğimizi , Test1.java adıyla herhangi dizine kaydettim (fiziksel java uzantılı dosya ile public sınıfın ismi birebir aynı olmalıdır) , bu dosyayı javac komutu ile derlediğimde iki adet fiziksel .class dosyası elde ederim ; Test1.class ve Test2.class . Test1.java dosyanın en başına herhangi bir paket ibaresi yerleştirmediğimden dolayı , Java bu sınıfları varsayılan paket (default package) olarak algılıcaktır.
ör-varsayılan-paket-2 - Test3.java
public class Test3 {
    
    public void kos() {
    }
}
Aynı şekilde bu örneğimizide aynı dizine Test3.java adıyla kaydettip derlenikten sonra genel bakış aşağıdaki gibidir.
 
Şekil-1

Paket Oluşturma

Kendi paketlerimizi oluşturmanın temel amaçlarında biri , aynı amaca yönelik işleri yapan sınıfları bir çatı altında toplamaktadır.Bu sayede yazılan sınıflar daha derli toplu olur , artı aranılan sınıflar daha kolay bulunabilir. Peki eğer kendimiz paket oluşturmak istersek bunu nasıl başaracağız ?
ör-paket-2
package tr.edu.kou.util ;
 
public class Test1 {
 
    public Test1() {
               System.out.println("tr.edu.kou.util.Test1 objesi olusturuluyor");
    }
 
    public static void main(String args[]) {
                 Test1 pb = new Test1();
    }
}
ör-paket-2 örneğimizde , Test1.java fiziksel dosyasını işletim sistemimizin herhangi bir dizine yerleştiremeyiz çünkü o artık tr.edu.kou.util paketine ait bir sınıfdır , bu sebepten dolayı içinde bulunması gereken dizinde bu paket ismiyle pararlel olmalıdır.





















Şekil-2
Paket isimlerine bulunan çözüm , şu andaki internet alan isim sistemiyle(Internet Domain Name System) aynıdır.Örneğin Kocaeli Üniversitesinde matematik paketi yazan bir kişi , bu paketin içersindeki sınıfların,dünyanın herhangi bir yerindeki başka kütüphanenin paketleri içersindeki sınıfların ismiyle çakışmaması için internet alan isim sistemini kullanmalıdır. Internet alan isim sistemi , www.kou.edu.tr adresinin dünya üzerinde tek olduğunu garantiler. Aynı mantığı paket isimlerine uygulayarak , paketlerin içersindeki sınıf ismi problemine çözüm bulmuş oluruz . Dikkat edilecek olursa , paket isimleri , Internet alan isimlerinin tersden yazılmış halleridir , işletim sistemlerinin farkı göz önüne alınarak , math paketine ait sınıfların içinde bulunması gereken dizin , Unix veya Linux için tr/edu/kou/math , Window için tr\edu\kou\math şekilde olmalıdır.



Şekil-3

CLASSPATH ayarları

Java yorumlayıcısı (interpreter) ; işletim sisteminin çevre değişkenlerinden CLASSPATH değişkenini bakarak import ifadesindeki paket'i bulmaya calisir.
gösterim-3
import  tr.edu.kou.math.*;
Diyelim ki math paketi aşağıdaki dizinde bulunsun :
gösterim-4
C:\kodlar\bolum4\tr\edu\kou\math\
Java yorumlayıcısının , import ifadesindeki paket'i bulması için aşağıdaki tanımı CLASSATH'e eklememiz gerekmektedir.
gösterim-5
CLASSPATH="C:\kodlar\bolum4\;."
CLASSPATH'e eklenen bu tanım sayesinde , Java yorumlayıcısı , C:\kodlar\bolum4\ dizinine kadar gidip , tr\edu\kou\math dizinini arıyacaktır , eğer -ki böyle bir dizin bulunursa , bu dizinin altındaki tüm sınıflar uygulama tarafından kullanılabilecek hale gelecektir.

Şekil-4

DortIslem.java , dosyasını C:\kodlar\bolum4\tr\edu\kou\math dizinine yerleştirelim :
ör-dört-işlem
package tr.edu.kou.math ;
 
public class DortIslem {
 
    public DortIslem() {
        System.out.println("tr.edu.kou.util.DortIslem objesi olusturuluyor");
    }
 
    public double topla(double a , double b) {
        return (a + b) ;
    }
 
    public double cikart(double a , double b) {
        return (a - b) ;
    }
 
    public double carp(double a , double b) {
        return (a * b) ; 
    }
 
    public double bol(double a , double b) {
        if  ( (a != 0) && (b != 0) )  {
            return (a / b) ;
        } else {
            return 0 ;
        }
    }  
}

Gerekli CLASSPATH , tanımlarını yaptıktan sonra , bu paketi kullanacak olan uygulamamızı , işletim sistemimizin herhangi bir dizinine yerleştirebiliriz.
ör-dört-işlem-kullanım
import tr.edu.kou.math.*;
 
public class Hesaplama {
 
    public static void main(String args[]) {
        DortIslem di = new DortIslem();
        double sonuc = di.topla(9.6 , 8.7);
        System.out.println("9.6 + 8.7 = " + sonuc   );
        sonuc = di.cikart(9.6 , 8.7);
        System.out.println("9.6 - 8.7 = " + sonuc   );
        sonuc = di.carp(5.6 , 8.7);
        System.out.println("9.6 * 8.7 = " + sonuc   );
        sonuc = di.bol(5.6 , 8.7);
        System.out.println("9.6 / 8.7 = " + sonuc   );
    }
}
Uygulamanın çıktısı aşağıdaki gibidir:
tr.edu.kou.util.DortIslem objesi olusturuluyor
9.6 + 8.7 = 18.299999999999997
9.6 - 8.7 = 0.9000000000000004
9.6 * 8.7 = 48.71999999999999
9.6 / 8.7 = 0.6436781609195402
Önemli nokta
Dikkat ettiyseniz , CLASSPATH değişkenini tanımlarken , tanımın en sonuna "." nokta koyduk.

Şekil-5
Bu önemli bir ayrıntıdır. Bu noktanın konmasındaki neden , varsayalın paketlerin(default package) içindeki sınıfların birbirlerini görebilmesini sağlamaktır.Bu nokta unutulursa , anlamsız hata mesajları ile karşılaşılabilir.
Java 2 'yi sisteminize ilk kurduğunuz zaman basit örnekleri CLASSPATH değişkenine herhangi bir tanım eklemeden bile çalıştırabildiğinizi görürsünüz. Bunun sebebi Java 2 'nin temel kütüphanleri , kendi kurulum dizinine göre tahmin edebilmesinden ileri gelir.

Çakışma

Ayrı paketin içersindeki , aynı isimdeki sınıfları uygulamızda kullanırsak ne olur ? Tahminen , isimleri aynı olsa bile değişik paketlerde bulundukları için bir sorun yaşanmaması gerekir.
Öncelikle tr.edu.kou.util paketinin içersine kendi ArrayList sınıfımızı yazalım .
ör-io-arraylist
package tr.edu.kou.util;
 
public class ArrayList {
 
    public ArrayList() {
        System.out.println("tr.edu.kou.util.ArrayList objesi olusturuluyor");
    }
}
Aşağıdaki örneği işletim sisteminizin herhangi bir dizinine kayıt edebilirsiniz.
ör-çakışma-1
import java.util.*;
import tr.edu.kou.util.*;
 
public class Cakisma  {
 
    public static void main(String args[]) {
        System.out.println("Baslagic..");
        ArrayList al = new ArrayList();
        System.out.println("Bitis..");
    }  
}

Cakisma.java dosyasını javac komutu ile derlediğimiz zaman , aşağıdaki hata mesajı ile karşılaşırız.
Cakisma.java:8: reference to ArrayList is ambiguous, both class tr.edu.kou.util.
ArrayList in tr.edu.kou.util and class java.util.ArrayList in java.util match
ArrayList al = new ArrayList();
^
Cakisma.java:8: reference to ArrayList is ambiguous, both class tr.edu.kou.util.
ArrayList in tr.edu.kou.util and class java.util.ArrayList in java.util match
ArrayList al = new ArrayList();
^
2 errors
Bu hata mesajının anlamı , ArrayList sınıfının hem java.util paketinde hemde tr.edu.kou.util paketinde bulunmasından kaynaklanan bir ikilemi ifade eder. Uygulamda ArrayList sınıfı kullanılmıştır ama hangi paketin içindeki ArrayList sınıfı ?
Bu sorundan kurtulmak için aşağıdaki örneğimizi inceliyelim
ör-çakışma-2
import java.util.*;
import tr.edu.kou.util.*;
 
public class Cakisma2  {
 
    public static void main(String args[]) {
        System.out.println("Baslagic..");
        tr.edu.kou.util.ArrayList al = new tr.edu.kou.util.ArrayList();
        System.out.println("Bitis..");
    }  
}
Eğer ortada bir ikilem varsa , hangi sınıfını kullanmak istiyorsanız ,o sınıfın içinde bulunduğu paket isimini de yazarak , oluşan ikilemi ortadan kaldırabilirsiniz.
Paket içersindeki uygulamaları çalıştırmak
Paketlerin içersindeki tek başına çalışabilen uygulamalarımızı (standalone), herhangi bir yerden önüne sadece paket açıklamasını yazarak çalıştırmamız mümkündür. ör-dört-işlem-kullanım uygulamasının yeni versiyonu C:\kodlar\bolum4\tr\edu\kou\math dizinine kaydedelim.
ör-paket-uygulama
package tr.edu.kou.math        ;
 
public class Hesaplama {
 
    public static void main(String args[]) {
        DortIslem di = new DortIslem();
        double sonuc = di.topla(9.6 , 8.7);
        System.out.println("9.6 + 8.7 = " + sonuc   );
        sonuc = di.cikart(9.6 , 8.7);
        System.out.println("9.6 - 8.7 = " + sonuc   );
        sonuc = di.carp(5.6 , 8.7);
        System.out.println("9.6 * 8.7 = " + sonuc   );
        sonuc = di.bol(5.6 , 8.7);
        System.out.println("9.6 / 8.7 = " + sonuc   );
    }
}
Artık Hesaplama sınıfımız tr.edu.kou.math paketinin yeni üyesidir. Paket içersindeki tüm java uzantılı dosyaları C:\kodlar\bolum4\tr\edu\kou\math javac *.java diyerek derletikten(compile) sonra Hesaplama.class dosyasını java komutu kullanara çalıştırmayı deneyelim .
gösterim-6
java Hesaplama
Bir aksilik var gibi , ekranda beliren hata mesajı aşağıdaki gibidir .
Exception in thread "main" java.lang.NoClassDefFoundError: Hesaplama (wrong name
: tr/edu/kou/math/Hesaplama)
        at java.lang.ClassLoader.defineClass0(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:509)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:12
3)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:246)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:54)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:193)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:186)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:265)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:262)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:322)
Hesaplama sınıfı bulanamıyor diye bir hata mesajı ? nasıl olur ama orda ?? evet orada ama o artık Hesaplama sınıfı değildir , tr.edu.kou.math.Hesaplama sınıfıdır yani artık bir paketin üyesi olmuştur. Aşağıdaki ifade sayesinde işletim sisteminizin herhangi bir dizininden (- tabii CLASSPATH değişkeninin değeri doğru tanımlanmış ise ) tr.edu.kou.math.Hesaplama sınıfına ulaşıp onu java komutu ile çalıştırabiliriz.
gösterim-7
java tr.edu.kou.math.Hesaplama
Uygulamanın çıktısı aşağıdaki gibidir .
9.6 + 8.7 = 18.299999999999997
9.6 - 8.7 = 0.9000000000000004
9.6 * 8.7 = 48.71999999999999
9.6 / 8.7 = 0.6436781609195402

JAR Dosyaları (The JavaTM Archive File)

JAR dosya formatı , birçok dosyayı arşivlememize ve sıkıştırmamıza olanak tanır.Normalde JAR dosylarının içersinde sınıf dosyaları (*.class) bulunur.Bazı durumlarda özellikle appletler de yardımcı dosyalarda(gif , jpeg ...) JAR dosyasının içersinde konulabilir.
JAR dosyasının sağladığı faydalar aşağıdaki gibidir.
  • Güvenlik : Digital olarak JAR dosyasının içeliğini imzalıyabilirsiniz.Böylece sizin imzanızı tanıyan kişiler JAR dosyasının içeliğini rahatlıkla kullanabilirler.
  • Sıkıştırma : Bir çok dosyayı güvenli bir şekilde arşivleyip sıkıştırılabilir.
  • Download zamanını azaltması : Arşivlenmiş ve sıkıştırılmış dosyalar internet üzerinde daha çabuk indirilebilir.
  • Paket mühürleme(versiyon 1.2) : Versiyon uyumluluğunu sağlamak amacı ile JAR dosyasının içersindeki paketler mühürlenebilir. JAR dosyasının içersinde paket mühürlemekten kasıt edilen paket içersinde bulunan sınıfların aynı JAR dsyasında bulunmasıdır.
  • Paket versiyonlama (versiyon1.2) : JAR dosyaları , içindeki dosyalar hakkında bilgiler saklayabililer , örneğin üretici firmaya ait bilgiler ,versiyon bilgileri gibi gibi .
  • Taşınabilirlik : Java Platformunun standart bir üyesi olan JAR dosyaları , kolaylıkla taşınabilir.
Oluşturduğumuz paketlerimizi JAR dosyasının içersine yerleştirerek daha derli toplu bir görüntü elde etmiş oluruz. tr.edu.kou.math ve tr.edu.kou.util paketlerini tek bir JAR dosyasında birleştirmek için aşağıdaki komutu kullanmamız yeterli olur ama JAR dosyasını oluşturmak için yazılan komutun hangi dizinde çağrıldığı önemlidir.
JAR-dosyası işlemleri için gerekli olan bazı komutlar :
Açıklama
Komut
JAR dosyası oluşturmak için
jar -cf  jar-dosya-ismi içeriye-atılacak-dosya(lar)
JAR dosyasının içeliğini bakmak için
jar -tf  jar-dosya-ismi
JAR dosyasının içeliğini toptan dışarı çıkartmak için
jar -xf  jar-dosya-ismi
Belli bir dosyayı JAR dosyasından dışarı çıkartmak için
jar -xf  jar-dosya-ismi arşivlenmiş dosya(lar)
JAR olarak paketlenmiş uygulamayı çalıştırmak için
java -classpath  jar-dosya-ismi MainClass
tablo-1
gösterim-8
jar -cf kou.jar tr/

Gösterim-8'deki ifadeyi C:\kodlar\bolum4 dizinin içersinde iken çalıştırmalıyız ki , JAR dosyasının içersine doğru yapıdaki dizinleri yerleştirelim.

Şekil-6

Oluşmuş olan bu JAR dosyasını CLASSPATH ekleyerek , Javanın bu paketleri bulmasını sağlıyabilirsiniz.Aşağıdaki ifade yerine :
gösterim-9
CLASSPATH="C:\kodlar\bolum4\;."
aşağıdaki ifadeyi kullanabilirsiniz .Tabii ki kou.jar dosyasını C:\muzik dizinine kopyaladıktan sonra...
gösterim-10
CLASSPATH="C:\muzik\kou.jar;."
Java CLASSPATH değerlerinden yola çıkarak JAR dosyasını bulup açar , tr\edu\kou\util ve tr\edu\kou\math dizinlerine erişebileceğinden bir sorun yaşanmıyacaktır.Yani JAR dosyasının hangi dizinde olduğu önemli değildir , önemli olan CLASSPATH'de olmasıdır.Tabii paketlerin içersindeki sınıflar geliştikçe güncelliği korumak adına JAR dosyasını tekrardan üretmek (jar -cvf ..... ) gerekecektir.
JAR dosyası içersindeki bir uygulamayı çalıştırmak
JAR dosyasının içeliğini dışarı çıkartmadan , içersindeki tek başına çalışabilir (standalone) java uygulamalarımızı çalıştırmak mümkündür.Örneğin JAR dosyasının içerisindeki tr.edu.kou.math paketinin altındaki Hesaplama sınıfını çalıştıralım;
gösterim-11
java -classpath C:\calismalar\kod\bolum4\kou.jar     tr.edu.kou.math.Hesaplama
Burada önemli olan hususlar , JAR dosyasının yerine belirtmek ve Hangi paketin altındaki tek başına çalışabilir sınıfın belirtilmesidir.

Yorumlar

Bu blogdaki popüler yayınlar

Soru ve Cevaplarla Kompanzasyon

Aktif Güç Nedir,Reaktif Güç Nedir

Sinusoidal AC dalga şekli, Tepe, ortalama, efektif(rms), değer tanımları...