ıÜüÖnsöz Kitap Hakkında Bu kitap Java`ya yeni başlayanlar veya az

advertisement
Önsöz
Kitap Hakkında
Bu kitap Java'ya yeni başlayanlar veya az bilenler için yazılmıştır. Java'da şu veya bu şekilde kod
yazabilen, fakat dilin temel yapısını henüz tam olarak anlamadığını düşünenler için de faydalı
olabilir. Tek tek class'ları veya kütüphaneleri referans kitabı mantığında anlatmak yerine,
okuyucunun dilin temel esprisini yakalaması sağlanmaya çalışılmıştır. Elbette gerektiğinde
önemli class'lar ve kütüphaneler hakkında da bilgi vermektedir. Zaten bunlar dili tam olarak
kavramak için de bilinmesi gereken asgari düzeydeki konulardır.
Bir bölümde Nesneye Yönelik Programlama (Object-Oriented Programming) anlatılıyor.
Ancak kitabın geneli OOP'u daha iyi anlamanıza katkıda bulunmayı amaçlamaktadır. Nesnelerle
çalışmanın gereğini tam olarak kavramamış bir geliştirici Java'yı diğer bazı dillere bezner
biçimde kullanarak bir çok zenginlikten mahrum kalabilir. Bu kitaptan Inheritance,
Abstraction, Encapsulation, Interface, Polymorphism gibi bir çok kelimenin (daha doğrusu
kavramın) ne anlama geldiğini öğrenebilirsiniz. Bu kavramları tümüyle kavramak elbette
zamanla ve deneyimle olacaktır. Biz burada sadece doğru yönde ilerlemeniz için bir yardımda
bulunmuş oluyoruz. Gerisi okuyucuya kalmıştır. Nesneye Yönelik Programlama bir 'bilgi'
olmaktan çok 'beceri'dir. Ancak 'zamanla' kazanılması mükündür. Vaktinden önce ne kadar iyi
bilirseniz bilin doğru bir biçimde uygulayamazsınız. Hatta bilinçiz nesneye yönelik tasarım,
nesnesiz program yazma tekniğinden daha kötü sonuçlar doğurabilir. Bu kitap bu bakımdan
çeşitli tuzaklara düşememeniz için gerekli uyarıları sırası geldikçe yapmaktadır.
Kitabın ilerleyen bölümlerinde mutlaka öğrenilmesi gereken bazı kütüphaneler
(API'lar)anlatılmaktadır. Bu kütüphaneleredeki bütün class'lar ayrıntılı olarak
incelenmemektedir elbette. Zaten bu konuların her biri ayrı bir kitap konusudur. Bu kitapta belli
kütüphanelerin temel yapısı anlatılmaktadır. Gerisini okuyucu kendisi ilerletebilir. Ezberciliğin
her konuda kötü bir şey olduğunu herkes bilir ya; Java'da ezbercilik imkansızdır. Bu kitabın
yazarı dahil hiç kimse bütün class'ların bütün property ve method'larını ezberleyemez. Java çok
zengin bir kütüphaneye sahiptir. Bu kitabın yazarı en fazla kullandığı nesneler için bile sürekli
documantasyon/referansa (Javadoc'a) bakmaktadır. Bir çok deneyimli programcının da böyle
yaptığı zaten biliniyor. Önemli olan kaybolmadan arama yapabilecek kadar bilgi sahibi olmaktır.
İşte bu kitap da bunu sağlamaya çalışmaktadır.
Java'nın Özellikleri
Java Basittir.
Java, kendisine yakın güçteki dillerin en basitidir. Örneğin, Java model olarak aldığı C++'tan çok
daha kolaydır. C++'ın çok güçlü bir dil olduğu tartışılmaz. Ama C++ ve C# çoğu bir dilde
bulunması çok da şart olmayan karmaşık bir çok özellik içermektededir. Bütün bu özelliklerin
öğrenilmesi çok zaman alır. Oysa Java gereksiz çok fazla özellik içermez. Ve Java'da bir
özelliğin öğrenilmesi ve kullanılması çok kolaydır. Başka dillerde çok zor yazılan işlemler
Java'da çok basit ifadelerle gerçekleştirilebilmektedir.
Java'nin basitliği yanlış anlaşılmamalıdır. VisualBasic/ASP, Delphi/Pascal, Perl, PHP gibi
dillerden ve ortamlardan daha basit değildir. Bu sayılan diller çok kolay öğrenilebilen, kısa
zamanda yeterli düzeye ulaşılabilen dillerdir. Ancak bu dillerde yapılabileceklerin belli bir sınırı
vardır. Bu dillerde büyük çaplı ve karmaşık işler yapamazsınız veya yapmanız durumda çok
zorluk çekersiniz. Oysa Java programlamanın her dalında iddia sahibidir. Her geçen gün Java
yeni bir alanda söz sahibi olmaktadır. Bu bağlamda 'basit' demek, 'çok gelişmiş işlemlerin basit
bir şekilde yapılabilmesini sağlayan' demektir. Yoksa 'programcı bunu anlamaz' diye
düşünülmesinden ötürü hiç bir özellik dışarda bırakılmamıştır.
Java Nesneye Yöneliktir.
Java tamamen (bazı kişilere göre %99) nesneye yönelik'tir. Diğer bazı diller gibi nesneye
yöneliklik sonradan dile eklenmemiştir, başından beri Java'da bulunmaktadır. Bir Java
programında olabilecek her şey ya nesnedir ya da bir nesnenin parçasıdır. Java nesneye yönelik
programlamayı sadece mümkün değil aynı zamanda kolay kılmıştır. Java'da bir nesnenin
yapılması, kullanılması, geliştirilmesi, başka bir yere aktarılaması çok kolaydır.
Java Dağıtıktır.
Java 'dağıtık' bir dildir. 'Dağıtık' birden fazla bilgisayarda çalışan programların bir biriyle
uyumlu çalışabilmesidir. Bir yazılım parçasının bir kısmının bir makinede diğerinin başka
makinede aynı anda çalışması mümkündür. Bu yüzden Internet'in dilinin Java olduğu
söylenmektedir. Günümüzde tek bir makine üzerinde çalışan, başka hiç bir yerle bağlantısı
olmayan uygulama kalmamış gibidir. Bir çok işletme Interenet üzerinden iş yapmaktadır. Bir çok
işletmede birden fazla makine birbirine bağlı olarak çalışmaktadır. Bu yüzden Java dağıtık
programlama için en uygun çözümlerden biridir.
Java Sağlamdır.
Java sağlam bir dildir. Programlamadaki hataların çoğu daha yazılma aşamasında
anlaşılabilmektedir. Yazılma aşamasında anlaşılmayanlar, programın çalışması esnasında
yakalanabilmektedir. Bir 'exception'la, programda hatanın ne olduğu, nerede olduğu ve hangi
işlemi yaparken olduğu bile belirtilebilmektedir. Başka dillerin aksine çalışma esnasında bir Java
programı "Bir hata oldu!" deyip çökmez. Bir çok durumda hataya rağmen program çökmeden
çalışmaya devam eder. Hata olması durumunda da programı çalıştıranlar hatayı ayrıntılarıyla
öğrenme olanağına sahip olur.
Java Güvenlidir.
Java güvenli bir dildir. Java diliyle virüs yapılamaz. Hiç bir virüs bir Java programına
bulaşamaz. Bir Java programının yaptığı her hareket takip edilir. Kötü niyetli bir program, bir
işlemi eğer izin verilmediyse yapamaz. Bu özellik, Internet gibi herkesin başkasının makinesine
erişebildiği bir ortmada çok önemlidir. Java'yı güvenlik gereksinimi yüksek bir çok firma bu
yüzden tercih etmektedir.
Mimarilere Yansızdır.
Sıradan kullanıcıların bildiğinin aksine dünya üzerinde bir çok işletim sistemi vardır. Hatta
kullanıcın çoğunun iyi bildiği Windows işletim sistemi bazı bilgisaya alanlarında hiç
kullanılmaz. UNIX/Linux, Apple Mac, IBM'in çeşitli işletim sitemleri dünya işletim sistemi
pazarında büyük yer tutmaktadır. Bir çok masaüstü kullanıcısının tek bildiği işletim sisteminin,
bazı sektörlerde adı dahi geçmemektedir. Java'da yazılan bir program hemen hemen bütün
işletim sistemlerinde hiç değiştirmeye gerek duymaksızın çalışır. Diğer dillerde bu özellik
yoktur. Hatta Windows'un bir versiyonunda çalışan program diğer bir versiyonda
çalışmayabilmekte, bazen makinenin çökmesi gibi büyük sonuçlar bile doğurabilmektedir.
Windows'u üreten Microsoft firmasının yazdığı programlar bile kendilerinin işletim sistemlerinin
bazılarında çalışmamaktadır. Kendilerinin yazdığı belgelerde hangi işletim sistemlerinin hangi
versiyonlarında hangi programlarının çalışmadığını belirtilmektedir. Bu durum bütün işletim
sistemi ve bütün programlar için geçerlidir. Ürettiği yazılımların her platformda çalışmasını
isteyen firmalar giderek daha çok Java'ya yönelmektedir.
Java Taşınabilirdir.
Java programları her ortamda aynı veya benzer bir şekilde çalışır. Her ortam/makine için ayrı bir
program yazmaya gerek kalmaz. Programcı programın çalışacağı makinenin durumunu göz
önüne almak zorunda kalmaz. Bir programın görüntüsü çalıştığı hey yerde hemen hemen aynıdır.
C programları da hemen hemen her işletim sisteminde yeniden derlenmek suretiyle çalışabilir.
Ama programcı bunun için hazırlık yapmalıdır. Bir işletim siteminde tamsayı -2^15 ile 2^15
arasında değer alırken diğerinde -2^31 ile +2^31 arasında alabilir. Ama Java bu farkları
programcıya şeffaf kılar. Programcı her işletim sistemi ve her sürüm için ayrı bir program
yazmak zorunda kalmaz.
Java Yorumlanır.
Java 'yorumlamalı' bir dildir. Yani bir Java programının komutları, çalışırken makinenin
anlayacağı formata çevrilir. Java'da bu Java Virtual Machine (JVM) tarafından yapılır. Bunun
avantajı bir programın kullanıdığı standart kütüphanelerin programla birlikte taşınması
zorunluluğunu ortadan kaldırmasındır. Bir yorumlayıcı herhangi bir ortamda varsa, bir dildeki
standart her özellik o ortamda var demektir. Programla birlikte bu kütüphanelerin de taşınması
gerekmez. Bu da bir Java programının bir makineden başka makineye indirilmesini çok
hızlandırır. Çünkü sadece programcının yazdığı nesneler yolculuk yapar. Applet'lerin çalışma
prensibi budur. Ana makinede bulunan applet, tarayıcı tarafından kullanıcının makinesine alınır
ve çalıştırılır. Java ortamı, yani JVM tarayıcının içinde mevcutur.
Java Yüksek Başarımlıdır.
Diğer dillerde olmayan bir çok özelliğe sahip olmasına rağmen, Java'da bunun için fazla bir
performans kaybı yoktur. Java'nın ilk versiyonlarında çalışan programlar diğer dillerde yazılan
eşdeğerlerine göre elbette yavaştır. Ancak Java'nın gelişmesiyle birlikte Java bu farkı, üstün
özelliklerinde vazgeçmek zorunda kalmaksızın kapatmaktadır. En son Java sürümüyle birlikte
JIT (Just-In Time-Tam Zamanında Derleme) teknolojisi devreye girmiş bulunlaktadır. Bununla
birlikte Java programları, diğer dillerde en iyi yazılmış programların hızını hemen hemen
yakalayabilmektedir. Java yapılması 'imkansız' gibi görüneni çok da fazla performans kaybına
yol açmadan yapar.
Java'nın yavaşlığı en fazla eleştiri alan özelliklerden biridir. Bir programın hızlı çalışması,
makinelerin hafıza veya işlemcisini terfi ettirerek çözülebilir. İşlemcinin ve hafızanın çok
ucuzladığı günlerde, bu, bir işletme için pek fazla maddi bir yük değildir. Bir programcının
sağlam, güvenli ve Java'nı sahip olduğu üstün özelliklere sahip program üretmesi daha fazla
masraflıdır. Bir işletmenin, durup dururken bir programın makineyi çökertmesinden dolayı
katlanacağı külfet az değildir. Programı yapanların bile hatayı anlamak için saatlerce bazen
günlerce uğraşması işletmeye yine maliyet olarak yansıyacaktır. Bu kadar eleştiri almasına
rağmen Java'nın giderek daha fazla yaygınlaşmasının elbette nedenleri vardır. Java'nın
yavaşlığından sadece Java'yı bilmeyenler ve kullanmayanlar şikayet etmektedir. Ancak Java
'hızla' yayılmaktadır.
Java Çok Kanallıdır.
Java dili başından 'çok kanallıdır' (multi-threaded'dir). Çok kanallılık, bir programın aynı anda
birden fazla işlemi yürütebilmesi demektir. Bir program herhangi bir şeyi beklerken arada başka
bir işlemi gerçekleştirebilir. Beklenen olay gerçekleşince ilk işlem kaldığı yerden aynen devam
ettirilir. Üstelik bunun için programcının fazla bir şey yapması da gerekmemektedir. Çok
kanallılık bir çok dilde hiç yoktur. C++ gibi dillerde de dilin özelliği değil, ona sonradan
eklenmiş kütüphanelerle kullanılabilmektedir. Ama Java'nın kendisi doğuştan çok kanallıdır. Bu
yüzden çok kanallı program yapmak için en kolay dil Java'dır.
Java Dinamiktir.
Java'da bir programla kullandığı birimlerin (kütüphaneler,modüller veya sınıfların) birbirine
bağlanması çalıştırma anında yapılır. Buna 'sonradan bağlama' (late binding) denir. Kullanılan
birimlerin iç yapısı değiştirildiğinde, bu birimleri kullanan programın değişmesi gerekmez. Yeter
ki birimlerin dışarıdan çağırma şekilleri değişmesin. Oysa C++ gibi dillerde herhangi bir
değişiklikte (bu bir modülün iç yapısında çağıranları ilgilendirmeyen çok ufak bir değişiklik bile
olsa) herşeyin yeniden işleme tabi tutulması gerekir. Buna da 'erken bağlama' (early binding)
denir. Java'da late-binding bu özellik olmasaydı, Java kütüphanlerindeki her hata düzeltme ve
değişiklikte dünyadaki bütün programları yeniden işleme tabi tutmamız gerekirdi ki bu mümkün
değildir.
Sonuç
Java iyi bir programlama dilidir. Giderek yaygınlaşması, diğer dillerin giderek Java'ya
benzemeye başlaması ve taklitlerinin çıkması da bunu göstermektedir. Java'yı tercih etmeyenler
elbette olmuştur ve olacaktır. Ama buzdolabının bile Java bildiği bu dönemde bu dili hiç
bilmemek, tümüyle yok saymak bilgisayar alanında var olmak isteyen insanlar için büyük bir
eksiklik olacaktır.
Java Platform'u
Java Platform'u
Java sadece bir programlama dili değildir. Aynı zamanda bir yazılım platformudur. Java
Platform'u işletim sistemi üzerinde çalışan, uygulamalara çok çeşitli servisler veren, bunu her
işletim sistemi için standart bir biçimde başarabilen bir platformdur. Java Programlama Dili ise
bu platform üzerinde yazılım geliştirmek için kullanılan programlama dilidir. O yüzden Java'yı
öğrenmek sadece Java dilini öğrenmek demek değildir. Java platformu üzerinde çalışan farklı bir
dil de üretilebilir. Ancak Java dilinin iyi bir programlama dili olması nedeniyle böyle bir ihtiyaç
doğmamışır.
Java platformunun yapısı, daha önce benzer bir platform olmaması nedeniyle, özellikle başka
dillerle çalışmış insanlara karmaşık gelebilir. Ancak Java, diğer dillerdeki, özellikle de C/C++
dilindeki "çözümsüz" veya "çözümü zor" konulara pratik çözümler üretmiştir. O yüzden başka
dillerle profesyonel programlama yapmış olan insanlar sık karşılaştıkları bir çok sorunun Java'da
çok kolay çözülmüş olduğunu görebilmektedirler. Bu bölümde bir Java programının çalışma
biçimini, öncellikle diğer dillerde yazılmış programların çalışma biçimlerini gözden geçirerek
inceleyeceğiz.
Derleme (Compilation) ve Yorumlama (Interpretation)
Programalama dili, insanla makine (bilgisayar) arasında iletişim kurmak için kullanılan dildir.
Başka bir deyişle programcı bilgisayara, özellikle de işlemciye istediklerini yaptırmak için bir dil
kullanır. Bu dil konuşma diline yakın bir dil olmalıdır ki insanlar rahatça kullanabilsin.
Bilgisayar işlemcisinin dili ise sadece sayılardan oluşur. Bilgisayarlar sayısal (dijital) aygıtlardır.
İşlemciler sadece belli sayılarla ifade edilen makine kodlarından anlar. Bu kodlardan oluşan dile
'makine dili' denir, üretilen koda da 'makine kodu' (machine code) denir. Bilgisayarın ilk
dönemlerinde insanlar programlarını sayı kodları kullanarak yazıyorlardı. Bu kodlar her işlemci
türü için değişik olduğundan, yazılan programlar sadece belli bir işlemci ile çalışabiliyordu.
Hatta bir işlemci sürümü için yazılan kod bir önceki sürümde çalışmayabiliyordu. Bu yüzden
'programlama dili' kavramı ortaya çıkmıştır. Bu yapıda, programcı bilgisayarın yapması
gerekenleri ona, konuşma diline yakın bir dille söyler. Bu dilde yazılanlar makine diline çevrilir.
Böylece programcılar, hem işlemciminin kendine komut kümesini öğrenmek zorunda kalmazlar;
hem de yazdıkları programlar birden fazla işlemciyle çalışabilir.
Programalama diliyle düz metin şekinde olan programa 'kaynak kodu' (source code) denir.
Makine dilinde olan koda da "ikili kod" (binary code) denir. Programlama dilinden makine diline
çevirme işi iki şekilde yapılabilir. Biri 'anında', ikincisi 'önceden'. Anında çevirmek, programa
dilindeki ifadeleri bir yandan okuyup bir yandan makine diline çevirmek demektir. Buna
'yorumlama' (interpretation) denir. Önceden çevirme ise, programlama dilindeki ifadelerin
çalıştırılmadan önce makine diline çevrilmesi, sonra da çalıştırılması anlamına gelir. Buna da
'derleme' (compilation) denir. Derleme'nin faydası daha hızlı olmasıdır. Çünkü makine diline
çevirme sadece ve sadece bir kere yapılmaktadır. Yorumlama da ise her çalıştırmada çevirme
işlemi yapıldığından daha yavaştır. Derlemenin zararı da, programdaki her değişiklikte önce
derlemeyi sonra çalıştırmayı gerekli kılmasıdır. Sık değişiklik yapılan durumlarda bu, programcı
için ciddi bir sorundur. Oysa yorumlama anında olduğu için, değişiklik de anında etkili
olmaktadır. Perl, Basic gibi diller yorumlamalı, C ve Pascal gibi diller de derlemeli dildir.
JVM - Java Virtual Machine (Java Sanal Makinesi)
Java'daki durum biraz daha karışıktır. Java hem 'derlemeli' bir dildir, hem de 'yorumlamalı'. Java
programlama diliyle yazılmış kaynak kodu, sanal bir işlemcinin anlayabileceği makine koduna
çevrilir. Bu kod gerçek bir makine olmadığından ona makine kodu denmez. Ama programala dili
gibi konuşma dilinde de olmadığından kaynak kodu da değildir. Bu ara dille yazılmış koda 'bayt
kod' (bytecode) denir. Çünkü makine kodu gibi baytlardan oluşur. Yani kaynak kodu bayt
koduna 'derlenir'. Sanal işlemci bu bayt kodlarının makine koduna programın çalışması
esnasında çevirir. Her işletim sistemi ve işlemci için ayrı bir sanal makine vardır. Java kaynak
kodları Java derleyicisi tarafından bayt koda çevrilir. Üretilen bu kod bütün işlemciler için
aynıdır. Her işletim sistemi ve işlemciye göre sanal makine, bu bayt kodu ilgili işlemcinin
makine diline anında çevirir yani yorumlar. Bu sanal makineye Java Sanal Makinesi - Java
Virtual Machine (JVM) denir.
Şimdi teorik olarak anlattığımız sürecin, uygulamadaki bileşenlerini inceleyelim. Java
platformunun programlama dili 'Java' dır. Bu dilde yazılmış kaynak kodları '.java' uzantılı
dosyalarda saklanır. "javac" adlı bir derleyici ile ikili koda çevrilir. İkili kod'lar '.class' uzantılı
dosyalarda saklanır. Bu dosyalar 'java.exe' adlı yorumlayıcı tarafından çalıştırılır. Java kaynak
kodu herhangi bir metin düzenleyici ile yazılabilir. Java'nın derleyicisi ücretsiz olarak
dağıtılmaktadır. Java'nın yorumlayıcısı (JVM)'de plug-in olarak yüklenebilmektedir. Bu plug-in
de ücretsizdir. Ayrıca bilinen bütün tarayıcılar'ın bir JVM'i bulunmaktadır.
Bir JVM içerinde çalışan Java application'u C ile yazılmış native kodu çağırabilir. Bu durumda
performans'tan kazanılmakla birlikte platform bağımsızlığı kaybedilmiş olur. O yüzden bu,
sadece çok hız gerektiren az sayıda işlem için kullanılabilir. Java'nın hızı giderek arttığından
buna zamanla daha az ihtiyaç duyulmaktadır. Bir .exe programı da Java programlarının
içerisinden çalıştırılabilir. Ancak bu durumda çalışan proses tamamen JVM'in dışında, aşağıdaki
işletim sisteminin kontrolünde bulunur. Application'la veri alışverişi bulunmayan programları
dışarıdan çağırmak için kullanılabilir.
Java'nın Kullanım Alanları
Applet'ler
Bir web sayfası içerisinde çalışabilen görsel Java bileşenlerine 'applet' denir. Bir web sitesinden
client'a .html veya .gif dosyası gibi indirilir ve browser tarafından çalıştırılır. Client'ta çalışması
nedeniyle kullanıcıyla çabuk etkileşim kurabilmektedir. Server'da çalışan CGI ve benzeri
programlar her işlemde server'a gidilmesini gerekli kılmaktadır. Bu da bandwith'i sınırlı client'lar
için ciddi bir sorun olmaktadır. Özellikle game ve chat gibi uygulamaları da applet hemen hemen
tek mantıklı seçenek olarak durmaktadır.
Servlet'ler
Server makinelerinde bir application server içerisinde çalıştırılabilen program modüllerine
'servlet' denir. Bunlar bağımsız application değildirler ve yüklenmeleri, çalıştırılmaları ve
gerektiğinde devreden çıkartılmaları bir application server tarafından yapılır. Bir URL olarak
çağrıldıklarında, varsa kullanıcıdan gelen parametreleri alıp çalışırlar ve çıktı olarak da HTML
üretirler. Bir dosyada 'statik' olarak bulunan HTML'in client'a aktarılması yerine HTML'in
'dinamik' olarak (real time'da) üretilip output'a basılması söz konusudur.
Application'lar
Java'nın önce Applet'lerle sonra da Servlet'lerle gündeme gelmesi, onun sanki normal bir
programlama dili olarak kullanılamayacağı gibi bir izlenim yaratmamalıdır. Java'nın internet'e en
uygun dil olması, internet dışındaki uygulamalarda kullanılamayacağı anlamına gelmez. Bir
ortamda Java platform'u yüklüyse her tür işlem için Java application'u çalıştırılabilir. Ancak,
herhangi bir makinede bir Java programı çalıştırılabilmesi için JRE (Java Runtime Engine - Java
Çalışma-Zamanı Motoru) bulunmalıdır. Bir çok işletim sistemi Java'yla birlikte gelmekte veya
kurulurken Java'yı tercihe bağlı olarak yüklemektedir. JRE yaklaşık 10 MB yer kapladığından ve
çok çabuk kurulduğundan CD ile dağıtılan programlarla birlikte de verilebilmektedir.
Micro Edition
Java'nın kullanım alanlarında biri de el cihazlar veya çeşitli makinelerdir. Bunlarda Java'nın
micro edition'u çalışır. Standart Java'dan farklı olan bu edition, bazı ek class'lar içerdiği gibi
bazı standart kütüphaneleri de içermez. Dilde de bazı farklar vardır. Örneğin kesirli sayılar micro
edition'da yoktur. Bunların dışında Java'nın temel çalışma biçimi aynıdır. Bir server veya başka
bir kaynaktan aplication yükleyip çalıştırmak applet benzeri olan midlet class'larıyla yapılır.
Java'yı destekleyen cep telefonları, buzdolapları, arabalar bulunmaktadır. Yakın bir gelecekte
Java'nın kullanım alanının daha da yaygınlaşacağını düşünülmektedir.
Enterprise Edition
Server'larda, işletmelerin network'lerinde e-ticaret, mail, kullanıcı sistemi gibi bir çok işlemi
desteklemek üzere çeşitli kütüphanelerle donatılmış bir başka Java versiyonu daha vardır :
Enterprise Edition. Bu edition standart Java artı dağıtık işlemler için bazı kütüphaneler
içermektedir. Değişik veritabanı ve e-ticaret çözümü üreten firmalar için bir standart teşkil
ettiğinden, Java'nın platform bağımsızlığı yanında, yazılım üreticilerinden bağımsız sistem
kurulabilmesini de sağlamaktadır. Firmayı tek bir işletim sistemine veya yazılım üreticisine
bağımlı olmaktan kurtarmaktadır. Sisteme entegre bir ürün başka bir şirketin yaptığı ürünle
rahatlıkla iletişim kurabilmekte, bir sistem yerine diğeri çok kolay yerleştirilebilmektedir. Bir
çok büyük veritabanı ve e-ticaret yazılımı üreticisi Java enterprise edition'u desteklemektedir.
JRE ve SDK
JRE (Java Runtime Engine - Java Çalışma Zamanı Motoru)
Bir makinede Java'yla yapılmış bir programın çalışması için orada mutlaka Java interpreter'ı
olması gereklidir. Applet'ler browser içindeki Java'yla çalışırlar. Java kodlarını çalıştıran sisteme
JRE (Java Runtime Engine- Java Çalışma Zamanı Motoru) denir. Java'da yapılmış bir program
herhangi bir makineye kurulurken (eğer yoksa) öncelikle JRE kurulmalıdır. Ancak bu işlem bir
makine için sadece bir kere yapıldığından, üzerinde JRE kurulmuş bir makineye herhangi bir
program yüklenirken tekrar JRE kurulmasına gerek yoktur. JRE bazı işletim sistemlerinde
kendiliğinden kurulu olup, bazılarında da tercihe bağlı olarak kurulabilmektedir.
Elbette yazılan program, Java'nın o makinede kurulu sürümünden daha ileri bir sürümü gerekli
kılıyorsa JRE'nin upgrade edilmesi gerekir. Java'da yeni bir sürüm yüklenince eski sürümle
çalışan programlar çalışmaya devam eder. Bütün Java sürümleri 'geriyle uyumlu' (backward
compatible)'dırlar. Yıllar önce yapılmış Java'nın ilk sürümüne göre çalışan uygulamalar, son
sürümle de çalışmaktadır.
Java Plug-in
JRE kurulduğu zaman aynı zamanda browser'lar için bir plug-in olarak çalışır. Herhangi bir
HTML sayfasında applet'le karşılaşıldığında artık browser'ın kendi Java'sı değil bu plug-in
devreye girer. Bu applet'in Java'nın son sürümlerindeki özellikler içermesi durumunda zaten
zorunludur. Internet Explorer'ın en son sürümü bile örneğin Java'nın 1.1 versiyonunu
içermektedir. Oysa şu anda Java'nın son sürümü 1.4'dür. Netscape Navigator ve Opera gibi
browser'lar da kurulurken Java plug-in'ini tercihe bağlı olarak yüklemektedirler. JRE 10 MB'a
yakın olduğu için bir kullanıcının Java plugin'ini (JRE'yi) indirmesi bağlantı hızına göre
değişmekle birlikte dakikalar mertebesinde süren bir işlem olabilmektedir. Ancak kurulumu 1
dakikadan daha az sürmektedir. Intranet gibi şirket için network ortamlarında her hangi bir
makineye konan JRE, saniyeler mertebesinde çok kısa sürede client makineye kurulabilmektedir.
SDK (Software Development Kit - Yazılım Geliştirme Kiti)
Java'da yazılmış programların çalışması için JRE gerekmektedir. Ancak JRE program
geliştirmek için kullanılamaz. JRE sadece Java programlarını çalıştırmak için gerekli araçları
içerdiğinden derleyici içermez. Bir programı çalıştırmak isteyen bir kulanıcının zaten bir
program yapıp derlemesi gibi bir gereksinmesi yoktur. O yüzden program yapmak isteyenlerin
Java SDK (Software Development Kit - Yazılım Geliştirme Kiti)'ni kurmaları gerekmektedir.
SDK JRE'yi de içermektedir. Programcının derlediği programı elbette çalıştırması da gerekir.
SDK belli bir klasöre kurulur ve hemen hemen bütün araçlar bu klasörün altındadır. Bu yüzden
bir makineden diğerine kopyalandığında bile çalışabilir. Sistemde çok fazla değişiklik
yapmadığından sistemin bütününü veya başka programları olumsuz yönde etkileyecek hiç bir
işlem yapmaz. O yüzden de kurulumu riskli değildir. Ayrıca sisteme çok fazla bağlı
olmadığından, sistemdeki değişikliklerden etkilenmez.
Java'yı derlemek ve çalışırmak için standart tek bir editör (IDE, RAD) yoktur. SDK sadece
derleme ve çalıştırmak için kullanılır. Java kodu yazmak için sadece bir metin düzenleyici
yeterlidir. Ancak daha hızlı kod yazabilmek için çeşitli şirketlerin Java geliştirme ortamları
vardır. Bunlarla çalışmak daha kolay olmasına karşın burada herbirinin ayrı ayrı incelenmesi
mümkün değildir. SDK'yla çalışmak zor olsa da diğer bütün editörle yapılabilen her tür işlem
SDK'yla da yapılabilir. Yani SDK 'eksik' değildir. Sadece kullanım kolaylığı sağlayan araçlar
içermez. Buna karşın bedavadır ve diskte çok az yer kaplar. Ayrıca editörler her zaman en yeni
Java versiyonunu içermezler. SDK'ile çalışmaya alışanlar Java'nın son versiyou çıktığı anda hatta
daha test aşamasındayken bile onunla çalışmaya başlayabilirler. Belli şirketlerin çıkardığı
editörlerin en son sürümü yakalamaları bir süre sonra olabilmektedir.
Derleme ve Çalıştırma (Windows İçin)
Çalışma Ortamının Kurulması
Burada JDK kurmak için standart bir yöntem anlatılacaktır. Bu şekilde çalışmanın bir çok yararı
bulunmaktadır. Özellikle laboratuar ve ağ yöneticilerinin bu sisteme uymaları kendilerine bir çok
fayda sağlayacaktır.
Adım 1 : SDK Kurucu'yu İndirin
SDK'yı download etmek için
http://java.sun.com/j2se/1.4/download.html
adresine gidin. 'Windows (all languages)' ve 'SDK' bölgesinde download seçeneğini tıklayın.
Çıkan anlaşmaya 'Accept' deyin. Daha sonraki sayfada çıkan asıl download linkini tıklayın ve
dosyayı
c:\jdownload
klasörüne (yoksa yaratıp) kaydedin.
Adım 2 : SDK'yı Kurun
Kurucu programı ('c:\jdownload\j2sdk-1_4_0-win.exe') çalıştırın ve klasör olarak
c:\jsdk
(yoksa yaratıp) verin.
Adım 3 : Bir Çalışma Dizini Yaratın
Diskte
c:\jwork
adıyla bir dizin yaratın.
Adım 4 : Basit Bir Uygulama Yazın
Çalışma dizinine 'c:\jwork\MyClass.java' şeklinde bir dosya yaratın ve içine şunları aynen yazın
public class MyClass{
public static void main(String[] args){
System.out.println("OK!");
}
}
Adım 5 : Source Kodu Derleyin
c:\jsdk\bin\javac MyClass.java
Adım 6 : Programı Çalıştırın
c:\jsdk\java -cp c:\jwork MyClass
Eğer ekranın son satırında "OK!" görüyorsanız sistemize Java başarıyla kurulmuş demektir.
Yazdığınız class'ları aynı şekilde derleyebilirsiniz.
Basit Applicationlar
Main Method'u
Java'da yapılabilecek en basit program ekrana yazı yazan bir application'dur.
Greeter.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class Greeter{
2
public static void main(String[] args){
3
System.out.println("Merhaba Dunya!");
4
}
5 }
Basit bir işlem gerçekleştirmesine rağmen bu class, bir Java class'ı ve application'u hakkında bir
çok bilgi içermektedir. Java'da her birim bir class olmak zorundadır. Bağımsız variable veya
function yoktur. Her variable veya function mutlaka bir class'ın içinde yer alır. Her application
aslında özel bazı koşullara sahip bir class'dır. Bir class'ın application olabilmesi için gerekli
koşul
public static void main(String[] args){
}
diye bir method'unun olmasıdır. Java bir class'ı uygulama olarak çalıştıracağı zaman, o class'ın
main() method'unu bulur ve oradan itibaren çalıştırır. Bu method yukarıdaki şekliyle aynen
bulunmalıdır yoksa Java bu class'ın bir program olduğunu anlayamaz.
Ekrana yazı yazmak için System.out.println() şeklinde bir ifade kullanılır. Bu, System adlı
class'ın out adlı property'sinin println() adlı methodunu çağırmak demektir. System class'ı
uygulamanın çalıştığı ortamla ilişkili bazı property'ler ve method'lar barındırır. Ekrana yazmak
için out adlı bir property'si bulunmaktadır. println() method'u da ekrana bir yazı yazıp yeni bire
satıra geçer, yani bir satırlık yazı yazar.
Görüldüğü gibi Java'da basit bir application yazmak için bile (Greeter örneğinde olduğu gibi) bir
class yapmak gerekir. Ekrana yazı yazmak için bile bir classın (System'in ) bir property'sinin
(out'un) bir method'unun (println()'in) çağırılması gerekmektedir. En basit application için
bunları yapmak gerekiyorsa Java'nın çok zor ve öğrenilemez olduğu düşünülebilir. Ancak en
karmaşık application'larda da sadece bu ve benzer işlemler yapılır. Sadece class, property ve
method isimleri ve işlevleri değişir.
Variable Kullanımı
Greeter class'ıyla aynı işlevi yapan bir başka class yazalım.
GreeterWithVariable.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterWithVariable{
2
public static void main(String[] args){
3
String message="Merhaba Dunya!";
4
System.out.println(message);
5
}
6 }
Bu class ekrana yine aynı mesajı yazacaktır. Ancak bu kez ekrana yazılacak yazı önce bir
variable'da saklanıyor, sonra ekrana basılmak üzere println()'e veriliyor.
Java'da değişken bu şekilde yapılır :
Type name=value;
Type, bir değişkenin nasıl bir veri sakladığını gösterir. Java'da bir variable'ın mutlaka type'ının
belli olması gerekir.
String message="Merhaba Dünya";
Şeklinde bir ifade de "message diye bir variable var, bunun type'ı String'dir ve ilk değeri
'Merhaba Dünya!'dır" demektir. String bir class'dır ve içerisinde karakter barındırır.
Method Kullanımı
Yine aynı şeyi yapan bir class yapalım. Ancak ekrana bir satır basan bir method kullanarak
yapalım.
GreeterWithMethod.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterWithMethod{
2
public static void printLine(String line){
3
System.out.println(line);
4
}
5
public static void main(String[] args){
6
printLine("Merhaba Dunya!");
7
}
8 }
printLine() methodunun işlevi kendisine verilen String'i ekrana basmaktır. main() methodunda da
printLine() methodu çağırılmaktadır. Bir method bir kez yazılıldıktan sonra defalarca
kullanılabilir.
public static void main(String[] args){
printLine("Merhaba Dünya!");
printLine("Merhaba Güneş!");
printLine("Merhaba Ay!");
}
Method tanımlamak şu şekilde olur :
ReturnType name(ParameterType1 parameter1,ParameterType2 parameter2)
Burada her methodun alacağı parameter'lar ve return edilecek değerin type'ı belirtilir. Eğer
dönülecek hiç bir değer yoksa return type olarak void yazılır.
Birden Fazla Method Kullanımı
Aynı class içince birden fazla method yazılabilir. Bunlar gerektiğinde birbirlerini çağırabilir.
GreeterWithDoubleMethod.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterWithDoubleMethod{
2
public static void printLine(String line){
3
System.out.println(line);
4
}
5
public static void printGreeting(String greeted){
6
printLine("Merhaba "+ greeted);
7
}
8
public static void main(String[] args){
9
printGreeting("Dunya!");
10
}
11 }
Bu application çalıştırıldığında ekranda "Merhaba Dünya" yazar.
İki string tipini birleştirmek için '+' operatorü kullanılır. Tamsayılar için toplama anlamına gelen
'+', Stringler için birleştirme anlamına gelir. 1+2 işleminin sonucu 3 ederken "1"+"2" işleminin
sonucu "12" eder.
Dosya Listesi

Greeter.java

GreeterWithVariable.java

GreeterWithMethod.java

GreeterWithDoubleMethod.java
Basit Class'lar
Class Kullanımı
Bir class yapalım ama bu class bir application olmasın. Bu sadece başka bir uygulamaya hizmet
verecek bir class olsun.
GreetingPrinter.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreetingPrinter{
2
public static void printLine(String line){
3
System.out.println(line);
4
}
5
public static void printGreeting(String greeted){
6
printLine("Merhaba "+ greeted);
7
}
8 }
Şimdi de GreetingPrinter adlı class'ı kullanan bir application yapalım.
GreeterWithClassUse.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterWithClassUse{
2
public static void main(String[] args){
3
GreetingPrinter.printLine("Dunya");
4
}
5 }
Burada iki class'ın işbirliği sözkonusu. GreetingPrinter ekrana bir selamlama basabiliyor.
GreeterWithClassUse ise bu class'ı kullanarak "Merhaba Dünya" diyebiliyor. Aynı şekilde bir
başka application da bu class'ı kullanabilir.
AnotherGreeterWithClassUse.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class AnotherGreeterWithClassUse{
2
public static void main(String[] args){
3
GreetingPrinter.printLine("Evren");
4
}
5
6 }
Bir class yapmanın avantajı, bir işlemi bir kere yapmak, bir daha da oradan kullanmaktır.
GreeterPrinter'da bir değişiklik yapma ihtiyacı duyarsak öbür class'lar otomatik olarak duruma
adapte olacaktır. Örneğin, GreeterPrinter.printGreeting()'i
public static void printGreeting(String greeted){
printLine("Merhaba "+ greeted+"! ");
}
şeklinde değiştirelim. İki uygulama da çalışınca selamlamayı ünlemle yapacaktır.
Parametere Kullanımı
GreetingPrinter görüldüğü gibi sadece "Merhaba diyebilmektedir. Bunu kullanan classlardan
birinin "Ne Haber?" deme hakkı yoktur. Bunun için başka bir class yapalım :
FlexibleGreetingPrinter.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class FlexibleGreetingPrinter{
2
public static void printLine(String line){
3
System.out.println(line);
4
}
5
public static void printGreeting(String greeted,String salutation
){
6
7
8 }
printLine(salutation+ " "+ greeted + "!" );
}
Bu printGreetings() methodu bir yerde
FlexibleGreeting.printGreetings("Dünya","Merhaba");
şeklinde başka bir yerde
FlexibleGreeting.printGreetings("Dünya","Ne Haber");
diye çağrılabilir.
Aynı İsimli Birden Fazla Method Yazmak : Overloading
İki kullanımda da mutlaka Merhaba veya Ne Haber" diye bir selamlama verilmelidir. Oysa aksi
belirtilmediği sürece "Merhaba" demesi sağlanabilir.
FlexibleGreetingPrinterWithDefault.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class FlexibleGreetingPrinterWithDefault{
2
public static void printLine(String line){
3
System.out.println(line);
4
}
5
public static void printGreeting(String greeted,String salutation
){
6
7
8
9
10
11 }
printLine(salutation+ " "+ greeted + "!" );
}
public static void printGreeting(String greeted){
printGreeting(greeted,"Merhaba");
}
Bu şekilde benzer işlevi gören aynı adlı iki method iki farklı şekilde kullanılabilir. Bir yerde
FlexibleGreetingPrinterWithDefault.printGreeting("Dünya","Nasılsın");
şeklinde çaırılabilir. Bir başka yerde
FlexibleGreetingPrinterWithDefault.printGreeting("Dünya");
denebilir. İkinci durumda biz söylemesek de "Merhaba" diyecektir. Buna overloading denir.
İkinci bir versiyon yazarak printGreeting()'i overload etmiş olduk.
Dosya Listesi

GreetingPrinter.java

GreeterWithClassUse.java

AnotherGreeterWithClassUse.java

FlexibleGreetingPrinter.java

FlexibleGreetingPrinterWithDefault.java
Object Kullanımı
Object Yaratmak
Diyelim ki aynı method, parameter'lerden biri hep aynı olmak üzere çok defa çağrılıyor.
FlexibleGreetingPrinterWithDefault.printGreeting("Dünya","İyi Misin");
FlexibleGreetingPrinterWithDefault.printGreeting("Alem","İyi Misin");
FlexibleGreetingPrinterWithDefault.printGreeting("Evren","İyi Misin");
FlexibleGreetingPrinterWithDefault.printGreeting("Güneş","İyi Misin");
görüldüğü gibi gereksiz yere "İyi Misin" parameter'i sürekli giriliyor. Çünkü bu class'a şöyle
diyemiyorsunuz. "'İyi Misin' selemlamasını aklında tut. Sonra da aynı selamlamayı Dünya, Alem
gibi isimle kullan." Oysa Java'da bunu yapmak mümkündür. Bunun için class şu şekide
olmalıdır.
NonStaticGreetingPrinter.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class NonStaticGreetingPrinter{
2
String salutation;
3
public void printGreeting(String greeted){
4
System.out.println(salutation+ " "+ greeted + "!" );
5
}
6 }
Kullanımı da şöyle olur.
NonStaticGreetingPrinter printer=new NonStaticGreetingPrinter();
printer.salutation="İyi Misin";
printer.printGreeting("Dünya");
printer.printGreeting("Alem");
printer.printGreeting("Evren");
printer.printGreeting("Güneş");
Dikkat ettiyseniz printGreeting() methodunun başında static yazmıyor. static keyword'u
methodlar için kullanılıdığında, ilgili method, bu class'tan bir nesne yaratılmaksızın kullanılabilir
demektir. Ancak bu durum kullanacağı veriyi dışardan her sefer alan method'lar için geçerlidir.
O yüzden
FlexibleGreetingPrinterWithDefault.printGreeting("Güneş","İyi Misin")
ifadesinde "İyi Misin" selamlamasını sürekli girmek zorundayız. Bunun nedeni bu classından hiç
nesne yaratılmamış olması ve veri tutma yeteneğinizin olmamasıdır. NonStaticGreetingPrinter
ise yaratılabilir ve salutation değerini saklayabilir. Bir nesne içerisinde değer saklayabilen
variable'a property denir. Kullanımı da object.property biçimindedir. Bir nesne yaratmak için
ClassName object=new ClassName();
gibi bir ifadeye gerek vardır.
NonStaticGreetingPrinter printer=new NonStaticGreetingPrinter();
gibi. Bu class'da salutation bir property'dir. printGreeting() methodunun her çağrılışında
salutation property'sinin değeri kullanılır. Bu property bir kez atandı diye bir daha değişmez
durumuda değildir.
NonStaticGreetingPrinter printer=new NonStaticGreetingPrinter();
printer.salutation="İyi Misin";
printer.printGreeting("Dünya");
printer.printGreeting("Alem");
printer.salutation="Kötü Müsün";
printer.printGreeting("Evren");
printer.printGreeting("Güneş");
biçiminde salutation değeri değiştirilebilir. Değiştikten sonra ekranda görülen selamlama da
değişir. Bunun için object'i tekrar yaramaya gerek de yoktur. NonStaticGreeter classında
salutation property'si tanımlanırken default bir değer verilebilir.
String salutation="Merhaba";
O zaman en başta bir değer atamadan da kullanılabilir.
NonStaticGreetingPrinter printer=new NonStaticGreetingPrinter();
printer.printGreeting("Dünya");
printer.printGreeting("Alem");
Dosya Listesi

NonStaticGreetingPrinter.java
Class'lar (Sınıflar)
Class,Property ve Method Kavramları
Yazılım geliştirmenin iki temel bileşeni vardır : veri ve işlev. Her tür program belli veriler
üzerinde belli işlever gerçekleştirir. Nesne, belli bir anlam bütünlüğü içeren veriler ve
gerektiğinde o verilerle çalışan işlemlerden oluşan yapıdır. Dikdörgenler prizması diye bir nesne
olduğunu düşünelim. Bununla ilgili en, boy ve yükseklik gibi veriler vardır. Ayrıca alanını ve
hacmini hesaplama gibi işlemler bulunmaktadır. Java'da veri ve işlem içeren her birime "class"
(sınıf) denir. Class'ların içerdiği veriye "property" (özellik), işlemlere de "method" (yöntem)
denir. Dikdörtgenler prizması'nı belirten bir nesne yapalım.
Göster Gizle Kopar Satır Gizle Satır Göster
1 public class RectangularPrism{
2
float width;
3
float height;
4
float depth;
5
float getVolume(){
6
return width*height*depth;
7
}
8
float getArea(){
9
return 2*(width*height+width*depth+height*depth);
10
}
11
12 }
Burada yaptığımız, dikdörtgenler prizması diye bir nesne olduğunu, bu nesnenin width, height,
depth gibi özellikleri olduğunu, bu nesneyle alan ve hacim hesaplaması yapabileceğimizi
söylemekten ibarettir. Ayrıca her property'nin veri tipini de belirttik. Dikdörgenler prizmasının
kenarların kesirli sayılarla belirtilebilir.
Instance
Yukarıda bir class'ı tanımladık ('definition' yaptık). Bu class bütün dikdörtgenler prizmalarında
olabilecek özellikler ('property'ler) ve yöntemler ('method'lar) içeriyor. Henüz ortada belli bir
prizma yok. Belli bir pizmanın "yaratılması" gerekli ki biz hacmini ve alanını bulalım. Class
tanımına uygun olarak yaratılan nesnelere instance (örnek) denir. Dikdörtgenler prizmasına bir
örnek verilmesi, başka bir deyişle bir dikdörtgenler prizması yaratılması lazım. Buna nesneye
yönelik programlamadaki terminolojiyi kullanırsak, RectangularPrism class'ından bir instance
yaratılması gerekiyor. Bir prizma yaratalım, boyutlarını 10,20 ve 30 olarak verelim. Alanını ve
hacmini hesaplayıp ekrana yazalım.
RectangularPrismTest.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class RectangularPrismTest{
2
public static void main(String[] args){
3
RectangularPrism prism=new RectangularPrism();
4
prism.width=10.0f;
5
prism.height=20.0f;
6
prism.depth=30.0f;
7
float volume=prism.getVolume();
8
System.out.println("Volume : "+volume);
9
float area=prism.getArea();
10
System.out.println("Area : "+area);
11
}
12 }
Burada RectangularPrism class'ından bir instance yarattık. İsmi de 'prism'. Bu isim rastgele
seçilmiş bir isimdir, kısaca 'p' de diyebilirdik. Ancak bir kez prism dedikten sonra aşağıda aynı
ismi kullanmak zorundayız.
Property Intialization
Bir nesne yaratılırken 'property'lerinin değerleri default (varsayılan) değerlerine atanır.
Property'ler de birer nesneyse (primitive type değilse) 'null' değerini alır. Bir değer olarak 'null'
hiç bir değeri yok demektir. Bir nesneyi yaratıp kullanan kişi bir method'u çağırmak için gerekli
olan property'lerin değerlerini önceden vermezse hata durumu oluşur. Örneğin, prism değerinin
'height' property'si verilmezse hacim hesaplanmaya çalışılırsa ne olacak? Nasıl bir hacim değeri
üretilecek? Böyle sorunlarla karşılaşmamak için property'lerin 'initialize' edilmesi gerekebilir.
Property'ler belirlenirken
float width=1.0f;
float height=1.0f;
float depth=1.0f;
şeklinde bir initialization yapılabilir. Böylelikle bir değerin verilmesi unutulsa bile belli bir değer
default alınacağından sorun çıkmaz. Height değeri verilmezse hacim 1 çıkar. Alan da
2*(1*1+1*1+1*1)=6 çıkar.
Constructor
Bir nesnenin yaratılma aşamasında bazı işlemlerin yapılması, bazı değerlerin atanması
gerekebilir. Bir nesne yaratılırken çağrılan method benzeri yapıya 'constructor' denir.
Constructor aslında bir method değildir. Ama class'la aynı ismi taşıyan, dönüş değeri olmayan
bir method olarak da düşünülebilir. Prizmanın boyutlarının daha instance yaratılırken verilmesi
bu şekilde sağlanabilir.
PrismWithConstructor.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class PrismWithConstructor{
2
float width;
3
float height;
4
float depth;
5
public PrismWithConstructor(float w,float h,float d){
6
width=w;
7
height=h;
8
depth=d;
9
}
10
float getVolume(){
11
return width*height*depth;
12
}
13
float getArea(){
14
return 2*(width*height+width*depth+height*depth);
15
}
16
17 }
Bu class'ı kullanan bir application yapalım.
PrismWithConstructorTest.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class PrismWithConstructorTest{
2
public static void main(String[] args){
3
PrismWithConstructor prism=new
PrismWithConstructor(10.0f,20.0f,30.0f);
4
float volume=prism.getVolume();
5
System.out.println("Volume : "+volume);
6
}
7 }
Method Signature
Bir method'un ismiyle birlikte sırasıyla aldığı parametre tipleri, o method'un 'signature'unu
oluşturur. Siz bir method çağırdığınızda, öncelikle o nesnede o isimde bir method olup
olmadığına bakılır. Eğer varsa, çağırdığınız parametreler'in tipleriyle birlikte eşleştirme yapılır ve
uygun bir method varsa derleme işlemi başarılı olur. Aksi takdirde kod derlenemez.
Bir nesnenin bir methodunu çağırdığınızda compiler kızıyorsa ve siz method ismini doğru
yazdığınıza eminseniz, bilinki verdiğiniz paramtereler ya eksiktir, ya fazladır, ya sırası yanlıştır
ya da parametre tipleri yanlıştır.
Overloading (Çeşitleme)
Bir method'la aynı isimde başka bir method yazılabilir. Buna overloading (çeşitleme) denir. Bu
işlem, benzer işlemleri farklı parameteler'le yapan iki method için yapılır. Bu şekilde, bir çok
method ismini öğrenmekten kurtulmuş oluruz. Ancak, overloading işleminde yeni method'un
signature'u mutlaka farklı olmalıdır ki bir method çağırdığınıza hangisini çağırdığınız
anlaşılabilsin. Zaten aynı isimde aynı parametreleri aynı sırada alan bir ikinci method yazmanın
hiç bir anlamı yoktur. Aynı işi yapıyorlarsa, bir tanesine hiç gerek yok. Farklı işler yapıyorlarsa
farklı bir isimde olmalıdır.
Bir method'un return type'ı signature'a dahil değildir. Yani aynı isimde aynı parametre tiplerini
aynı sırada belirten fakat iki ayrı return type olan iki ayrı method olamaz. Java'da bir method'un
döndürdüğü değerin fazla bir önemi yoktur. Sadece o method'u çağıran için gerekliyse bir anlamı
vardır. Hatta bir değer döndüren method, döndürdüğü değer kullanılmadan da çağrıabilir. Bazı
method'lar belki lazım olur diye belli bir değeri döndürmektedirler.
Birden Fazla Constructor
Bir class'ın farklı parametreler alan birden fazla constructor'u olabilir. Yani constrcutor'lar da
method'lar gibi 'overload' edilebilirler.
PrismWithMultipleConstructor.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class PrismWithMultipleConstructor{
2
float width;
3
float height;
4
float depth;
5
public PrismWithMultipleConstructor(float w,float h){
6
width=w;
7
height=h;
8
depth=1.0f;
9
}
10
public PrismWithMultipleConstructor(float w,float h,float d){
11
width=w;
12
height=h;
13
depth=d;
14
}
15
float getVolume(){
16
return width*height*depth;
17
}
18
19 }
Bir constructor başka bir constructor'u çağırabilir. Bunun için 'this' operatörü kullanılmalıdır.
public PrismWithMultipleConstructor(float w,float h){
this(w,h,1.0f);
}
public PrismWithMultipleConstructor(float w,float h,float d){
width=w;
height=h;
depth=d;
}
Burada iki constrcutor'dan biri diğerini çağırıyor. Kendisine gelen değerleri aynen öbürüne
devrederken bir değeri kendisi belirliyor. Bu yöntemin yararı, bir değişiklik yapıldığında sadece
tek bir constructor'un değiştirilmesinin yeterli olmasıdır.
Default & Parameter'siz Constructor'lar
Aslında, programcı hiç bir tane yazmasa dahi, her class'ın bir constructor'u vardır. Sanki
public class MyClass{
public MyClass(){
}
}
şeklinde bir constructor verilmiş gibi kabul edilir. Programcı hiç bir şey yapmadığında sağlanan
default constructor hiç parametre almaz ve hiç bir işlem yapmaz. Hiç parametre almayan ama
bazı initilization işlemleri yapan contructor'lar da yazılabilir. O zaman parameterless
constructor (parametresiz kurucu) olur. Birim küpü 2, 2, 2 boyutlarında kabul ettiğimizi
varsayalım.
PrismWithParameterlesConstructor.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class PrismWithParameterlesConstructor{
2
float width;
3
float height;
4
float depth;
5
public PrismWithParameterlesConstructor(){
6
width=2.0f;
7
height=2.0f;
8
depth=2.0f;
9
}
10
public PrismWithParameterlesConstructor(float w,float h,float d){
11
width=w;
12
height=h;
13
depth=d;
14
}
15
float getVolume(){
16
return width*height*depth;
17
}
18
float getArea(){
19
return 2*(width*height+width*depth+height*depth);
20
}
21
22 }
Görüldüğü gibi class'ın iki constructor'u var. Birisi parametreleri dışardan alıyor, diğeri içerde
belirliyor. İki constructor'u da test edelim. Birisi default contructor'la birim küp yaratsın, diğeri
boyutları vererek.
PrismWithParameterlesConstructorTest.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class PrismWithParameterlesConstructorTest{
2
public static void main(String[] args){
3
PrismWithParameterlesConstructor prism1=
4
5
6
7
8
9
10
11
}
12 }
new PrismWithParameterlesConstructor();
PrismWithParameterlesConstructor prism2=
new PrismWithParameterlesConstructor(10.0f,20.0f,30.0f);
float volume1=prism1.getVolume();
float volume2=prism2.getVolume();
System.out.println("Volume 1: "+volume1);
System.out.println("Volume 2: "+volume2);
,
Dosya Listesi

RectangularPrism.java

RectangularPrismTest.java

PrismWithConstructor.java

PrismWithConstructorTest.java

PrismWithMultipleConstructor.java

PrismWithParameterlesConstructor.java
Application Argument'ları
Komut Satırı Argument'ları
Bir Java application'unda dışarıdan argument alınması mümkündür. Bu şekilde application'un
duruma göre değişik çalıştırılabilmesi, application'u değiştirmeden mümkün olur. Normal şartlar
altında bir application'un çalışması için komut satırından
java ClassName
girilmesi gerekir. Ancak argument verilmesi durumunda
java ClassName Argument0 Argument1 ...
biçiminde kullanılır. Bu argument'ler main method'una args[] array'i olarak verilir. main()
methodunun
public static void main(String[] args)
biçiminde tanımlanmasının nedeni budur. Programın içinde argument'lara
public static void main(String[] args) {
String arg0=args[0];
String arg1=args[1];
}
biçiminde erişilebilir.
Dışarıdan aldığı isme selam veren bir application yazalım.
GreeterByArguments.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByArguments{
2
public static void main(String[] args){
3
String greeted=args[0];
4
System.out.println("Merhaba "+greeted);
5
}
6
7 }
Bu uygulamayı çalıştırırken
java GreeterByArguments Dünya
girersek ekrana "Merhaba Dünya" yazar. Aynı şekilde
java GreeterByArguments Evren
de diyebilirdik. Yani bizim application'umuzu kullanan kişi istediği değeri girebilir, istediği
selamı ekrana çıkarabilir. Elbette biz bunu programın içinde de yapabilirdik. Ancak bu durumda
her değişiklikte yeniden program yazmamız veya her sefer kodu değişitirip derlememiz
gerekirdi. Oysa bir uygulama bir kez yazıldıktan sonra başka bir yerde hatta başka bir ülkedeki
insanlar tarafından kullanılabilir olmalıdır. Her değişiklikte application'u yeniden yazmak çoğu
kez mümkün olmaz.
Argument'ların Kontrolü
Yukarıdaki uygulama çalıştırılırken argument vermek unutulursa hata uyarısı alınır. Çünkü
uygulama mutlaka neyi selamlayacağının girilmesini istemektedir. Bu hatadan kurtulmak için
kullanıcının bir değer girip girmediği kontrol edilebilir.
GreeterByArgumentsChecked.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByArgumentsChecked{
2
public static void main(String[] args){
3
if(args.length==1){
4
String greeted=args[0];
5
System.out.println("Merhaba "+greeted);
6
}
7
}
8 }
Uygulamaya argument girilmemesi durumunda sadece hata vermemesi değil, kullanıcıya bir
uyarı mesajı vermesi daha uygun olur.
GreeterByArgumentsWithWarning.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByArgumentsWithWarning{
2
public static void main(String[] args){
3
if(args.length==1){
4
String greeted=args[0];
5
System.out.println("Merhaba "+greeted);
6
}else{
7
System.out.println("Lutfen kime selam verilecek girin");
8
}
9
}
10 }
Genellikle application'lar bu durumda girilecek argument'ler hakkında bilgi veren bir yazıyı
ekrana basarlar ve programdan çıkarlar. Programdan çıkmak, yani application'un çalışmasını
kesmek için System.exit() methodu kullanılır.
GreeterByArgumentsWithHelp.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByArgumentsWithHelp{
2
public static void main(String[] args){
3
if(args.length==1){
4
String greeted=args[0];
5
System.out.println("Merhaba "+greeted);
6
}else{
7
System.out.println("kullanma:java GreeterByArguments
GreeterByArgumentsWithHelp greeted");
8
System.exit(0);
9
}
10
}
11
12 }
Exit methoduna '0' girmenin manası, programın doğal olarak, programcı tarafından
durdurulduğunu göstermektir. Bir hata olduğunu belirtmek için 0 dışında bir değer, örneğin '-1'
girilebilir.
Bir application'un, belli bir argument'in girilmemesi durumunda da varsayılan (default) değerle
çalışması sağlanabilir.
GreeterByArgumentsWithDefault.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByArgumentsWithDefault{
2
public static void main(String[] args){
3
String greeted;
4
if(args.length==1){
5
greeted=args[0];
6
}else{
7
greeted="Dunya";
8
}
9
System.out.println("Merhaba "+greeted);
10
}
11
12 }
Bu application
java GreeterByArgumentsWithDefault Evren
diye de çağrılabilir,
java GreeterByArgumentsWithDefault
şeklinde de. İkinci durumda "Merhaba Dünya" yazacak ve hata vermeyecektir.
Dosya Listesi

GreeterByArguments.java

GreeterByArgumentsChecked.java

GreeterByArgumentsWithWarning.java

GreeterByArgumentsWithHelp.java

GreeterByArgumentsWithDefault.java
Değişkenler ve Tipler
Type kavramı
Java'da her variable'ın belli bir type (tip)'i olması gereklidir. Tip, variable'ın nasıl bir veri
taşıdığını ve onun üzerinde ne gibi operasyonlar yapabileceğimizi belirler. Değişkenin type'ı
tamsayıysa çıkarma yapabilirsiniz, String ise yapamazsınız. Java yapılan işlemlerde kullanılan
değerlerin tiplerine son derece dikkat eder. Herhangi bir tip uyumsuzluğunda derleme hatası
gelir.
İki sayıyı toplayıp sonucu ekrana basan bir application yapalım.
IntegerAdder.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class IntegerAdder {
2
public static void main(String[] args){
3
int a=200;
4
int b=100;
5
int sum;
6
sum=a+b;
7
System.out.println("Sum is "+sum);
8
}
9 }
Bu application'da
int a=200;
ifadesi bir variable'ın declaration'unu içerir. Tanımlama şu biçimde yapılabilir.
Type Variable=IntialValue;
Elbette bu declaration değişkenin ilk değerinin belli olması durumunda kullanılır. İlk değerin
daha sonra belli olması durumunda declaration
Type Variable;
biçiminde yapılır. Toplamın sonucu baştan bilinmediği için önce
int sum;
biçiminde declaration yapılabilmiştir. Değeri daha sonra bir işlem sonucunda belli olacaktır.
sum=a+b;
Buradaki iki satırı tek satır olarak yazmak da mümkündür
int sum=a+b;
Bu durumda tanımlama ve işlem aynı ifade içerisinde yer almış olmaktadır.
Class Type'lar
Java'da temel olarak iki çeşit type vardır : primitive type'lar ve class type'ları. Örneğin int
primitive type'tır. String'de bir class type'ıdır. İki String type'ındaki veriyi birleştirmek istersek
yine + kullanılır. Ancak işlem bu kez toplama değil birleştirme olur.
StringConcatanator.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class StringConcatanator{
2
public static void main(String[] args){
3
String a="200";
4
String b="100";
5
String concatanation;
6
concatanation=a+b;
7
System.out.println("Birleştirilmiş String is
"+concatanation);
8
}
9 }
Bu uygulama değeri "200" olan String type'ındaki a ile değeri "100" olan String type'ındaki b
değişkenini birleştirir. Sonu yine bir String'tir ve "200100"dür. Görüldüğü gibi variable'ların
type'ı işlemlerin nasıl yapılacağını belirlemektedir. int type'ınındaki bir variable
int a=200;
şeklinde tanımlanırken String type'ındaki a
String a="200";
biçiminde tanımlandı. String değerleri belirtmek için çift tırnak kullanılır.
Primitive Type'lar
Primitive type'lar tamsayı, gerçel sayı, mantıksal ve karakter type'lar dır. Tamsayı type'ları,
alabilecekleri maksimum ve minimum değerlerin sırasına göre byte, short, int, long'dur. Gerçek
sayılar float ve ondan daha büyük değerleri alan double'dır. Tip olarak boolean sadece true ve
false gibi iki değer alır. char tipi de harf,rakam ve noktalama işaretleri gibi karakterleri tutabilir.
PrimitiveTypesPrinter.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class PrimitiveTypesPrinter{
2
public static void main(String[] args){
3
int i=50000;
4
short s=500;
5
long l=5L;
6
byte b=3;
7
float f=2.5f;
8
double d=3.5;
9
char c='K';
10
11
12
13
14
15
16
17
18
19
}
20 }
boolean x=true;
System.out.println("
System.out.println("
System.out.println("
System.out.println("
System.out.println("
System.out.println("
System.out.println("
System.out.println("
Integer : " + i );
Short: "+ s );
Long: "+ l );
Byte : "+b );
Float : "+ f );
Double : "+ d );
Characater : "+c );
Boolean : "+ x );
Dosya Listesi

IntegerAdder.java

StringConcatanator.java

PrimitiveTypesPrinter.java
Basit Data Tipleri
Array'ler
Birden fazla veri sıralı olarak saklanmak istenirse diziler kullanılır. Dizilerin declaration'u
Type[] name=new Type[Length];
biçiminde olur. Örneğin 10 elemanlı bir int dizisi
int[] a=new int[10];
şeklinde tanımlanır
Dizinin bir elemanına erişim de
name[i]
biçiminde gerçekleşir. Örneğin yukarıdaki dizinin 3. elemanının değerini 7 yapmak için.
a[3]=7;
yazmak yeterlidir.
Dizinin 5'inci elemanının değerine erişim de
int x=a[5];
biçiminde olur. Bir array'in değerlerini daha tanımlarken belirlemek mümkündür
int[] a=new int[10]{10,9,8,7,6,5,4,3,2,1 };
Bir array'in elemanlarını toplayan bir uygulama yazalım.
ArraySum.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class ArraySum{
2
public static void main(String[] args){
3
int[] a=new int[]{10,9,8,7,6,5,4,3,2,1 };
4
int sum=0;
5
for(int i=0;i<a.length;i++){
6
sum+=a[i];
7
}
8
System.out.println("Sum of Array : "+ sum);
9
}
10
11 }
Array'ler de aslında bir nesnedir. Loop'ta kullanılan a.length ifadesinde a array'inin, array'in
boyunu veren length adlı property'si kullanılmıştır.
Primitive Type'ların Wrapper'ları
Java'da herşey class'dır. Ancak class olarak kullanılmayan primitive type'lar da bulunur. Her
primitive type'ın bir de class karşılığı bulunur ki bu type'la ilgili yapılabilecek işler bu class
aracılığıyla yapılabilsin. Bu class'lara wrapper denir. İçlerinde bir primitive type tutma
özellikleri vardır. Örneğin int tipine karşılık Integer class'ı vardır. Bu class'ın içinde int tipiyle
ilgili çeşitli property ve methodlar bulunur. Bir String'in int'e veya bir int'in String'e
dönüştürülmesi için birer method bulunur. Örneğin, kesirli bir sayı gösteren bir String'i kesirli bir
sayı haline getirmek için
String s="1.5f";
float f=Float.parseFloat(s);
şeklinde bir işlem gereklidir. Bir integer'i String'e çevirmek için
int i2=2;
String s2=Integer.toString(i2);
şeklinde bir kod yazılır.
Bir primitive tip yerine, wrapper'ı kullanılabilir.
Integer w=new Integer(2);
Daha sonra ilkel hali
int i=w.intValue();
şeklinde alınabilir. Dışardan argument olarak integer bir sayı alan program yapalım
IntegerSum.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class IntegerSum{
2
public static void main(String[] args){
3
String a=args[0];
4
int i=Integer.parseInt(a);
5
String b=args[1];
6
int j=Integer.parseInt(b);
7
int sum=i+j;
8
System.out.println("Sum : "+sum);
9
}
10 }
String Class'ı
Yazı veya metin denilen verileri saklamak için iki yol vardır. Ya char array'i kullanmak.
char[] c=new char[]{'J','a','v','a'};
veya String class'ını kullanmak
String s="Java";
String s=new String("Java");
String class'ı da aslında içerisinde bir character array taşır.
char[] c=new char[]{'J','a','v','a'};
String s=new String(c);
diyerek bir character dizisinde String üretebiliriz. Bir string'in character'lerine
char[] a=s.toCharArray();
şeklinde erişilebilir. String class'ı bu tip veri üzerinde ihtiyaç duyulabilecek bir çok method
içermektedir. İçerisinde "JAVA 1.2" ifadesini içeren bir cumleyi, "Java 1.3" ile değiştirme
uygulaması yapalım.
VersionUpgrader.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class VersionUpgrader{
2
public static void main(String[] args){
3
String string="We use JAVA 1.2 in application development";
4
String older="JAVA 1.2";
5
String newer="Java 1.3";
6
int start=string.indexOf(older);
7
String before=string.substring(0,start);
8
int finish=start+older.length();
9
int end=string.length();
10
String after=string.substring(finish,end);
11
String result=before+newer+after;
12
System.out.println("Result : "+result);
13
}
14 }
String.indexOf() methodu' belirtilen verilen String'in asıl String'in içinde hangi sırada basladığını
gösteriyor. String.substring() bir String'in bir parçasını almak için, String.length() de character
sayısını bulmak için kullanılır.
Dosya Listesi

ArraySum.java

IntegerSum.java

VersionUpgrader.java
Akış Kontrolü
'For' Loop'u
Bir programın akışını kontrol etmek için bazı yapılar bulunur. Belli bir koşulun gerçekleşmesine
göre bir iş, gerçekleşmemesine göre başka bir iş yapılabilir. Bir işlemin belli bir koşul
sağlanıncaya kadar veya sağlandığı sürece yapılması da istenebilir. Aynı selamı 10 kere ekrana
basan bir uygulama yazalım.
GreeterByForLoop.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByForLoop{
2
public static void main(String[] args){
3
for(int i=0;i<10;i++){
4
System.out.println("Merhaba Dunya");
5
}
6
}
7
8 }
Bir işlemin kaç kere yapılacağını belli olduğu tipteki loop'lar 'for' loop'larıdır. Yapısı
for( FirstStatement; TerminationCondition; StementForEachIteration ){
BlockToExcecute;
}
biçimindedir. Burada for loop'unun içine ilk olarak, en başta (sadece bir kere) yapılması istenen
işlem, ikinci olarak loop'tan çıkmak için sağlanması beklenen koşul girilir. Son olarak da her
sefer yapılması gereken işlem belirtilir. Örnek'te i değişkeni 0'a eşitleniyor, her sefer 10'dan
küçük mü diye kontrol ediliyor ve her sefer bir arttırılıyor. i=10 olduğunda i>10 ifadesi artık
yanlış olacağından loop o noktada bitmektedir. int i=0; ifadesi hem bir variable declaration'u
hem da initial value verme işlemidir. Bu, Java gibi bir değişkenin tipinin ve değerinin baştan
belli olmasını zorunlu tutan dillerde gereklidir. i++ ifadesi de bir i değerinin bir arttırılması
anlamına gelir i=i+1 yazmanın kısa ve hızlı bir yoludur.
While Loop'u
Yukarıdaki işlemi başka bir loop çeşidi olan while loop'u ile de gerçekleştirebilirdik.
GreeterByWhileLoop.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByWhileLoop{
2
public static void main(String[] args){
3
int i=0;
4
while(i<10){
5
System.out.println("Merhaba Dunya");
6
i++;
7
}
8
}
9
10 }
Görüldüğü gibi while döngüsünün yapısı
while(ContinuationCondition){
BlockToExecute;
}
biçimindedir. Örnekte for döngüsünün yerine kullanılmıştır ancak while döngüsünün işlevi bir
işlemi belli bir koşul gerçekleştiği sürece yapmaktır. Bu koşul bir sayının belli bir değere
ulaşması olduğu gibi döngünün içerisinde belirlenebilecek herhangi bir değer de olabilir. Özetle
bu koşul gerçekleştiği sürece bu işlemi yap anlamına gelir.
'Do-While' Loop'u
Aynı işlemi while döngüsünün bir başka türü olan do-while döngüsü ile de halledebiliriz.
GreeterByDoWhileLoop.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByDoWhileLoop{
2
public static void main(String[] args){
3
int i=0;
4
do{
5
System.out.println("Merhaba Dunya");
6
i++;
7
}while(i<10);
8
}
9
10 }
do-while döngüsünün yapısı while döngüsünün tersidir.
do{
BlockToExecute;
}while(ContinuationCondition);
biçimindedir. Bu tip döngüde önce işlem yapılmakta sonra döngünün bitip bitmediği kontrol
edilmektedir. Elbette koşulu önce veya sonra kontrol etmek çoğu kez isteğe bağlıdır. Ancak bir
koşulun gerçekleşip gerçekleşmediği ancak döngünün içinin bir kez çalıştırılması sonucunda
belli oluyorsa do-while kullanmak zorunludur.
'If' Yapısı
Programın akışını kontrol etmekte en çok kullanılan yapı if yapısıdır. Bir koşul gereçkleşiyorsa
belli bir işlemi gerçekleşmiyorsa bir başkasını yapmaya yarar. Ancak bu bir kez yapılan bir
kontroldür ve programın akışı bir kez buradan dallandı mı bir daha aynı koşula bakılmaz. Adı ve
cinsiyeti girilen bir insana erkekse selam veren bir uygulama yazalım.
GreeterByIfStatement.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByIfStatement{
2
public static void main(String[] args){
3
String name=args[0];
4
String genus=args[1];
5
if( genus.equals("Erkek") ){
6
System.out.println("Merhaba Bay "+name);
7
}
8
9
10 }
}
Burada kontrolü yapılan koşul genus.equals("Erkek") şeklindedir. Yani; dışarıdan alınan genus
arguman'ı "Erkek" değerine eşitse.
'If-Else' Yapısı
Bir koşulun sağlanmaması durumunda da bir işlemi gerçekleştiren bir program yazalım.
GreeterByIfElseStatement.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByIfElseStatement{
2
public static void main(String[] args){
3
String name=args[0];
4
String genuine=args[1];
5
if(genuine.equals("Erkek") ){
6
System.out.println("Merhaba Bay "+name);
7
}else{
8
System.out.println("Merhaba Bayan "+name);
9
}
10
}
11 }
'If-Else-If' Yapısı
Yukarıdaki örnek cinsiyetin erkek değilse kadın olduğunu varsaymaktadır. Yanlış bir ifade
girilse de kadın kabul edilmesi istenmeyebilir.
GreeterByIfElseIfStatement.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterByIfElseIfStatement{
2
public static void main(String[] args){
3
String name=args[0];
4
String genuine=args[1];
5
if( genuine.equals("Erkek") ){
6
System.out.println("Merhaba Bay "+name);
7
}else if(genuine.equals("Kadın")){
8
System.out.println("Merhaba Bayan "+name);
9
}else{
10
System.out.println("Merhaba Bay/Bayan "+name);
11
}
12
}
13 }
Bu şekilde istendiği kadar if ve else arasında istendiği kadar else if yapısı kullanılabilir.
Switch-Case Yapısı
Çok fazla sayıda if-else kullanmak yerine basit tipte veriler için switch-case diye başka bir
kontrol ifadesi bulunmaktadır. Kullanıcıdan girilen sayıya göre bir işlem gerçekleştiren bir
uygulama yazalım. Kullanıcı tek rakam girmeye zorlanırsa 10 tane ihtimal vardır ve çok sayıda
if-else yapısı kurmak işi karmaşıklaştıracaktır.
GreeterBySwitchCaseStatement.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class GreeterBySwitchCaseStatement{
2
public static void main(String[] args){
3
String argument=args[0];
4
int number=Integer.parseInt(argument);
5
switch(number){
6
case 0: System.out.println("0 Girdiniz.");break;
7
case 1: System.out.println("1 Girdiniz.");break;
8
case 2: System.out.println("2 Girdiniz.");break;
9
case 3: System.out.println("3 Girdiniz.");break;
10
case 4: System.out.println("4 Girdiniz.");break;
11
case 5: System.out.println("5 Girdiniz.");break;
12
case 6: System.out.println("6 Girdiniz.");break;
13
case 7: System.out.println("7 Girdiniz.");break;
14
case 8: System.out.println("8 Girdiniz.");break;
15
case 9: System.out.println("9 Girdiniz.");break;
16
}
17
}
18
19 }
Görüldüğü gibi String tipinde olan argument, Integer.parseInt methoduyla int tipine çevrilmiştir.
Çünkü switch ifadesi sadece int, char gibi basit tiplerle çalışmakta, içerisine herhangi bir class
tipi kabul etmemektedir.
Dosya Listesi

GreeterByForLoop.java

GreeterByWhileLoop.java

GreeterByDoWhileLoop.java

GreeterByIfStatement.java

GreeterByIfElseStatement.java

GreeterByIfElseIfStatement.java

GreeterBySwitchCaseStatement.java
Exception'lar
Exception Kavramı
Her program doğru olarak yazılması durumunda hatasız olarak çalışacaktır. Ancak bu ideal bir
durumdur ve hatasız bir program yazmak hiç bir kimseye nasip olmamıştır. Önemli olan hatasız
bir uygulama yapmak değil, hata oluştuğunda bunu programın anlayabilmesini ve önlem
alabilmesini sağlamaktır. Hiç bir şey yapılamıyorsa, en azında kullanıcıya hatanın bildirilmesi
gerekmektedir. Ancak, bir hata olması durumunda program kesinlikle çökmemelidir.
Hatanın önlenmesi için en çok kullanılan yöntem, hata oluşturabilecek sorunların konrol
edilmesidir. Örneğin, bir dosyayı okumadan önce programcı okumak istediği bir dosyanın
okumaya çalıştığı yerde olup olmadığını kontrol edebilir. Ancak her durumu programcının
öngörebilmesi ve önlemini alması her zaman mümkün olmaz. Hatanın ve anormal durumların ele
alınmasında en iyi yol 'exception' kullanmaktadır. Exception'ların devreye girmesiyle hata
ayıklamak çok daha kolaylaşmıştır. Exception'larla bir program parçası hatayı anlamaya ve
değerlendirmeye zorlanabilir. Örneğin okunacak bir dosyanın orada bulunmaması durumunda
programcının bunu anlaması ve bir tepki vermesi zorunlu hale getirilebilir.
Try-Catch Bloğu
Çağrılan bir method'ta hata oluşması durumunda bunun yakalanması için try-catch bloğu
kullanılır :
try{
// Hata oluşturabilecek herhangi bir işlem.
}catch(Exception e){
// Hata durumunda yapılacaklar.
}
Girilen bir sayının tek mi çift mi olduğunu anlayan basit bir program yapalım.
OddEvenDifferantiatorWithoutException.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class OddEvenDifferantiatorWithoutException{
2
public static void main(String[] args){
3
String input=args[0];
4
int number=Integer.parseInt(input);
5
int mod=number % 2;
6
if ( mod == 0){
7
System.out.println("cift");
8
}else{
9
System.out.println("tek");
10
}
11
12
}
13 }
Bu program çalışır durumdadır. Kullanıcının girdiği bir sayının çift mi tek mi olduğunu
anlayabilmektedir. Ancak kullanıcı ya sayı yerine "A" girerse? Bu durumda program
çalışmayacak o anda her şey çokecektir. Bunu önlemenin yolu elbette önce girilen String'n bir
sayı olup olmadığını anlamaktır. Ancak bu çok karmaşık bir işlemdir. Bütün karakterler alınmalı
ve her birinin rakam olup olmadığı tek tek kontrol edilmelidir. Bunu yapan isNumber() diye bir
method yazılabilir. Ancak Exception kullanarak daha basit bir şekilde sorun çözülebilmektedir.
OddEvenDifferantiatorWithException.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class OddEvenDifferantiatorWithException{
2
public static void main(String[] args){
3
try{
4
String input=args[0];
5
int number=Integer.parseInt(input);
6
int mod=number % 2;
7
if ( mod == 0){
8
System.out.println("Çift");
9
}else{
10
System.out.println("Tek");
11
}
12
System.out.println("Teşekkürler");
13
}catch(NumberFormatException e){
14
System.out.println("Sayı giriniz!");
15
}
16
17
}
18 }
NumberFormatException, Integer class'ının static methodu parseInt() tarafından
fırlatılabilmektedir. Burada sadece Exception da yakalanabilirdi. Ancak bu durumda diğer
hatalar için de aynı mesaj çıkacaktı.
Try-Catch-Finally
Bir exception'ın fırlaması durumunda kodun yürütülmesi o noktada durur ve artık catch()
bloğunun içerisindekiler yürütülmeye başlar. Bazı durumlarda bir işlemin hata olsa da olmasa da
gerçekleştirilmesi istenebilir. Try bloğunun içindeki kod parçaları hata durumunda çalışmayacağı
için buraya konması doğru olmaz. Yukarıdaki örnekte hata olması durumunda "Teşekkürler"
yazısı ekrana basılmayacaktır. Diyelim ki biz kullanıcıya hata yapsa da yapmasa de teşekkür
etmek istiyoruz. Bunun için kod şu hale getirilmeklidir.
OddEvenDifferantiatorWithExceptionAndFinally.javaIndir Göster Gizle Kopar Satır Gizle Satır
Göster
1 public class OddEvenDifferantiatorWithExceptionAndFinally{
2
public static void main(String[] args){
3
try{
4
String input=args[0];
5
int number=Integer.parseInt(input);
6
int mod=number % 2;
7
if ( mod == 0){
8
System.out.println("cift");
9
}else{
10
System.out.println("tek");
11
}
12
}catch(NumberFormatException e){
13
System.out.println("enter number");
14
}finally{
15
System.out.println("thank");
16
}
17
18
}
19 }
Throw
Programcı istediği yerde kendisi de bir Exception fırlatabilir. Bir yerde throw keyword'üyle
fırlattığı exception'u başka bir yerde kendi yakalayabilir. Girilen bir rakamaın 1000'ler
basamağındaki rakamını bulan bir program yazalım. Ancak bir sayının binler basamağındaki
sayısını bulabilmek için girilen sayının binden büyük olması gerekir.
ThousandsFinderWithThrow.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class ThousandsFinderWithThrow{
2
public static int getTousands(int number){
3
if(number<1000){
4
throw new IllegalArgumentException("1000'de kuçuk sayi
girilmemeli!");
5
}
6
int division=number/1000;
7
int digit=division % 10;
8
return digit;
9
}
10
public static void main(String[] args){
11
try{
12
String input=args[0];
13
int number=Integer.parseInt(input);
14
int digit=getTousands(number);
15
System.out.println("Binler : "+digit);
16
}catch(IllegalArgumentException e){
17
String message=e.getMessage();
18
System.out.println(message);
19
}
20
21
}
22 }
Throws
Bir method kendisini çağıran kodu Exception'u yakalamaya (try-catch içine almaya) zorlayabilir.
Bunun için yapılması gereken method'un tanımında throws keyword'üyle Exception'un adının
verilmesidir.
public void method()
throws AnyException
{
// Her hangi bir lod parçası.
}
Bu methodun çağrıldığı yerde mutlaka
public void another(){
try{
object.method();
}catch(AnyException e){
System.out.println("Bir hata oluştu!");
}
}
biçimde yakalanması gerekir.
Bir method bir exception'u yakalamak istemezse kendisi de onu throws listesine alabilir.
public void another()
throws AnyException
{
object.method();
}
Ancak bu sefer de bu methodu hangi method çağırıyorsa o yakalamak zorundadadır. Tabii o da
throws listesinde göstermezse. En sonunda mutlaka bir method bu exception'u yakalayacaktır.
RuntimeException'lar
Bazı exceptionları yakalamak zorunlu değidir. Bunun için o exception'un runtime exception
olması gerekir. Yani RuntimeException veya onu extend etmiş herhangi bir exception olması.
Bu tip exception'lar genellikle hatanın çalışma esnasında yaklanması gerektiği durumlarda
kullanılır. IllegalArgumentException ve NumberFormatException class'ları runtime
exception'dur.
Exception Türetme
Kullanıcı kendi exception'larını da yazabilir.
class AnyKindOfException extends Exception{
}
ve diğer exceptionlarla aynı şekilde fırlatabilir veya yakalayabilir.
Dosya Listesi

OddEvenDifferantiatorWithoutException.java

OddEvenDifferantiatorWithException.java

OddEvenDifferantiatorWithExceptionAndFinally.java

ThousandsFinderWithThrow.java
StringTokenizer ve StringBuffer
Java'da String işlemlerini kolaylaştırmak için çok çeşitli class'lar bulunur. Bunlar arasında bir
string'i parçalara ayırmay ayarayan StringTokenizer ve string'leri birleştirmeye yarayan
StringBuffer en fazla kullanılanlarındandır.
StringTokenizer
Bir string'i belli karakterlere göre parçalamak için StringTokenizer class'ı kullanılır. Her bir
parçaya 'token' denir. Sınırlayıcı karakterlerin her biri 'delimiter' diye adlandırılır.
StringTokenizer, verilen stringi verilen karakterlere göre parçalar ve sırayla verir.Çalışma
mantığı token'ları bir dizi olarak verme şeklinde olmaz. Token'lara erişim sırayla gerçekleşirilir.
Bir tümce içinde geçen sözcükleri bulmaya yarayan bir kod parçası yazalım.
String sentence="Java is a simple, object-oriented, distributed,
interpreted,"
+" robust, secure,architecture-neutral, portable, multithreaded,
dynamic,"
+" buzzword-compliant, general-purpose programming language.";
String delims=" ;,.-";
StringTokenizer tokenizer=new StringTokenizer(sentence,delims);
while(tokenizer.hasMoreTokens()){
String token=tokenizer.nextToken();
System.out.println(token);
}
StringTokenizer, parçalayacağı string'i ve sınırlayıcı karakterleri constructor'da ister.
Delimiter'ler bir string biçiminde birleştirilerek verilir. Bu sadece çalışma kolaylığı sağlamak
içindir, yoksa verilen string'deki her karakter ayrı ayrı düşünülür. Whitespace (boşluk)
karakterleri aynen, 'yeni satır' (new line) gibi karakterler '\' ile kaçılarak belirtilir.
StringTokenizer Enumeration interface'ini implement eder. Başka bir deyişle StringTokenizer
da Enumeration olarak erişilebilir.
StringTokenizer tokenizer2=new StringTokenizer(sentence,delims);
while(tokenizer2.hasMoreElements()){
String token=(String)tokenizer2.nextElement();
System.out.println(token);
}
Burada hasMoreTokens() ve nextToken() yerine hasMoreElements() ve nextElement()
kullanılmıştır. Ancak Enumeration string değil object tipiyle çalıştığı için token'ın string olarak
kullanılabilmesi için cast edilmesi gerekir.
Bazı durumlarda delimiter'ler de gerekebilir. StringTokenizer constructor'unda parametre olarak
'returnDelims' değerini alır. Default'u false olan bu değer true girilirse, token'larını yanısıra
delimiter'lar da döner sonuçta.
boolean returnDelims=true;
StringTokenizer tokenizer3=new StringTokenizer(sentence,delims,returnDelims);
while(tokenizer3.hasMoreTokens()){
String token=tokenizer3.nextToken();
System.out.println(token);
}
StringTokenizerTest.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.util.*;
2 public class StringTokenizerTest {
3
public static void main(String[] args){
4
String sentence="Java is a simple, object-oriented, distributed,
interpreted,"
5
+" robust, secure,architecture-neutral, portable, multithreaded,
dynamic,"
6
+" buzzword-compliant, general-purpose programming language.";
7
StringTokenizer tokenizer=new StringTokenizer(sentence);
8
while(tokenizer.hasMoreTokens()){
9
String token=tokenizer.nextToken();
10
System.out.println(token);
11
}
12
String delims=" ;,.-\n\r\t";
13
StringTokenizer tokenizer2=new StringTokenizer(sentence,delims);
14
while(tokenizer2.hasMoreElements()){
15
String token=(String)tokenizer2.nextElement();
16
System.out.println(token);
17
}
18
boolean returnDelims=true;
19
StringTokenizer tokenizer3=new
StringTokenizer(sentence,delims,returnDelims);
20
while(tokenizer3.hasMoreTokens()){
21
String token=tokenizer3.nextToken();
22
System.out.println(token);
23
}
24
}
25 }
StringBuffer
Java'da metin biçimindeki verileri tutmak için String class'ı kullanılır. Bu class içerisinde bir
char[] (karakter dizisi) tutar. Bu değişmez. Dolayısıyle birden fazla string'in birleştirlmesi, bir
string'in içersinden bir bölümünün çıkarılması gibi işlemler yeni bir string üretilmesi şeklinde
olur. Bu işlemler için aslında programcı bilmese de StringBuffer adlı class kullanılır. Örneğin
x = "a" + 4 + "c"
şeklindeki kod
x = new StringBuffer().append("a").append(4).append("c").toString()
şeklindeki kodun kısa yazılışıdır. Ancak işlem tek ifade içerisinde olmadığı durumlarda, bir çok
String nesnesi yaratılır. Çünkü string içerisindeki değerler sabittir. Bir karakter bile eklense yeni
bir string yaratılmış olur.
x+="a";
x+="b";
gibi basit ifadelerde bile çok sayıda string nesnesi yaratılır. Dolayısıyla çok fazla stirng
operasyonu içeren kodların Stirng class'ını kullanması performans açısından kayba yol açar. O
yüzden bu durumlarda StringBuffer kullanmak faydalı olabilir. Bu nesne de bir char[] (karakter
dizisi) tutar ancak bu eklem çıkarma yapıldıkça değişir, gerektiğinde uzar. StringBuffer nesnesi
StringBuffer buffer=new StringBuffer();
şeklinde boş olarak,
StringBuffer buffer=new StringBuffer("initial");
da olduğu gibi başlangıçta bir değer vererek olabilir. Bir string eklemek için
buffer.append("mystring");
şeklinde bir ifade gerekir. Buradaki append() methodu temel tipler ve object için oveload
edilmiştir (her biri için ayrı bir method append() yazılmıştır). Karakter veya sayı eklemek için,
örneğin
buffer.append('A');
buffer.append(2.4);
ifadeleri yeterlidir. Bu append() methodu kolaylık olsun diye StringBuffer'ın kendisini geri
döndürmektedir.
buffer.append("first").append("second");
şeklinde bir ifade yazılabilir. İlk append method'undan buffer döndüğü için ikinci bir append
yazılabilmektedir. StringBuffer'ın ortasında bir yere metin eklemek için
buffer.insert(5,"xxx");
şeklinde bir ifade gereklidir. Burada "xxx" 5'. karakterden itibaraen araya sokulur. Belli bir kısmı
değiştirmek için
buffer.replace(3,5,"yyy");
şeklinde bir ifade yeterlidir. Burada replace() method'uyla İndisi 3'ten başlayıp 5'e kadar giden
bölge silinir yerine "yyy" konur. StringBuffer'la yapılacak işler bittikten sonra String class'ına
çevirmek gerektiğinde
String string=buffer.toString();
şeklinde toString() method'u kullanılır. Genellikle üzerinde değişiklikler yapılacak string önce
StringBuffer class'ına constructor'da verilir. En son işlemler bittikten sonra tekrar toString
methodu'yla string'e döndürülür.
StringBufferTest.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class StringBufferTest {
2
public static void main(String[] args){
3
StringBuffer buffer=new StringBuffer();
4
buffer.append("One");
5
buffer.append("Two");
6
buffer.append("Three");
7
buffer.append("Four").append("Five");
8
buffer.append('S').append('i').append('x');
9
char[] chars= new char[]{'S','e','v','e','n'};
10
buffer.append(chars);
11
buffer.insert(6,"-");
12
buffer.replace(12,16,"-4-");
13
String string=buffer.toString();
14
System.out.println(string);
15
String sub=buffer.substring(19,22);
16
System.out.println(sub);
17
}
18 }
Dosya Listesi

StringTokenizerTest.java

StringBufferTest.java
Vector ve Hashtable
Java'da bir den fazla değeri tutmaya yarayan temel veri yapısı array (dizi)dir. Diziler 'sabit
miktarda değerleri' tutarlar ve bir 'index' (indis) aracağılığıyla elemanlara erişim sağlarlar.
Ancak bazı durumlarda elemanların sayısı baştan belli değildir. Sonradan belli olur veya baştan
belirlenen değer sonradana değişir. Bazı durumlarda da erişim için index kullanılamaz. Bir arada
tutulması istenen elemanlar için bir index gibi bir sayı tutmak anlamsızdır. Her eleman sayı
olmayan bir 'key' (anahtar)'a bağlı olabilir. Veritabanları için ID alanları, web sitelerinde
kullanıcı isimleri, kimlik veya vergi numaraları bunlara örnektir. Bu tipte veriler için dizi
kullanmak anlamsızdır, çünkü elamanlar sıralı değildir. '3.' veya '5.' elemanı diyebileceğimiz bir
eleman yoktur. Elemanları sayısının da sırasının da anlamı yoktur. Örneğin, 3. eleman silinince
yani aradan bir eleman çıkınca 5. eleman 4. eleman haline gelir. Bu durumda daha önce 5'ler
erişilebilen elemanı 4 numaraya düşebilir. Bu durumlarda dizi kullanılamaz.
Java'da birden fazla nesneyi tutmak için Collection'lar kullanılır. Collectionlar Java 2 Standart
Edition'a 1.2'de dahil olmuştur. Bu versiyondan önce Collection gibi kullanılabilecek sadece
Vector ve Hashtable gibi bir kaç class bulunmaktaydı. Collection'lar Java'ya dahil olunca bu
class'lar da Collection'ların arasında katılmıştır. Collection'ların daha yeni ve daha kullanışlı
olmalarında rağmen Java'da bir çok yerde Vector ve Hashtable kullanılmaya devam
edilmektedir. Bula 'eskimiş' değildirler. Bu iki class'ın öğrenilmesi Collection'ları öğrenmek için
iyi bir başlama noktası olabilir.
Vector
Vector, temelde bir array'le aynı işlevi görür. Elemanlarına 'index'le erişilebilir. Ancak index
olmadan erişmek de mümkündür. 'Araya şu elanı sok' veya 'Sonuna şu elemanı ekle' denebilir.
Eleman sayısı başta belirlenmek zorunda değilidir. Eleman eklendikçe Vector büyür.
Vector tanımlamak, Vector class'ına ait bir nesne tanımlamaktır :
Vector v=new Vector();
Eleman eklemek te bu nesnenin bir method'unu çağırmak şeklinde olur :
v.addElement("x");
aynı şekilde eklenmiş bir elemanını index'iyle almak için bir method çağrılır
String v=(String) v.elementAt(3);
Cast
Burada 'cast' yapmak zorundayız. Vector ve Hashtable'ın, genel olarak bütün Collection'ların tip
bilgisini kaybetmesi gibi bir durum söz konusudur. Collection'lar genel yapılar olduğu için
içlerinde barındırdıkları nesnenin tipini (class'ını) bilmezler. Onlar sadece 'Object' tutarlar.
Örneğin 'elementAt' methodu
public Object elementAt(int index);
şeklinde tanımlanmıştır. 'addElement' metodu da
public void addElement(Object o);
şeklinde tanımlanmış. 'String' class'ı bir obje olduğundan, yani her String aynı zamanda bir
Object olduğundan eleman eklerken 'cast' sorunu çıkmaz. Ancak alırken String yerine object
aldığımızdan ve her Object bir String olmayabileceğinden cast işlemi yapılmalıdır.
Bir vectorden eleman silmek için 'removeElement' methodu bulunmaktadır. Eleman sayısını
almak için size() diye bir method vardır. Bütün elemanlara erişim için bir döngü kurulabilir. Bir
vektörün bütün elemanlarını ekrana basmak için
for(int i=0;i<v.size();i++){
String item=(String) v.elementAt(i);
System.out.println(item);
}
şeklinde bir kod yazılabilir.
Enumeration
Bir vector'deki bütün elemanlara erişmenin farklı yöntemi daha vardır : Enumeration
kullanmak. Örneğin :
Enumeration e=v.elements();
while(e.hasMoreElements()){
String item=(String) e.nextElement();
System.out.println(item);
}
şeklindeki kod, bütün elemanlara erişim yapar. Enumeration bütün elemanlara erişmek için
kullanılan bir interface'dir. hasMoreElements() methodu elemanların bütün bitmediğini belirtir.
nextElement() method'u da sıradaki elemanı verir. Bu method çağrılınca sıra bir sonraki elemana
geçer. Başka bir deyişle, bu methd iki işi birden yapar.

Sıradaki elemanı ver

Sırayı bir sonraki geçir
bu sayede method her çağrıldığıda farklı bir değer, yani sıradaki değeri verir.
VectorTest.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.util.*;
2 public class VectorTest {
3
public static void main(String[] args){
4
Vector v=new Vector();
5
v.addElement("Bir");
6
v.addElement("İki");
7
v.addElement("Üç");
8
v.addElement("Dört");
9
v.removeElement("Bir");
10
for(int i=0;i<v.size();i++){
11
String item=(String) v.elementAt(i);
12
System.out.println(item);
13
}
14
Enumeration e=v.elements();
15
while(e.hasMoreElements()){
16
String item=(String) e.nextElement();
17
System.out.println(item);
18
}
19
}
20 }
Hashtable
Bir grup değere 'index'le değil 'key'le erişmek için Hashtable class'ı kullanılır. İndex int tipinde
bir sayıysa key herhangi bir object, örneğin bir string olabilir. Bu class her değeri bir key'le
birlikte saklar ve o key verildiğinde o key karşılık gelen değeri verir. Hashable yaratmak için
Hashtable ht=new Hashtable();
şeklinde bir ifade yeterli. Bir eleman eklemek için
ht.put("mykey","myvalue");
yazılabilir. Bir değeri almak için de
String val=(String) ht.get("x");
şeklinde bir ifade yeterli. Burada cast yapmak zorunlu, çünkü Hashtable'dan bir nesne Object
tipinde alınıyor. Onu herhangi bir class tipinde kullanmak için cast etmek lazım.
Hashtable'daki bütün değerleri almak için de Enumeration interface kullanılır. Hastable'lar
index'le erişim yapmadıkları için bütün eleman ları almanın başka bir yolu yok. Bir döngü
yapmak mümkün değildir. Enumeration'la erişimde elemanlar konulduğu sırada alınmayabilir.
HashtableTest.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.util.*;
2 public class HashtableTest {
3
public static void main(String[] args){
4
Hashtable ht=new Hashtable();
5
ht.put("x","A");
6
ht.put("y","B");
7
ht.put("z","C");
8
String val=(String) ht.get("x");
9
System.out.println("val : "+val);
10
Enumeration e=ht.elements();
11
while(e.hasMoreElements()){
12
String item=(String) e.nextElement();
13
System.out.println(item);
14
}
15
}
16 }
Dosya Listesi

VectorTest.java

HashtableTest.java
Package'ler ve Derleme Birimleri
Package
Birbiriyle işlev veya kullanım açısından ilişkili class'lar 'package' adı verilen bir birim altında
birleştirilir. Bir class'ın ait olduğu package'i belirtmek için 'package' keyword'ü kullanılır.
package mypackage;
public class MyClass
// ..
}
Bir class'ın diğer bir class'la aynı package'te olması, ona bazı avantajlar sağlar.
Aslında bütün class'lar bir package'e ait olmak zorundadır. Hiç bir isim verilmediğinde o class
isimsiz default package'de kabul edilir. Package'i belirtilmemiş bütün classlar aynı package'in
class'ları sayılır. Bazı durumlarda sadece örnek olsun diye yapılıp hatalı (derlenemez durumda)
bırakılan class, yine package'siz olan başka bir class'ın derlenmesini engelleyebilir.
Import
Bir class'ın kendisiyle aynı package'de olmayan class'ı kullanabilmesi için, class tanımından önce
import etmesi gerekir. Bu sadece kullanılacan class'ların tam olarak hangi pakette olduğunu
söylemek anlamına gelir. Bunun için 'import' keyword'ü kullanılır.
package myanotherpackage;
import mypackage.MyClass;
public class MyAnotherClass
// ..
}
Burada sadece kullanılacağı belirtilmektedir. Yoksa, import edilen class'ın import eden class'ın
üzerine 'include' edilmesi (eklenmesi) sözkonusu değildir.
'java.lang' package'indeki class'ları kullanmak için import ifadesine gerek yoktur. Bu package
olmadan hiç bir Java programı yapılamayacağı için, default olarak import edilmiş sayılır.
'*' Operatörüyle Import
Bir package'deki bütün class'ları import etmek için '*' operatörü kullanılabilir.
package myanotherpackage;
import mypackage.*;
public class MyAnotherClass
// ..
}
Bu işlem, altalta çok sayıda import ifadesi yazmaktan daha kolaydır.
'*' operatörü kullanılıdığında bir çok class'ın gereksiz yere import edildiği gibi bir izlenim
doğmakla birlikte, import işlemi aslında bir belirtmeden öteye gerçek bir 'içine alma' işlemi
anlamına gelmediği için önemli bir performans kaybına yol açmaz. Sadece bazı programcılar
okunurluğu arttırmak için böyle bir yola gitmektedirler.
Fully-Qualified Name (Tam Nitelendirilmiş İsim)
Aslında her class package ismiyle birlikte adlandırılır. Örneğin, 'mypackage' isimli bir
package'de 'MyClass' isimli bir class'ın tam nitelendirilmiş ismi 'mypackge.MyClass' dır. Import
ifadesi, sadece programcıyı her class ismini böyle uzun yazmaktan kurtarmaktadır. 'java.awt'
package'inde olan Button adlı class'ın bir instance'ını 'import java.awt.*' diyerek kullanırsak
Button b=new Button();
şeklinde yaratabiliriz. Hiç 'import' kullanmayarak aynı ifadeyi
java.awt.Button b=new java.awt.Button();
şeklinde de yazabiliriz. Bu şekilde paket ismiyle birlikte verilen class isimlerine fully-qualified
name denir.
Alt Package'ler
Bazı durumlarda çok fazla class içermemesi için bir package alt birimlere bölünebilir. Örneğin,
görsel bileşenler içeren 'java.awt' package'ın image'larla ilşkili olan 'java.awt.image' şeklinde bir
alt package'i bulunmaktadır. Aslında alt package'in teknik anlamda üst package'in 'içinde' olması
sözkonusu değildir. Alt package isimlendirmesi iki 'ayrı' package'i sadece anlamca
ilişkilendirmektedir.
Bir class'ta üst package'i import etmek, otomatikman alt package'lerin de import edileceği
anlamına gelmez. Örneğin, 'java.awt.*' ifadesi 'java.awt.event.*' ifadesini içermez. Bu alt
package'den herhangi bir class kullanılacaksa ayrıca import edilmesi gerekir.
Standart Package'ler
Java'nın kendi API'ı (Application Programming Interface - Uygulama Programlama Arayüzü'ü)
bir çok class'dan oluştuğu için bir çok package altında gruplandırılmıştır. Bunların çoğu 'java.' ve
'javax.' la başlar. 'javax' öneki daha çok, sonradan extension (ekleme) package'ler için kullanılır.
Önceden 'extension' olan package'ler daha sonra standart API'a dahil olabilmektedir.
Java'nın standart package'leri benzer ve ilişkili class'lardan oluşur. Her package'de bulunan
class'ların ezberlenmesine gerek yoktur. Sadece her package'de ne tür class'ların bulunduğu
öğrenilmesi yeterlidir. Örneğin, arayüzle ilgili class'lar 'java.awt'dedir. Görsel bir bileşen olarak
Button bu package'tedir. Yine görsel bir bileşen olan text alanı'nın (TextArea'nın) da bu
package'de olması gayet doğaldır.
Naming Convention (İsimlendirme Geleneği)
Package isimlerinin rastgele verilmesi, bir sistemde farklı kurumlara ait package'leri bulunması
durumunda 'name collision' (isim çarpışması) adı verilen bir sorun yaratabilmektedir. Aynı
package ismini başka bir kurum da kullandıysa ne olacak? Örneğin siz package'in adını
'myapplets' koydunuz. Sistemde aynı isimde başka bir kuruma ait bir package daha var
tesadüfen. Java önce hanginizinkini bulursa onu yükler. Sizinki önce bulunuyorsa onların
package'i doğru çalışmaz, onlarınki önceyse sizinki.
Bu sorunlarla karşılaşmamak için package isimlerinde standart bir yöntem uygulanır. Bir kurum,
sahip olduğu İnternet domain ismini tersten yazarak package isimlerinin önüne ekler. Örneğin
'godoro.com'a sahip olan kurum veya kişiler, chat appletlerini 'com.godoro.chat' diye bir
package'e koyabilirler. ChatApplet isimli biri class için fully-qualified class name
'com.godoro.chat.ChatApplet' şeklinde olur. Java'yı ortaya çıkaran 'Sun' firması da kendi
package'lerini 'com.sun.' şeklinde başlatmaktadır. ÖZel kuruluşlar com., ticari olmaytan
kurumlar da org. ile başlarlar.
Aynı Package'teki Class'lar
Aynı package'deki class'lar birbirlerinin private olmayan property ve methodlarına, onlar public
olmasala bile ulaşırlar. Ayrıca, aynı package'deki class'ların birbirlerini 'import' etmeleri
gerekmez.
Derleme Birimi
Class'lar '.java' uzantılı dosyalarda bulunabilirler. Bu dosya aslında bir compilation unit
(derleme birimi)dir (). Bir dosyada birden fazla class alt alta tanımlanabilir. Ancak en fazla bir
tanesi 'public' olabilir. Ve dosyanın (derleme biriminin) adı bu public class'ın adıyla aynı
olmalıdır. Bu class derleme biriminin asıl class'ıdır ve adı değiştirildiğinde dosyanın da adı
değiştirilmelidir. Tek dosyada bulunan class'lar derlendiğinde her biri için ayrı .class üretilir.
Yani derlendikten sonra class'lar birbirinden ayrılırlar. Bir derleme biriminde sadece bir tane
class bulundurmak, zorunlu olmasa da bir gelenek halini almıştır.
Encapsulation
Encapsulation Kavramı
Her class çeşitli üyelerden (property ve method'lardan) oluşur. Hemen hemen bütün class'lar
başka bir class tarafından kullanılmak amacıyla üretildiğinden, bazı üyeler sadece dışarıdan
kullanılmak üzere hazırlanmıştır. Buna karşı bazı property ve method'lar, diğerlerine yardımcı
olmak, sadece onlar tarafından class'ın iç işlerinde kullanılmak için yazılırlar. Belli bir class'ı
kullanan class'ın bunları görmesi veya bilmesi gerekmez. Hatta bazı durumlarda property ve
method'ların sadece ufak bir kısmı dışarısı tarafından kullanılır. Bir insanın belli bir class'a
baktığında üyelerden hangisi kendisinin işine yarar, hangisi sadece başka methodlarda
kullanılmak için yapılmıştır ve class'a özel'dir anlaması çok zor olabilir. Bazı durumlarda da
güvenlik ve sağlamlık sağlamak amacıyla bir class'ı kullanan class'ın bazı property'leri
değiştirmesi ve bazı methodlara erişmesi engellenmek istenebilir. Bazı property ve methodların
ait olduğu class'ın dışında erişimini sınırlama özelliğine 'encapsulation' (kapsülleme) denir.
Encapsulation sağlamak için private, public ve proteced sözcükleri kullanılır. Bunlara access
modifier (erişim değiştirici) denir. Hiç birini kullanmak da bu bağlamda belli bir tercih anlamına
gelir.
Default Access
Hiç bir access modifier kullanılazsa, yani bir property ve methodun başında private, protected ve
public keyword'lerinden hiç biri kullanılmazsa bu üye 'package private' olur. Yani ona sadece
aynı package'deki diğer class'lar erişebilir, diğer package'lerdekiler erişemez.
Public Access
Sistemdeki bütün class'ların erişebilmesini sağlamak için 'public' erişim değiştiricisi kullanılır.
Herkesin erişmesinde sakınca bulunmayan üyeleri için kullanılır. Genellikle bu değiştirici
özellikle başkaları erişsin diye yazılan property ve method'lar için kullanılır. Bir nesnede ne
kadar az public değişken varsa dışarıya o kadar sade görünür ve o kadar kolay kullanılır. O
nesneyi kullananlar gereksiz bir çok üye arasında dolaşmak zorunda kalmazlar.
Private Access
Bir property veya method'un sadece tanımlandığı class'dan erişilebilmesini, başka bir deyişle, o
class dışındaki bütün class'lardan (aynı package'de olsalar bile) erişiminin yasaklanmasını
sağlamak için 'private' keyword'ü kullanılır.
Bir değişkenin dışardan görülebilmesini ancak değiştirilemesini veya değiştirme işleminin
class'ın kontrolünde yapılmasını sağlamak için standart bir yöntem izlenir. Bir property'yi readonly (salt okunur) yapmak için, o property private yapılır. Ona erişmek için bir tane public
method yazılır. Bu şekilde dışarından property'nin value'si dolaylı olarak öğrenilmiş olur.
Göster Gizle Kopar Satır Gizle Satır Göster
1 public class MyDiscreetClass{
2
private int value=3;
3
public int getValue(){
4
return value;
5
}
6 }
Bu class'tan yaratılmış bir nesne'yi kullanan örnek yapalım.
MyDiscreteUserClass.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class MyDiscreteUserClass{
2
public static void main(){
3
MyDiscreetClass d=new MyDiscreetClass();
4
int v=d.getValue();
5
System.out.println("Value : "+v);
6
}
7 }
Buradaki value private olduğu için
int v=d.value;
yazarsak derleyici hata verir. Property orada olduğu halde artık erişilmez hale gelmiştir. Ama
değeri öğrenmek için getValue() methodu kullanılabildiği için bir programın işleyişini bozmaz.
Biz bu değeri değiştirmek istersek :
d.value=5;
derleyici yine hata verecektir. Bu şekilde class kendi property'sini korumuş oluyor.
Bir değişkenin hem okunması hem de değiştirilmesi istenip sadece bunun kontrollü bir şekilde
yapılmasını istersek yine property'yi private tutarız ve hem erişebilmek için hem de
değiştirebilmek için iki ayrı method yazarız. Bir değerin eksi olmamasını sağlayan bir class
yapalım :
MyControlledClass.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class MyControlledClass{
2
private int value=3;
3
public int getValue(){
4
return value;
5
}
6
public void setValue(int v){
7
if(v>0){
8
value=v;
9
}else{
10
value=-v;
11
}
12
}
13 }
Bu değeri değiştirip sonrsa yeni değeri alan bir program yazalım.
MyControlledUserClass.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class MyControlledUserClass{
2
public static void main(){
3
MyControlledClass d=new MyControlledClass();
4
d.setValue(-7);
5
int v=d.getValue();
6
System.out.println("Value : "+v);
7
}
8 }
Bu program, kendisinin değiştirmeye (kullanılan class açısından bakarsak, 'bozmaya') çalıştığı
değerin hala sağlam olduğunu ortaya koymaktadır.
Protected Access
Bazı durumlarda bir property veya method'un dışarıya kapalı olmasını ancak o class'ı extend
edenlere açık olması istenebilir. Bu durumda 'protected' erişim değiştiricisi kullanılır. Bir class
diğerini extend ederse, onun bütün public property'lerin erişebilir hale gelir. Zaten bunlara her
class'ın erişebilmektedir. Hiç bir private property extend eden class'a geçmez. Bunlar diğer bütün
class'lara da kapalıdır. Ancak protected property ve methodlar dışarıya kapalı oldukları halde,
extend edilen class bunlara erişim hakkına sahiptir. Bu keyword, belli bir property veya
method'un sadece onu extend eden class'ları ilgilendirmesi durumunda kullanılır.
Erişim değiştirici olarak protected verilmiş property veya method'lara o class'la aynı package
içerisindeki bütün class'lar tarafından da erişilebilir.
Erişim Düzeyleri Sıralaması
Encapsulation düzeyleri için
public > protected > 'default' > private
şeklinde bir sıralama yapılır. Büyük olan düzey küçük olanların haklarını da kapsar. Bir
property'nin public olup private özelliği içermemesi, yani tanımlandığı class'tan erişilemez ama
onun dışındaki bütün class'lardan erişilmesi gibi bir durum söz konusu olamaz.
Dosya Listesi

MyDiscreetClass.java

MyDiscreteUserClass.java

MyControlledClass.java

MyControlledUserClass.java
Inheritance (Kalıtım)
Inheritance Kavramı
Bir class'ın başka bir class'daki property ve method'lara sahip olmasına inheritance denir.. Belli
bir class, daha genel bir kavramı ifade eden class'ın üyelerine sahip olarak, onları tekrar
tanımlamak zorunda kalmaz. Bir class'ın diğerindeki özellikleri miras olarak alması için
kullanılan keyword 'extends' dir. Anlam olarak "Bu class şu class'ı 'genişletir' yani ondaki
property ve methodları alır ve yenilerini ekler" demektir.
Inheritance, bazı durumlarda başka birinin yazdığı class'a bazı eklemeler yaparak belli bir işlem
için kullanılır hale getirmek için kullanılabilir. Böylelikle sadece o class'ta olmayan property ve
methodları eklemek suretiyle çok kısa sürede gelişmiş bir class sahibi olabilir. Bazen de ortak bir
çok özellik içeren iki nesnede de aynen bulunan property ve methodları tanımlamaktan
kurtulmak için kullanılabilir.
'Extends' Kullanımı
Diyelim ki bize bir küp ve küre'yle hacim, yüzey alanı, kütle ve ağırlık gibi hesaplamalar
yapmamız gerekiyor. Bir çok özellik bu iki nesnede ortaktır. İkisinde de bir özkütle vardır.
Hacim hesaplama teknikleri değişebilir ama kütle hesap teknikleri değişmez. Her iki cisim için
de kütle, özkütle ile hacmin çarpımıdır. Bu iki cisim için SimpleSphere ve SimpleCube gibi iki
class yapacaksak, ortak özellikleri içeren SimpleBody diye bir class yapmak akıllıca olur.
Şimdilik sadece SimpleSphere'e ihtiyacımız varsa dahi, sonradan SimpleCube veya başka bir
cismin gerekebileceğini düşünerek bir base class yapmak da faydalı olabilir.
Göster Gizle Kopar Satır Gizle Satır Göster
1 public class SimpleBody{
2
private double density=1.0;
3
public SimpleBody(){
4
}
5
public SimpleBody(double d){
6
setDensity(d);
7
}
8
public void setDensity(double d){
9
density=d;
10
}
11
public double getDensity(){
12
return density;
13
}
14 }
Görüldüğü gibi, cismin yoğunluğunu belirten bir property ve bunula ilgili iki method var. Bu
class'ı 'extend' eden SimpleSphere adlı bir class yapalım.
SimpleSphere.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class SimpleSphere extends Body{
2
public double radius=1.0;
3
public SimpleSphere(double d,double r){
4
super(d);
5
radius=r;
6
}
7
public double getVolume(){
8
return (3.14 * radius * radius * radius )/3;
9
}
10 }
Yazdığımız SimpleSphere class'ın radius property'si dışında, density property'si de vardır. Şöyle
bir kod parçası geçerlidir :
SimpleSphere s=new SimpleSphere();
s.setRadius(3.6);
s.setDensity(1.2);
Extend eden class'a subclass, extend edilen class'a da super class (veya base class) denir.
Super Class'ın Constructor'unun Kullanımı
Bir class'ı extend eden class'ın constructor'u extend ettiği class'ın constructor'unu 'super()'
şeklinde çağırabilir. Bu şekilde super class'a veri aktarılmış olur. SimpleSphere class'ına bir
constructor ekleyelim :
public SimpleSphere(double d,double r){
super(d);
setRadius(r);
}
Bu şekildeki constructor'u kullanmak istersek
SimpleSphere sphere=new SimpleSphere(3.6,1.2);
biçiminde bir kod yazmak yeterli olacaktır.
Bir constructor'ın diğerini çağırması durumunda super ifadesi kesinlikle ilk satırda
belirtilmelidir. Herhangi bir kod parçası yazıldıktan sonra super class'ın bir constructor'u
çağrılamaz.
Super class'ın constructor'u açık olarak çağrılmadıkça, parametresiz olan super() constructor'un
çağrıldığı varsayılır. Super constructor'un böyle bir constructor'u yoksa mutlaka parametreli bir
constructor çağrılmalıdır. Aksi takdirde derleyici hata verir.
Super Class'larda Protected Property'ler
Base class'da 'private' olan property'lere subclass'tan erişilemez. Erişilmesi için 'public' yapılması
durumunda da ilgili üye herkese açık hale gelecektir. Sadece extend eden class'ın erişimini
sağlamak için 'protected' erişim değiştiricisi kullanılır. SimpleBody class'ında 'density'
property'si protected olmalıdır.
Overriding (Ezme)
Bir subclass super class'ının bir methodunun davranışını yeniden yazabilir, yani super'dekini
ezebilir. Buna overriding denir. Bunun için aynı üst class'ın method'unun signature'uyla aynı
olmalıdır. Bu işlem bazen methodun tamamen değiştirme, bazen de sadece bir ekleme yapma
şeklinde yapılır. SimpleSphere class'ında, SimpleBody class'ında density property'sini belirleyen
setDensity() method'u, negatif değer kontrolü yapacak şekilde değiştirmek için
public void setDensity(double d){
if(d>=0){
density=d;
}else{
density=0.0;
}
}
biçimde bir kod yeterlidir. SimpleSphere class'ında setDensity() methodu çağrıldığında bu yeni
method geçerli olacaktır. Elbette bu değişiklik SimpleBody class'ı ve bu class'ı extend eder diğer
class'ları bağlamaz. Onlar hala üsteki methodu çağırırlar.
Override eden method, override edilen methodu çağırabilir. Ancak ikisinin de adı da
parametreleri de aynı olduğu için super anahtar sözcüğü kullanılır.
public void setDensity(double d){
if(d>=0){
super.setDensity(d);
}else{
super.setDensity(0.0);
}
}
Super class'da olan bir method'un ismiyle aynı farklı parametreler alan bir method yazlıabilir.
Ama bu durumda overriding değil overloading yapılmış olur. Yani var olan bir method'u
değiştirmek yerine yeni bir method eklenmiş olur. İlk method çağrıldığında yine eskisi gibi
çalışır.
Multiple Inheritance (Çoklu Kalıtım)
Java'da 'multiple inheritance', yani bir class'ın iki veya daha çok class'ı extend etmesi, onların
property ve method'larını miras alması mümkün değildir. C++ gibi diğer nesneye yönelik
dillerde bu mümkündür ama Java'da kafa karışıklığına, çalışma zorluğuna, birbirine girmiş
yapılar yaratmaya neden olduğu için izin verilmemiştir. Java'daki single inheritance (tekli
inheritance)da hangi class'ın hangisini extend ettiği bir ağaç yapısı şeklinde net bir şeklide
görülmektedir. Aslında bu yazılım tasarımı açısından da gereklidir. Örneğin bir hayvan hem
memeli hem de kuş olmaz. Hem balık hem memeli olmaz. Hatta yarasa uçsa bile, balina yüzse
bile onlar birer memelidir. Yarasanın kuşlar gibi uçtuğunu görüp onu hem memeli hem kuş
saymak ne kadar yanlışsa, bir class'ı iki ayrı class'ın özelliklerine birden sahip olması gerektiğini
düşünmek o derece yanlıştır. Eğer tasarımınız bunu zorunlu kılıyorsa ya yanlış tasarım
yapmışsınızdır ya yanlış çözümleme yapmışsınızdır. Çoklu kalıtımın gerekli gibi göründüğü
durumlarda başka çözüm yolları devreye girer. Bunları programcı ve sistem tasarımcıları Java'da
bilgi ve deneyimlerini arttırdıkça öğrenebilirler. Örneğin iki class'ı extend etmek yerine birini
extend etmek, diğerini bir property olarak tanımlamak ve kullanmak mantıklı bir çözüm olabilir..
Dosya Listesi

SimpleBody.java

SimpleSphere.java
Interface'ler ve Abstract Class'lar
Interface Kavramı
Java'da interface, bir class'ta olması gereken method ve property'leri tanımlayan yapıdır. Kendisi
normal bir class değildir, sadece neyin yapılacağını göstermekte, ancak nasıl yapılacağını
göstermemektedir. Örnek olarak, bir madde'de ne gibi işlevler ve özellikler olması gerektiğini
belirten bir interface yazalım.
Göster Gizle Kopar Satır Gizle Satır Göster
1 public interface Matter{
2
public double getVolume();
3
public double getMass();
4 }
Bu ifade, 'bir maddenin yoğunluğu, hacmi ve kütlesi olur' demenin Java'daki yoludur. Ancak
görüldüğü gibi maddenin yoğunluğu nasıl hesaplanır, kütlesi nasıl verilir, hiç bir şekilde
belirtmemektedir. Sadece ne olması gerktiğini söylemektedir.
Interface'in Implementation'u
Bir class'ın interface'deki bütün method'ları içerdiğini, gerçekleştirdiğini belirtmesine
implementation denir ve 'implements' keyword'üyle kullanılır.
CubeMatter.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class CubeMatter implements Matter{
2
public double density=1.0;
3
public double edge=1.0;
4
public double getDensity(){
5
return density;
6
}
7
public double getVolume(){
8
return edge*edge*edge;
9
}
10
public double getMass(){
11
return density*edge*edge*edge;
12
}
13 }
Burada "Küp diye bir nesnemiz var ve o bir maddedir, yani bir maddede olabilecek bütün
nitelikler onda da bulunur." demiş olduk ve bunların nasıl hesaplandığını gösterdik. Aynı
interface'i implement eden başka bir class'da yapılabilir.
SphereMatter.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class SphereMatter implements Matter{
2
public double density=1.0;
3
public double radius=1.0;
4
public double getDensity(){
5
return density;
6
}
7
public double getVolume(){
8
return (3.14 * radius * radius * radius )/3;
9
}
10
public double getMass(){
11
return density*(3.14 * radius * radius * radius )/3;
12
}
13 }
Görüldüğü gib bu class'da aynı interface implement ediyor. Ancak hacim ve kütle hesaplaması
çok değişik.
Absract Class'lar
Bazı methodlarını implement etmiş, bazılarının imlementation'unun kendisini extend eden class'a
bırakmış olan class'a abstract class denir. Bu tip class'lar en çok, iki class'ın ortak
methodlarından bazılarının implementation'u da aynı olması durumunda kullanılır. Örneğin bir
küp için de kütle, hacim ve yoğunluğun çarpımına eşittir, bir küre için de. Ancak yaptığımız iki
nesnede de bu ortak özelliği kullanamıyor. Her birisi kütle hesaplamasını kendisi yapılıyor.
Matter interface'ini implement eden ne kadar class varsa bu işlem o kadar tekrarlanacak
demektir. Bu 'ortak' işlemi bir kere yapıp, hep onun kullanılmasını sağlamak mümkündür.
Ancak çözülmesi gereken bir sorun var : Her class'ın kütlesi aynı şekilde hesaplanıyor bunu
hesaplamak için gerekli hacim değerini bilmiyoruz ve her class kendisine göre değişik bir şeklide
hesaplıyor. Bu sorun abstract method kullanarak çözülebilir.
Body.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 abstract public class Body{
2
public double density=1.0;
3
public Body(double d){
4
density=d;
5
}
6
public double getDensity(){
7
return density;
8
}
9
public double getMass(){
10
return density*getVolume();
11
}
12
abstract public double getVolume();
13 }
Burada abstract bir Body class'ı yarattık. Bu class, hem Cube'ün hem de Sphere'in ortak
özelliklerini içermektedir. Zaten density property'si ikisinde de ortaktır. Bu şekilde inherintace
yoluyla Cube ve Sphere'a geçebilir. Burada getVolume() method'u abstract bırakılmıştır. Yani
implement edilmemiştir. Çünkü volume hesaplamak için her nesne farklı bir method
kullanmaktadır. Ancak getMass() implement edilmiştir. Çünkü kütle yoğunlukla hacmin
çarpımıdır. Burada object-oriented porgramlama dışındaki bir teknikle asla yapılamayacak bir
işlem bulunmaktadır. Bir method (getMass()) henüz yazılmamış bir mehodu (getVolume()'u)
kullanarak bir işlem yapabilmektedir. Bu şekilde her cisim için ayrı ayrı hesap yapmaktan
kurtulmuş olduk. Şimdi küp ve küre için yeni class'lar yapalım :
CubeBody.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class CubeBody extends Body{
2
public double edge=1.0;
3
public CubeBody(double d,double e){
4
super(d);
5
edge=e;
6
}
7
public double getVolume(){
8
return edge*edge*edge;
9
}
10 }
Görüldüğü gibi bu class kütle hesabını yapan getMass() diye bir method'u yazmak zorunda
kalmadı. Çünkü ona miras yoluyla sahip olmuştur. Aşağıdaki gibi kod yazılabilir :
CubeBody cube=new CubeBody(2.5,10.2);
double mass=cube.getMass();
System.out.println("Mass : "+mass);
Aynı şekilde yeni bir küre class'ı yazalım.
SphereBody.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class SphereBody extends Body{
2
public double radius=1.0;
3
public SphereBody(double d,double r){
4
super(d);
5
radius=r;
6
}
7
public double getVolume(){
8
return (3.14 * radius * radius * radius )/3;
9
}
10 }
Tıpkı küp gibi küre de artık kütle hesabını, hiç bir ek kodlama yapmadan yapabilmektedir.
Hem Extend Hem Implement Etmek
Bir class sadece bir class'ı extend edebilir. Ancak aynı anda bir class'ı extend edip bir veya daha
fazla interface'i implement edebilir. Çünkü 'extends' keywordünün aksine, 'implements' demek
yoluyla bir class'ın aldığı hiç bir şey yoktur. Sadece bazı method'ları implement etmeyi taahüt
etmektedir. Bir Cube class'ı hem Body classını extend edebilir hem de Matter inetrface'ni
implement edebilir.
public class Cube extends Body implements Matter{
// ...
}
Base class'ın bir interface'i imlement etmesi durumda subclass'da etmiş sayılır. Yani
public class Body implements Matter{
// ...
}
dersek
public class Cube extends Body{
// ...
}
dememiz yeterlidir. Cube class'ı Matter'i implement etmiş sayılır. Yani implementation'u da
miras yoluyla almış demektir.
Interface'in Kullanım Özellikleri
Interface'ler bütün methodları absract olan bir absract class gibi düşünülebilirler. Ancak
class'lardan ayrılan başka özellikleri vardır. Ayrıca söylensin veya söylenmesin bütün method ve
property'ler public sayılır ve başların proteced veya private gibi anahtar sözcükler alamazlar.
Interface'lerde bütün propertyler public, final ve static'tir. O yüzden interface'lerde tanımlanan
property'ler bir veya daha fazla class'da kullanılan sabitler için kullanılır.
MathConstants.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public interface MathConstants{
2
double PI=3.14;
3 }
Circle.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class Circle implements MathConstants{
2
private double radius=1.0;
3
public getCircumference(){
4
return 2*PI*radius;
5
}
6 }
görüldüğü Circle classında tanımlanmadığı halde PI değişkeni, sadece MathConstants
interface'ini implement ettiği için erişilebilir durumdadır. Bu interface'i implement eden Cylinder
adlı bir class'da aynı şekilde PI'a erişebilir. Bu anlamda PI bir sabittir. Ama PI property'si sadece
implement edilen class'lar tarafından görülmekte olduğundan global değildir. Zaten Java'da
global değişken ve sabit yoktur. Onlara ihtiyaç duyulan yerlerde interface kullanılır. Ancak yine
de değişken (dah doğrusu sabit) bir yere (interface) ait olduğundan global olmasından doğacak
sakıncalardan kurtulunabilir. Örneğin Math.PI ve GreekLetters.PI yazılabilir, ikisi farklı değerler
taşıyabilir.
Dosya Listesi

Matter.java

CubeMatter.java

SphereMatter.java

Body.java

CubeBody.java

SphereBody.java

MathConstants.java

Circle.java
Polymorphism (Çok Biçimlilik)
Polymorphism (Çok Biçimlilik)
Nesneye yönelik programlamada polymorphism , nesnelerin içeride farklı çalışmalarına rağmen
dışarıdan aynı biçimde görünmelerine denir. Bu şekilde, bir grup nesneyi kullanan class'lar
implementation'la ilgili detayları bilmek zorunda kalmazlar, içerideki değişikliklerden
etkilenmeden çalışmaya devam ederler. Aynı class'ı extend eden veya aynı interface implement
eden class'lar standart bir şekilde erişilebilme özelliklerine sahip olurlar.
Polymorphism Olmadan Kodlama
Bir miktar kübün toplam kütlesini hesaplamak istediğimizi düşünelim. Küp class'ının ana hatları
şöyle olsun :
public class Cube{
// ...
public double getMass(){
// ...
}
}
Bu class'tan yaratılmış instance'ların kütlelerini toplayan bir method ve program yazalım.
Göster Gizle Kopar Satır Gizle Satır Göster
1 public class CubesMassCalculator{
2
public static double calculateTotalMass(Cube[] cubes){
3
double total=0.0;
4
for(int i=0;i<cubes.length;i++){
5
total+=cubes[i].getMass();
6
}
7
return total;
8
}
9
public static void main(String[] args){
10
Cube[] cubes=new Cube[3];
11
cubes[0]=new Cube(2.2,10.5);
12
cubes[1]=new Cube(3.1,6.1);
13
cubes[2]=new Cube(5.6,1.2);
14
cubes[3]=new Cube(9.3,6.1);
15
cubes[4]=new Cube(4.0,3.7);
16
double total=calculateTotalMass(cubes);
17
System.out.println("Total Mass : "+total);
18
}
19 }
Aynı programı küreler içinde yazabiliriz. Sphere class'ımız da aynı biçimde tanımlanmış olsun :
public class Sphere{
// ...
public double getMass(){
// ...
}
}
Ancak calculateTotalMass() method'unu şu biçimin de tanımlamalıyız :
public static double calculateTotalMass(Sphere[] spheres){
// ..
}
Peki ya bir nesne dizimiz değişik cisimlerden oluşuyorsa? Örneğin üç tane kübümüz iki tane
küremiz varsa ne olacak? Onun için şöyle bir method daha yazmalıyız.
public static double calculateTotalMass(Cube[] cubes,Sphere[]
spheres){
// ..
}
Ya dikdörgenler prizması ve piramit gibi cisimlerimiz de varsa ne yapacağız? Her biri için ayrı
toplamlar alan bir sürü method yazmaktan başka çaremiz kalmayacak. İşte polymorphism burada
devreye giriyor.
Ploymophism'den Yararlanma
Eğer iki class'da ortak bir method varsa, bu ikisinin de temel alacağı Body şeklinde bir class
yapmak gereklidir :
class Body{
// ...
public double getMass(){
// ...
}
}
class Cube extends Body{
// ...
}
class Sphere extends Body{
// ...
}
Çeşitli tipte cisimlerden olişan bir dizinin toplam kütlesini hesaplayan bir class yapalım.
BodiesMassCalculator.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 public class BodiesMassCalculator{
2
public static double calculateTotalMass(Body[] bodies){
3
double total=0.0;
4
for(int i=0;i&bodies.length;i++){
5
total+=bodies[i].getMass();
6
}
7
return total;<noframes></noframes>
8
}
9
public static void main(String[] args){
10
Body[] bodies=new Body[3];
11
bodies[0]=new Cube(2.2,10.5);
12
bodies[1]=new Sphere(3.1,6.1);
13
bodies[2]=new Cube(5.6,1.2);
14
bodies[3]=new Cube(9.3,6.1);
15
bodies[4]=new Sphere(4.0,3.7);
16
double total=calculateTotalMass(bodies);
17
System.out.println("Total Mass : "+total);
18
}
19 }
Görüldüğü gibi tek method çeşitli cisimlerin kütlelerini toplayabiliyor. Her cismin farklı bir
hacim ve kütle hesaplama şekli olduğu halde. Bunun için tek gerekli şart Cube ve Sphere
class'larının Body class'ını extend etmeleri ve Body class'ında getMass() şeklinde bir method
olmasıdır. Pyramid diye Body'yi extend eden bir class yapıp, dizinin dördüncü elamanı olarak
verirseniz calculateTotalMass() methodu yine toplam kütleyi doğru olarak hesaplayacaktır.
Çünkü o zaten Sphere'ı da Cube'ü de tanımamaktadır. Sadece Body class'ını tanımaktadır ki, bir
cismin kütlesi olması, onun kütlesini toplama dahil etmesi için yeterlidir.
Interface ve Abstract Class'larla Polymorphism
Polymorphism özelliğini kullanmak için, class'ların belli bir concrete base class'a sahip olmaları
gerekmez. Base class'ları abstract olabilir. Hatta ortak kullanılan method'un kendisi bizzat
abstract olabilir. Bu biçimde interface'lerin de kullanılması mümkündür. Aynı interface'i
implement eden her class aynı type'da kabul edilir. Yukarıdaki örnekteki class'lar
abstract class Body{
// ...
abstract public double getMass();
}
class Cube extends Body{
// ...
public double getMass(){
// ...
}
}
class Sphere extends Body{
// ...
public double getMass(){
// ...
}
}
şeklinde de tanımlanmış olsalar aynı şekilde kullanılabilirdi. Body'nin bir class değil de bir
interface olarak tasarlanması durumunda da aynı şey geçerlidir.
interface class Body{
public double getMass();
}
class Cube implements Body{
// ...
public double getMass(){
// ...
}
}
class Sphere implements Body{
// ...
public double getMass(){
// ...
}
}
Dosya Listesi

CubesMassCalculator.java

BodiesMassCalculator.java
Stream'ler
Input ve Output Stream'leri
I/O (Input/Output) bilgisayarın hafızası kadar hızlı olmayan bir birimde belli bir verinin
okunması ve yazılması işlemidir. Örnek olarak bir disk üzerindeki dosyalar ele alınabilir. Disk
üzerindeki dosyalara erişim hafızadaki bilgilere erişim kadar kolay olmaz. Bir dosyadan okuma
veya dosyaya yazma yavaş yavaş (hatta bazen byte byte) yapılır. Ayrıca network bağlantıları da
aynı şekilde değerlendirilmelidir. Zira network üzerinden başka bir makineyle okuma/yazma
yapmak elbette yavaş yavaş gerçekleştirilir. Bazen okunacak veri hazır olmayabilir veya
yazılacak birim henüz yazılan datayı aynı hızda alacak durumda olmayabilir. Böyle durumlarda
Stream kavramı gündeme gelir. Okumak için InputStream ve yazmak için de OutputStream
kullanılır. Streamlar 'byte' konuşurlar. Bir dosya okumak için, FileInputStream ve bir dosyaya
yazmak için FileOutputStream kullanılır.
InputStream'den Okuma
Bir dosyadan byte byte okuma yapıp ekrana basan bir program yazalım.
Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.io.*;
2 public class InputStreamer{
3
public static void main(String[] args)
4
throws IOException
5
{
6
String filename="c:\\myfolder\\myfile.ext";
7
FileInputStream in=new FileInputStream(filename);
8
int c;
9
while ((c = in.read()) != -1){
10
System.out.print(c);
11
}
12
in.close();
13
}
14 }
InputStream'in read() methodu bir int okur ancak bu aslında bir byte'tır. Okuma yapmayı
bitirince -1 döndürür. Burdan artık stream'den gelecek veri olmadığını anlarız.
OutputStream'e Yazma.
Elimizdeki bir karakter dizisini bir dosyaya byte byte yazan bir program yapalım.
OutputStreamer.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.io.*;
2 public class OutputStreamer{
3
public static void main(String[] args)
4
throws IOException
5
{
6
String filename="c:\\myfolder\\myfile.ext";
7
8
9
10
11
12
13
14
}
15 }
FileOutputStream out=new FileOutputStream(filename);
char[] cs=new char[]{'J','a','v','a'};
for(int i=0;i<cs.length;i++){
char c=cs[i];
out.write(c);
}
out.close();
OutputStream'in write() methodu veriyi yazmak için kullanılır.
File olmayan Stream'ler
Bİr file'dan okumak için niye hem InputStream hem de FileInputStream'a ihtiyaç duyulduğu
sorusu akla gelebilir. InputStream genel bir kaynaktan byte byte okumaya yarar.
FileInputStream'se file'dan okuma yapmak içindir. Aslında FileInputStream, InputStream'i
extend eder, yani onun özel bir halidir. FileInputStream dışında network'ten okumak için veya
bir ses cihazından okumak için, veya herhangi bir cihazdan okumak için kullanılan
InputStream'ler bulunur. Aslında
FileInputStream in=new FileInputStream(filename);
yerine
InputStream in=new FileInputStream(filename);
da yazılabilirdi. Okuma kodu değişmezdi. Aynı şekilde AudioInputStream'la
InputStream in=new AudioInputStream(...);
gibi bir kod yazarak ses cihazından veya dosyasından okuma yapabiliriz. Kod yine değişmez.
Bütün bunlar OutputStream'ler için de söylenebilir. Java'nın I/O kütüphanesindeki karmaşıklığın
sebeplerinden biri stream'lerin genel bir çözüm içermesi, sadece dosyalarla sınırlandırılmamış
olmasıdır.
Rasgele Erişimli Dosyalar
Hem okuma hem yazma yapma ihtiyacı olduğunda kullanılabilecek bir RandomAccessFile
adında bir class vardır. Ancak normal şartlarda aynı anda hem okuma hem yazma gerekmez. Bu
class bunun gerekli olduğu nadir durumlarda kullanılır. Hem input stream'lerde olan read
methodları hem de output stream'lerde olan write method'ları vardır.
Buffer'lı Stream'ler
Input ve output stream'ler byte byte okuma yaptıkları için oldukça yavaş çalışırlar. Örneğin
diskten bir dosya okunacaksa, bir byte okumak için bile, manyetik ve mekanik esaslarla çalışan
disk cihazının okuma yapan kafası diskin ilgili bülümüne yerleştirilecek ve sonra okuma
yapılacaktır. Aynı yerden 1000 byte'lık bir veri okunsa da aynı işlem 1000 kere tekrarlanacaktır.
Disklerde bu durumu hafifletecek bazı özellikler mevcuttur ancak yazılımda da yapılması
gereken bazı işlemler vardır. Burada 'buffering' (tamponlama) devreye girer. Okuma yaparken
bir byte bile okunacaksa belli bir miktar (örneğin 1024 tane) byte hafızaya, yani bir buffer'
(tampon)'a okunur. İkinci byte okunurken diskten değil buffer'dan okunur. Buffer'daki sayı
tükenene kadar böyle gider. Ne zaman ki artık bufferda hiç bir şey kalmaz, gidilir tekrar diskten
okuma yapılır. Tabii yine bir byte değil buffer size'ı kadar.
Yazma yaparken de buffer kullanılabilir. Belli bir size'da buffer açılır ve stream'a yazılan
değerler diske değil bu buffer'a yazılır. Ne zaman ki buffer size'ı dolar, bütün buffer içeriği diske
tek seferde yazılır. Bu durumda disk açısından tek yazma işlemi gerçekleştiğinden sistem hızlı
çalışır. Ancak yazma yaparken bir sorun var : Ya buffer dolup diske yazma yapmadan programa
bir şey olur da işlem yarım kalırsa? Çünkü buffer'da diske yazılmayı bekleyen byte'lar diskteki
dosyada yok. Veri eksik kalmış oluyor. O yüzden, öncelikle buffer size'ı küçük tutlmalıdır.
Ayrıca 'flush' diye bir işlem vardır. Bu işlem 'buffer'daki veriyi hemen diske yaz, buffer dolmuş
olsun olmasın' demektir. Programcı belli bir anlam bütünlüğü olan veriyi yazdıktan sonra flush()
method'unu çağırarak buffer'ı diske yazar.
Programcı bu buffer işlemlerini kendi yapmak zorunda değildir. Bu işler çin
BufferedInputStream ve BufferedOutputStream vardır. Bunlar bir stream'le disk arasına
buffer koyarlar. Buffer'ın size'ı istenirse verilir verilmezse default bir değerde olur. Buffer
kullanmak basittir :
InputStream is=...;
BufferedInputStream bis=new BufferedInputStream(is);
Bundan sonraki kodda InputStream yerine BufferedInputStream kullanılır.
BufferedInputStream'de aslında bir InputStream'dir ve aynı methodlra sahiptir, o yüzden aynı
şekilde kullanılır. Aynı şeyler OutputStream ve BufferedOutputStream için geçerlidir.
'Madem buffer bu kadar faydalı niye her stream buffer'lı yapılmıyor. Böylelikle iki ayrı class'dan
da kurtulmuş olurduk' diye düşünülebilir. Ancak bazı stream'ler buffer'sız olmalıdır. Gelen
byte'ın anında okunması veya yazılması gerekebilir. Bu durumda buffer veriyi arada beklettiği
için zararlı olabilir.
Stream'leri Kapama
Stream'ler işlem yapmadan önce 'açılır' ve işlem yapıldıktan sonra 'kapanır'. Java'da açma işlemi
stram'lerin constructor'larında otomatik olarak yapılır. Ancak kapamak için 'close()'
kullanılmalıdır. Programdan çıkılırken stream'ler açık dahi olsa kapatılabilir. O yüzden sadece
main'den oluşan programlarda bu sorun anlaşılmaz. Ancak buffer'lı stream'lerde close() şarttır.
Çünkü buffer'da kalan verilerle ilgili işlemler, gerekiyorsa flush da close'da yapılır.
Dosya Listesi

InputStreamer.java

OutputStreamer.java
Reader ve Writer'lar
Text Stream'leri
Stream'ler (InputStream ve OutputStream) byte okumak için kullanılılır. Bunları (veya bunları
extend eden class'ları) kullanarak text, yani string okunabilir. Ancak bu durumda character
encoding'in bu class'lara verilmesi gerekir. Çünkü 'byte' tipindeki verileri 'char' tipine
dönüştürmek için encoding gereklidir. Çünkü, örneğin 'Ç' karakterinin byte olarak değeri bir
dilin encoding'inde, 123 diğerinde 127 olabilir. Bunun için Reader ve Writer classları
yapılmıştır. Reader'lar ve Writer'lar ortamın encoding'ini alıp byte'la char arasındaki dönüşünü
otomatik olarak yaparlar. Bunlar da aslında içlerinde birer stream'e sahiptirler ama bu
programcıyı ilgilendirmez.
Stream'ler için olduğu gibi Reader ve Writer'ların da buffer'lı versiyonları BufferedReader ve
BufferedWriter bulunmaktadır. Performansı arttırmak için kullanılmaları faydalı olur.
Reader'lar
Character ve text tipinde data okumak için InputStream'ler yerine Reader'lar kullanılır.
Bir text dosyasını satır satır okuyup ekrana basan bir application yazalım.
Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.io.*;
2 public class TextReader{
3
public static void main(String[] args)
4
throws Exception
5
{
6
String filename="c:\\myfolder\\myfile.ext";
7
FileReader file=new FileReader(filename);
8
BufferedReader in=new BufferedReader(file);
9
String line="";
10
String text="";
11
while ((line = in.readLine()) != null){
12
text+=line+"\n";
13
}
14
in.close();
15
System.out.print(text);
16
}
17
18 }
Writer'lar
Character tipinde veri yazmak için Writer'lar kullanılır. Bir String'i text dosyasına yazan bir
uygulama yazalım.
TextWriter.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.io.*;
2 public class TextWriter{
3
public static void main(String[] args)
4
throws Exception
5
{
6
String filename="c:\\myfolder\\myfile.ext";
7
FileWriter file=new FileWriter(filename);
8
PrintWriter out=new PrintWriter(file);
9
String text="Java is a powerful programming language and
platform.\n";
10
text+="However it is still evolving and far from being perfect.\n";
11
text+="On the other hand, no other language as promising as Java.\n";
12
out.print(text);
13
out.close();
14
}
15 }
Dosya Listesi

TextReader.java

TextWriter.java
File Class'ı
File Class'ının İşlevi
Bir dosya hakkında bilgi almak için File class'ı kullanılır. Ancak bu class bir dosyanın
içerisindeki veriyi temsil etmemektedir. Dosyalar içerisindeki verilerle çalışmak için
FileInputStream, FileOutputStream, FileReader ve FileWriter gibi classlar kullanılır.
File class'ı aynı zamanda directory (folder)'ları da temsil eder. Zaten aslında her directory diskte
kullanıcının değiştiremediği ancak dolaylı olarak üzerinde çalışabildiği bir dosyadır.
Bir dosya hakkında bilgileri ekrana basan bir program yazalım.
Göster Gizle Kopar Satır Gizle Satır Göster
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.io.*;
import java.util.*;
public class FileInspector{
public static void main(String[] args){
String filename="c:\\myfolder\\myfile.ext";
File file=new File(filename);
System.out.println("Directory?"+file.isDirectory());
System.out.println("Last Modified :"+new Date(file.lastModified()));
System.out.println("Exists?:"+file.exists());
System.out.println("Size :"+file.length());
System.out.println("Hidden?:"+file.isHidden());
}
}
File class'ı bir file hakkında çeşitli bilgileri öğrenmek için kullanılır. Bunlar işletim sisteminin bir
dosya hakkında tuttuğu kjayıtlardan gelmektedir. Dosyanın içeriğiyle ilgili bilgiler değildir.
Directory İşlemleri
Bir directory altındaki dosyaları listeleyen program yazalım.
DirectoryLister.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.io.*;
2 public class DirectoryLister{
3
static public void walk(File directory){
4
File[] files=directory.listFiles();
5
for(int i=0;i<files.length;i++){
6
File file=files[i];
7
boolean parent=file.isDirectory();
8
if(parent){
9
walk(file);
10
}else{
11
System.out.print(file.getAbsolutePath() );
12
System.out.println(" : "+file.length());
13
}
14
}
15
}
16
public static void main(String[] args){
17
String name="c:\\myfolder";
18
File directory=new File(name);
19
DirectoryLister.walk(directory);
20
}
21 }
Dosya Listesi

FileInspector.java

DirectoryLister.java
Serialization
Serialization Kavramı
Bir nesne herhangi stream'a (örneğin bir file'a ) yazılabilir ve bir stream'den okunabilir.
Programın çalışması esnasında hafızada bulunan nesneler program bitince (kapatılınca) yok olur.
Ancak serialization tekniğiyle bir nesne diske veya herhangi bir yere kaydedilebilir. Bir
program, kapanmadan önce bir dosyayaya sakladığı bir nesneyi daha sonra tekrar
çalıştırıldığında dosyadan okuyabilir. Hatta bir programın yazdığı nesneyi aynı dosyadan başka
bir program da okuyabilir. Bu şekilde nesnelerin network'te bir yerden diğerine gönderilmesi,
veritabanına normal bir veri gibi kaydedilebilmesi mümkün olabilmektedir.
Serializable
Bir class'ın serialization'a tabi tutulabilmesi için bazı koşulları sağlaması gerekir.
1. Class public olmalı.
2. Serializable' interface'ini implement etmeli. Bu interface'de implement edilecek herhangi bir
method yoktur. Sadece class'ın serialize edilebilemesine class yazarının izin verdiği anlamına
gelir. Bazı classlar güvenlik v.s. nedenlerle buna izin vermek istemeyebilir. Nesnenin
içerisindeki bütün veri serializable olmalıdır. Bir tane bile serializable olmayan nesne varsa işlem
başarısız olur.
3. Default (parametresiz) bir constructor'ı olmalıdır. Hiç bir constructor yazılmaması durumunda
da default contructor'un geçerli olduğu için yine sorun olmaz.
import java.io.*;
public MyClass implements Serializable{
public MyCLass(){
}
}
File'e Object Yazma
Hehangi bir class'tan oluşturulmuş bir nesne bir dosyaya ObjectOutputStream class'ı
aracılığıyla yazılabilir.
Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.io.*;
2 public class ObjectStorer{
3
public static void main(String[] args)
4
throws IOException
5
{
6
String filename="c:\\myfolder\\myobject.ser";
7
FileOutputStream f=new FileOutputStream(filename);
8
ObjectOutputStream out=new ObjectOutputStream (f);
9
Object mine=new Object(); //
10
out.writeObject(mine);
11
out.close();
12
}
13 }
File'dan Object Okuma
Daha önce bir dosyaya yazılmış nesne ObjectInputStream kullanılarak okunabilir.
ObjectLoader.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.io.*;
2 public class ObjectLoader{
3
public static void main(String[] args)
4
throws Exception
5
{
6
String filename="c:\\myfolder\\myobject.ser";
7
FileInputStream f=new FileInputStream(filename);
8
ObjectInputStream in=new ObjectInputStream (f);
9
Object mine=(Object)in.readObject();
10
in.close();
11
}
12 }
Bir dosyaya birden fazla nesne yazılabilir ve okunabilir. Ancak nesnelere hangi sırada yazılmışsa
o sırada okunmalıdır.
Bir nesne kaydedilirken içerisindeki bütün veri, alt nesneleri onların içindekiler dahil kaydedilir.
Aynı nesneye iki ayrı nesneden referans varsa iki kez kaydedilme durumu oluşabilir.
Class'da değişiklik olursa yazıldığı gibi okunamayacağından sorun çıkar. Bu yüzden class'ın
içerisinde
public static final long =1233421421L;
şeklinde bir property konması gerekir. Bu değer JDK ile birlikte gelen "serialver" adlı tool'dan
alınabilir.
Dosya Listesi

ObjectStorer.java

ObjectLoader.java
AWT'ye Giriş
AWT Hakkında
AWT (Abstract Windowing Toolkit - Soyut Pencereleme Takımı) Java'nın grafikli kullanıcı
arayüz ortamıdır. Başka bir deyişle pencereler, düğmeler, radyo butonlar ve menüler gibi görsel
bileşenler içeren kütüphane AWT'dir. Öncelikle AWT'nin başarılması çok güç bir iş başardığını
belirtmek gerekir. Çünkü Java, her işletim sisteminde çalışmak gibi bir iddiayla ortaya çıkan bir
dil ama görsel bileşenler her işletim sisteminde çok farklı. Farklı görünmeleri önemli değil, bazı
bileşenler bir işletim sisteminde bulunurken diğerinde olmayabiliyor. Bu yüzde AWT, en büyük
ortak çarpanı buluyor. Yani bütün işletim sitemlerinde olan bileşenleri kullanıyor. Düğme
hepsinde var ama tablo veya toolbar yok. Dahası her işletim sistemind eolan bileşenler de
birbirlerinden farklı özellikler içeriyor. Java bunlardan sadece ortak olanları alıyor. O yüzden
AWT ile yapılan arayüzler çok zengin ve çok güzel değil.
AWT'nin gerçekleştirilmesi için izlenen yol çok farklı. Her bileşen class'ı, aslında işletim
sistemindeki bir bileşenin peer'i (eş'i ). Programcı bu class'lardan birinin bir method'unu
çağırınca Java bunu alt tarafta bulunan gerçek bileşene iletiyor.O bileşende bir olay
gerçekleşince de bu üst tarafa iletiliyor. Elbette bu işlem programcıya şeffaf. Yani programcı
bunu bilmiyor.
AWT ve Swing
Java'da daha zengin bir arayüz sağlayan Swing kütüphanesi var. O da her işletim sisteminde aynı
şekilde çalışmasına rağmen zengin bileşenler içeriyor. Ancak Swing, bunu işletim sisteminin
bileşenlerini kullanmadan, her şeyi baştan kendisi yaparak başarabiliyor. Yani Swing'in düğme
bileşeni, işletim sistemindeki düğme bileşeni değil. Ona benzetilen, ama baştan yaratılan bir
bileşen. Swing, kendi bileşenlerini kendi yapıyor, sadece her işletim sistemine uygun bir şekilde
gürünmelerini sağlıyor. Hatta istenirse bir işletim sisteminde başka bir işletim sisteminin
gürünümü sağlanabiliyor. Yada hiç bir işletim sisteminde olmayan bir görünüm ortaya
çıkabiliyor.
Swing, AWT'den farklı bir arayüz sağlıyor ama yine de kendisi AWT üzerine kurulu. Yani
Swing, AWT'nin temel bileşenlerini kullanıyor. Zaten işletim sisteminin arayüzünün üzerine
kurulan AWT. Swing, AWT'deki temel özellikleri kullanarak kendi bileşenini kendi yapmış
oluyor. O yüzden AWT'de öğrenilen konulanrın %90'ı aynen Swing'de de geçerli. AWT'yi basit
arayüzü nedeniyle tercih etmeyenler de Swing kullanabilmek için AWT'yi bilmek zorunda.
AWT'nin Çalışma Mantığı
AWT'nin çalışma mantığı diğer arayüz sistemlerinden biraz farklı. Nedenlerin bir tanesi
AWT'nin başka işletim sistemlerinin üzerinde çalışmak zorunda olan bir kütüphane olması
elbette. Ancak başa bir neden de, Java'nın Internet dili olarak, her türlü makinede çalışmak gibi
bir ilkesi olması. Örneğin çok büyük ekranlı çok yüksek çözünürlüklü makinelerde de küçük
ekran ve düşük çözünürlüklü makinelerde de çalışmalı. Bir browser içerisinde de çalışmalı
bağımsız bir application olarak da çalışmalı. Bu gibi nedenlerden dolayı farklı bir arayüz
sistemlerinde çalışanlar için biraz garip gelebilecek bir yapıya sahip. Örneğin, 'şu düğmeyi şu X
ve şu Y noktasına koy' demiyorsunuz AWT'de. Onun yerine şunu ortaya şunu sola şunu yukarıya
koy diyebiliyorsunuz. Belki bir anlamda sınırlayıcı olabilen bu özellik, pencerenin büyümesi
veya küçülmesi durumunda da bileşenlerin görünmesini sağladığı için çok avantajlı olabiliyor.
Bir başka özelliği de arayüzün sadece kod yazarak kolaylıkla oluşturulabilmesi. Basit bir
pencerenin içerisine bir tane düğme ve bir tekst alanı koymak için sadece bir kaç satır kod
yeterli. Hiç bir görsel editör kullanmaya gerek yok. Elbette isteyen kullanabilir ama editör
kullanmadan da çok iyi arayüzler üretilebilir.
Temel Class'lar
AWT'de en temel nesneleri Component, Container ve Window olarak verilebilir. Component
tek başına işlev gören en küçük bileşendir. Button, TextField, List gibi bileşenler birer
component'tir. Container, içerisinde başka componentler bulunduran bir component'tir.
Window, içerisinde çeştili componentler veya container'lar bulunan, ekranda dikdörtgen
şeklinde görülebilen bir alan anlamına gelir. Frame (title bar'ı minimize/maximize/close
düğmeleri bulunan pencere) ve Dialog birer window'dur.
Window'lar
Window Class'ı
AWT'de Window class'ı ekranda dikdörtgen şeklinde görülebilen bir alan anlamına gelir. Bir
uygulamadaki görsel bütün component'leri içerisinde barındıran class budur. Frame gibi Dialog
class'ı da bu Window class'ını extend eder.
Frame
Üzerinde başlık çubuğu, simge durumuna getir, ekranı kapla gibi düğmeler bulunan class
Frame'dir. Yaratıldığında görünmez olan bu nesne, içerisine bütün component'ler konulduktan
sonra setVisible() method'u kullanılmalıdır.
myframe.setVisible(true);
yazılarak görünür hale getirilir.
Bazı uygulamalar pencere, menü, düğme gibi görsel bileşenler içerebilir. En basit görsel
bileşenler java.awt package'i içerisinde yeralır. O yüzden Frame gibi class'ları kullanabilmek için
import java.awt.*;
gibi bir ifade gereklidir.
EmptyFrameShower.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.awt.*;
2 public class EmptyFrameShower{
3
public static void main(String[] args){
4
Frame f=new Frame();
5
f.setBounds(100,100,400,300);
6
f.setVisible(true);
7
}
8
9 }
Bu program ekrana bomboş bir pencere çıkartıyor.
Bir Frame nesnesi yaratıldığında konumu x=0 y=0, boyutları width=0, height=0 biçimindedir. O
yüzden pencerenin boyutları setBounds() method'uyla belirlenmelidir.
Component Kullanımı
Component, tek başına belli bir işlev gören en küçük görsel bileşendir. Bir pencere içerisine
Button, TextArea, CheckBox, List gibi bazı component'ler konulabilir. Örnek olarak bir Button
ve TextArea koyalım.
ComponentFrameShower.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.awt.*;
2 public class ComponentFrameShower{
3
public static void main(String[] args){
4
Frame f=new Frame();
5
f.setLayout(new BorderLayout());
6
f.setBounds(100,100,400,300);
7
Button b=new Button("Press me!");
8
f.add(b,BorderLayout.NORTH);
9
TextArea t=new TextArea("Write in me!");
10
f.add(t,BorderLayout.CENTER);
11
Label l=new Label("Just read me!",Label.CENTER);
12
f.add(l,BorderLayout.SOUTH);
13
f.setVisible(true);
14
}
15
16 }
Bu kod çalıştırıldığında ekrana geçecek pencere :
Bir button nesnesinin yaratılması onun görülmesi anlamına gelmez. Onun pencereye add()
methoduyla eklenmesi gerekir.
Menu'ler
Bir Frame'e menu eklemek için MenuBar, Menu ve MenuItem class'ları kullanılır.
MenuFrameShower.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.awt.*;
2 public class MenuFrameShower{
3
public static void main(String[] args){
4
Frame f=new Frame();
5
f.setBounds(100,100,400,300);
6
MenuBar mb=new MenuBar();
7
Menu file=new Menu("File");
8
file.add(new MenuItem("New"));
9
file.add(new MenuItem("Open"));
10
file.add(new MenuItem("Save"));
11
file.add(new MenuItem("Save As"));
12
file.addSeparator();
13
file.add(new MenuItem("Exit"));
14
mb.add(file);
15
Menu edit=new Menu("Edit");
16
edit.add(new MenuItem("Undo"));
17
edit.add(new MenuItem("Redo"));
18
edit.addSeparator();
19
edit.add(new MenuItem("Cut"));
20
edit.add(new MenuItem("Copy"));
21
edit.add(new MenuItem("Paste"));
22
mb.add(edit);
23
f.setMenuBar(mb);
24
f.setVisible(true);
25
}
26 }
Bu kod çalıştırıldığında ekrana gelecek pencere :
Dosya Listesi

EmptyFrameShower.java

ComponentFrameShower.java

MenuFrameShower.java
Layout'lar
Layout Manager'ları
Java'da Component'lerin nereye nasıl konacağını belirleyen LayoutManager'lar vardır. Her
Container'ın bir layout manager'ı bulunur. Bir Component'in, dikdörtgen olması nedeniyle
ekranda x,y, width ve height gibi özellikleri bulunur. Layout manager'lar sayesinde her
component için bu değerleri girmek gerekmez. Hangi bileşenin nerde görüneceğine layout
manager'lar karar verir. Java'da çok sayıda layout manager bulunmaktadır. Aşağırakiler sadece
birer örnektir.
BorderLayout
En fazla kullanılan layout'lardan biri BorderLayout'tur. Component'leri North, South, East,
West ve Center gibi konumlara koyabilir.
BorderLayoutSample.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.awt.*;
2 public class BorderLayoutSample{
3
public static void main(String[] args){
4
Frame f=new Frame();
5
Button e=new Button("Doğu");
6
Button w=new Button("West");
7
Button n=new Button("North");
8
Button s=new Button("South");
9
Label c=new Label("Center",Label.CENTER);
10
f.setLayout(new BorderLayout());
11
f.add(e,BorderLayout.EAST);
12
f.add(w,BorderLayout.WEST);
13
f.add(n,BorderLayout.NORTH);
14
f.add(s,BorderLayout.SOUTH);
15
f.add(c,BorderLayout.CENTER);
16
f.setBounds(100,100,400,300);
17
f.setVisible(true);
18
}
19
20 }
Bu programın ekran görüntüsü şöyledir :
GridLayout
Bir başka layout da component'leri ızgara biçiminde sıralayan GridLayout'tur
GridLayoutSample.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.awt.*;
import java.awt.*;
public class GridLayoutSample{
public static void main(String[] args){
Frame f=new Frame();
f.setLayout(new GridLayout(4,3));
f.add(new Button("1"));
f.add(new Button("2"));
f.add(new Button("3"));
f.add(new Button("4"));
f.add(new Button("5"));
f.add(new Button("6"));
f.add(new Button("7"));
f.add(new Button("8"));
f.add(new Button("9"));
f.add(new Button("*"));
f.add(new Button("0"));
f.add(new Button("#"));
f.setBounds(100,100,400,300);
f.setVisible(true);
}
}
Flow Layout
FlowLayout, component'leri soldan sağa doğru sırayla koyar. Bir sıra bitince sol altından
yeniden dizer.
FlowLayoutSample.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1 import java.awt.*;
2 public class FlowLayoutSample{
3
public static void main(String[] args){
4
Frame f=new Frame();
5
f.setBackground(SystemColor.control);
6
f.setLayout(new FlowLayout());
7
f.add(new Button("Button"));
8
f.add(new TextArea("Area"));
9
f.add(new TextField("TextField"));
10
f.add(new Label("Label"));
11
f.add(new Checkbox("Checkbox"));
12
List list=new List();
13
list.add("List Item 1");
14
list.add("List Item 2");
15
list.add("List Item 3");
16
f.add(list);
17
f.setBounds(100,100,600,300);
18
f.setVisible(true);
19
}
20
21 }
Bu kod çalıştırıldığında ekrana geçecek pencere :
GridBagLayout
Diğer layout'ların basit yapısına karşın, GridBagLayout karmaşık düzenlemler için kullanılır.
Bunun için GridBagConstraints class'ı ile, her componentin ayrı ayrı nasıl dizileceği
belirlenebilmektedir.
Dosya Listesi

BorderLayoutSample.java

GridLayoutSample.java

FlowLayoutSample.java
Component'ler
Component Kavramı
Kullanıcıdan bir bilgi almak için kullanılan görsel nesnelere 'component' denir. Button,
TextField, CheckBox gibi component'ler bulunmaktadır. Bütün component'ler AWT içerisinde
bulunan Component adlı class'ı extend eder. Bu class bütün bileşenlerde bulunan yazı rengi,
boyutlar gibi property'ler ve çeşitli method'lar içerir.
Container Class'ı
Bir veya daha çok component içeren component'ler Container'lardır. Container'ın içine konan
component'ler belli bir layout manager tarafından yerleştirilir. Aslında Frame içerisine konan
componentler de Frame'in içerisindeki container'a konur. Container'ler da aslında birer
component'tir. Yani Container class'ı Component class'ını extend eder.
Panel Class'ı
Container class'ı içerisinde bir veya daha çok component bulundurabilen bileşen olmakla
birlikte, programcıların bu class'ı extend eden Panel adlı class'ın bu amaçla kullanılması gerekir.
Canvas Class'ı
Üzerinde çizim veya image işlemleri yapmak için kullanılması uygun olan component
Canvas'dır. Çizim yapmak için Component'teki paint() method'u override edilir :
public void paint(Graphics g){
g.drawLine(100,100,300,300)
}
Button (Düğme)
En çok kullanılan componentler'den biri olan Button, üzerinde bir etiket (label) bulunan, fareyle
tıklandığında basıldığı izlenimi veren ve bir ActionEvent üreten arayüz elemanıdır. AWT
paketinde Toolbar (araç çubuğu) yoktur, ancak bir panele bir kaç düğme eklenerek çok kolay
aynı işlevsellik elde edilebilir.
Telefonunun arayüzünü emüle eden bir pencere yapalım. Bu uygulama düğmelerden birine
basılarak yazılan numarayı güya arasın. İşlem, hangi düğmeye basılıdığını anlamak, eğer "Yes"
gibi kontrol tuşuysa bir işlem yapmak, "1","2","3" gibi numaraysa diplay'da göstermekten
ibarettir. PhoneSimulatorFrame class'ı implements ActionListener diyerek ve actionPerformed()
methodunu yazarak düğmeleri dinleyebilme özelliği kazanmıştır. Düğmelere kendisini
button.addActionListener(this) şeklinde kaydettirir. Hangi düğmeye basıldığını event'in
source'undan öğrenmektedir.
PhoneSimulatorFrame.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.awt.*;
import java.awt.event.*;
public class PhoneSimulatorFrame
extends Frame
implements ActionListener
{
private TextField display=null;
public PhoneSimulatorFrame() {
setBounds(100,100,100,200);
setLayout(new BorderLayout());
display=new TextField("");
add(display,BorderLayout.NORTH);
Panel buttons=createButtonsPanel();
add(buttons,BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent event){
Button button=(Button)event.getSource();
String label=button.getLabel();
if(label.equals("Yes")){
String text=display.getText();
if(text.length()==7 || text.length()==11){
System.out.println("Calling "+text);
}else{
System.out.println("Error!");
}
}else if(label.equals("C")){
display.setText("");
}else if(label.equals("No")){
display.setText("");
System.out.println("Cancelled.");
}else{
String text=display.getText();
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 }
text=text+label;
display.setText(text);
}
}
private Panel createButtonsPanel(){
Panel buttons=new Panel(new GridLayout(5,3));
addButton(buttons,"Yes");
addButton(buttons,"C");
addButton(buttons,"No");
addButton(buttons,"1");
addButton(buttons,"2");
addButton(buttons,"3");
addButton(buttons,"4");
addButton(buttons,"5");
addButton(buttons,"6");
addButton(buttons,"7");
addButton(buttons,"8");
addButton(buttons,"9");
addButton(buttons,"*");
addButton(buttons,"0");
addButton(buttons,"#");
return buttons;
}
private void addButton(Panel panel,String label){
Button button=new Button(label);
button.addActionListener(this);
panel.add(button);
}
public static void main(String[] args){
PhoneSimulatorFrame frame=new PhoneSimulatorFrame();
frame.setVisible(true);
}
Burada frame sadece button'ları dinlediği için event'in source'u Button'a cast edilmiştir. Eğer
başka bileşenleri de dinleseydi source'un Button olup olmadığını kontrol etmemiz gerekirdi.
Bunun için bir nesnenin belli bir class'ın veye subclass'ının bir instance'ı olup olmadığını kontrol
eden instanceof operatörü kullanılır. Örnekteki actionPerformed() aşağıdakine uygun olarak
değiştirilmelidir.
Object source=event.getSource();
if(source instanceof Button){
Button button=(Button) source;
}
TextArea
Bir kaç satırdan oluşan metin girişi için kullanılır. İçerisindeki text'in tamamı ve seçilmiş
kısmıyla ilgili bir çok method içerir.
TextField
Tek satırlık bilgi girişi için bu component kullanılır. TextArea'dan bir farkı da Enter'a
basıldığında ActionEvent'i üretebilmesidir.
Label
Kullanıcının değiştiremeyeceği tek satırlık metin için kullanılır. İşlevi ekranda belli bir yazıyı
sergilemekten ibarettir.
Checkbox
Kullanıcının bir konudaki tercihini öğrenmek için kullanılır. Birden fazla Checkbox bir
CheckboxGroup'a eklenirse, sadece aynı anda sadece birinin seçili olabildiği radio button olarak
çalışır.
List
Kullanıcının bir liste içerisinden herhangi birini seçmesi için kullanılır. Bir veya daha fazla
maddenin seçilmesine olanak tanır. Bir elemanın üzerinde çift tıklama durumunda çok eleman
seçilmiş olur.
Choice
Birden fazla elemanın tıklamayla açılan bir listeden eleman seçilmesine olanak tanıyan
bileşendir. Ekranda sadece seçili olan elamanı gösterir.
Form Örneği
Çok kullanılann bileşenleri içeren bir form örneği yapalım. Tamam düğmesine basılınca
kullanıcının girdiği değerleri ekrana bassın. Burada sadece düğmenin ürettiği ActionEvent
dinlenmektedir. Aslında Checkbox,Choice ve TextField'ları da dinlemek mümkündür. Ama o
durumda kullanıcının bilgi girişi bitmeden bir tepki verilir ki, form türü bilgi girişlerinde bu pek
doğru olmaz.
Burada her component grubu ayrı bir panel'e konmuş, daha sonra bütün paneller ana pencereye
yerleştirilmiştir. Bu şekilde sadece GirdBagLayout, GridLayout ve BorderLayout
kullanılarak karmaşık bir form yapılabilmiştir.
Insets class'ı her bileşenin etrafında kendisine ayrılan yerden bırakılacak aralığı belirler. Bu
şekilde bileşenlerin kendi alanlarını tamamen doldurması, birbirlerine ve en dış sınırlara
yapışması engellenmiş olur.
Bir başka önemli konu da, düğmelere ActionListener eklenmesinin anonymous inner class'larla
gerçekleştirlmiş olmasıdır. Bu şekilde ayrı bir listener class'ı yapmaya gerek duymadan ya da asıl
class'ın ActionListener'ı implement etmeye mecbur bırakmadan düğmeleri dinlemiş olduk.
Ayrıca birden fazla bileşenin dinlenmesine rağmen actionPerformed() methodunda hangi
düğmeye basıldığını anlamak için herhangi bir ayıklma yapmak zorunda kalmadık. "OK" ve
"Cancel" düğmeleri ayrı ayrı dinlenmektedir.
Dikkat edildiyse örnekte bazı bileşenler class'da property olarak tutulmuştur. Bunun nedeni,
tanımlandıkları method dışında da erişilebilmelerini sağlamaktır. Aksi taktirde her değişkenin
içinde bulunduğu '{' ve '}' scope'unun dışında tanınmaması yüzünden bu bileşenlere ve
içerisindeki verilere erişemeyebilirdik.
ComponentFormSample.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.awt.*;
import java.awt.event.*;
public class ComponentFormSample
extends Frame
{
private TextField name=new TextField();
private CheckboxGroup gender=new CheckboxGroup();
private Checkbox[] hobbies=new Checkbox[3];
private Choice education=new Choice();
private TextArea description=new TextArea();
public ComponentFormSample() {
setFont(new Font("Arial",Font.BOLD,12));
setBackground(Color.lightGray);
setBounds(100,100,300,500);
setLayout(new GridBagLayout());
Label label=new Label("INFORMATION FORM",Label.CENTER);
addPart(label,1,1);
Panel names=createNamesPanel();
addPart(names,2,1);
Panel genders=createGendersPanel();
addPart(genders,3,1);
Panel hobbies=createHobbiesPanel();
addPart(hobbies,4,4);
Panel education=createHobbiesPanel();
addPart(hobbies,8,1);
Panel descriptions=createDescriptionsPanel();
addPart(descriptions,9,1);
Panel buttons=createButtonsPanel();
addPart(buttons,10,1);
}
public Insets insets(){
return new Insets(25,15,15,15);
}
private void addPart(Component part,int row,int height){
GridBagConstraints constraints=new GridBagConstraints();
constraints.gridx=0;
constraints.gridy=row;
constraints.gridwidth=1;
constraints.gridheight=height;
constraints.weightx=1.0;
constraints.weighty=1.0;
constraints.fill=GridBagConstraints.BOTH;
constraints.insets=new Insets(5,0,5,0);
add(part,constraints);
}
private Panel createNamesPanel(){
Panel panel=new Panel(new GridLayout(1,2));
panel.add(new Label("Full Name "));
panel.add(name);
return panel;
}
private Panel createGendersPanel(){
Panel panel=new Panel(new GridLayout(1,3));
Checkbox male=new Checkbox("Male",gender,true);
Checkbox female=new Checkbox("Female",gender,false);
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
panel.add(new Label("Gender"));
Panel boxes=new Panel(new GridLayout(1,2));
boxes.add(male);
boxes.add(female);
panel.add(boxes);
return panel;
}
private Panel createHobbiesPanel(){
Panel panel=new Panel(new GridLayout(4,1));
panel.add(new Label("Hobbies"));
hobbies[0]=new Checkbox("Computer",true);
panel.add(hobbies[0]);
hobbies[1]=new Checkbox("Music",false);
panel.add(hobbies[1]);
hobbies[2]=new Checkbox("Art",false);
panel.add(hobbies[2]);
return panel;
}
private Panel createEducationPanel(){
Panel panel=new Panel(new GridLayout(1,2));
education.add("Primary");
education.add("Secondary");
education.add("High School");
panel.add(new Label("University"));
panel.add(education);
return panel;
}
private Panel createDescriptionsPanel(){
Panel panel=new Panel(new BorderLayout());
Label label=new Label("Description");
panel.add(label,BorderLayout.NORTH);
panel.add(description,BorderLayout.CENTER);
return panel;
}
private Panel createButtonsPanel(){
Panel panel=new Panel(new GridLayout(1,2));
Button ok=new Button("OK");
ok.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
printData();
setVisible(false);
}
}
);
panel.add(ok);
Button cancel=new Button("Cancel");
cancel.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
setVisible(false);
}
}
);
panel.add(cancel);
return panel;
}
113
private void printData(){
114
System.out.println("# Name :"+name.getText());
115
System.out.println("# Gender
:"+gender.getSelectedCheckbox().getLabel());
116
System.out.println("# Hobbies ");
117
for(int i=0;i<hobbies.length;i++){
118
System.out.println(hobbies[i].getLabel()+" :
"+(hobbies[i].getState()?"Yes":"No"));
119
}
120
System.out.println("# Description : "+description.getText());
121
}
122
public static void main(String[] args){
123
ComponentFormSample frame=new ComponentFormSample();
124
frame.setVisible(true);
125
}
126 }
Dosya Listesi

PhoneSimulatorFrame.java

ComponentFormSample.java
Dialog'lar
Dialog
Ekrana bir Diyalog kutusu getiren class Dialog'dur. Genellikle kullanıcıdan kısa zamanda bir
bilgi beklendiğinde kullanılır. Frame'den fazla bir farkı olmadığı için aynı şekilde kullanılabilir.
Diyaloğun 'modal' olması durumunda kullanıcının asıl pencrede işlem yapması engellenir.
Modal yapmak için
mydialog.setModal(true);
demek veya constructor'da modal parametresini true olarak girmek gerekir.
File Dialog
FileDialog, kullanıcı bir dosyayı açmak istediğinde veya belli bir yere farklı kaydetmek
istediğinde kullanılır. Basit bir text editörü yapalım. Bir file menüsü olsun ve text dosyalarını
açma ve saklama özelliğine sahip olmasını sağlayalım. FileDialog class'ı ekrana kullanıcının
dosyayı belirleyebileceği bir diyalog kutusu getirir. Bu class LOAD (Open) ve SAVE modunda
açılabilir. Kullanıcının seçtiği dosyanın adını ve directory'si (ayrı ayrı) öğrenilebilir. Dosya
açarken
FileDialog dialog=new FileDialog(this,"Open",FileDialog.LOAD);
dialog.setVisible(true);
String filepath=dialog.getDirectory()+dialog.getFile();
şeklinde bir kod parçası kullanılır. Dosyayı başka bir adla kaydederken bu kodda sadece
FileDialog dialog=new FileDialog(this,"Save",FileDialog.SAVE);
şeklinde değişiklik yapmak yeterlidir.
TextEditor.javaIndir Göster Gizle Kopar Satır Gizle Satır Göster
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class TextEditor
extends Frame
implements ActionListener
{
private TextArea area=new TextArea();
private String filepath="Untitled.txt";
public TextEditor() {
setBounds(0,0,640,480);
putMenuBar();
setLayout(new BorderLayout());
add(area,BorderLayout.CENTER);
}
private void putMenuBar(){
Menu file=new Menu("File");
putMenuItem(file,"New");
putMenuItem(file,"Open");
putMenuItem(file,"Save");
putMenuItem(file,"Save As");
file.addSeparator();
putMenuItem(file,"Exit");
MenuBar menubar=new MenuBar();
menubar.add(file);
setMenuBar(menubar);
}
private void putMenuItem(Menu menu,String label){
MenuItem item=new MenuItem(label);
item.addActionListener(this);
menu.add(item);
}
public void actionPerformed(ActionEvent event){
MenuItem item=(MenuItem) event.getSource();
String label=item.getLabel();
if(label.equals("New")){
handleNew();
}else if (label.equals("Open")){
handleOpen();
}else if (label.equals("Save")){
handleSave();
}else if (label.equals("Save As")){
handleSaveAs();
}else if (label.equals("Exit")){
handleExit();
}
}
private void setContent(String text,String filepath){
area.setText(text);
this.filepath=filepath;
setTitle(filepath);
}
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
private void handleNew(){
setContent("","Untitled.txt");
}
private void handleOpen(){
try{
FileDialog dialog=new FileDialog(this,"Open",FileDialog.LOAD);
dialog.setVisible(true);
String filepath=dialog.getDirectory()+dialog.getFile();
String text=loadText(filepath);
setContent(text,filepath);
}catch(Exception e){
e.printStackTrace();
}
}
private void handleSave(){
try{
String text=area.getText();
storeText(text,filepath);
}catch(Exception e){
e.printStackTrace();
}
}
private void handleSaveAs(){
try{
FileDialog dialog=new FileDialog(this,"Save",FileDialog.SAVE);
dialog.setVisible(true);
String filepath=dialog.getDirectory()+dialog.getFile();
setTitle(filepath);
String text=area.getText();
storeText(text,filepath);
}catch(Exception e){
e.printStackTrace();
}
}
private void handleExit(){
System.exit(0);
}
private String loadText(String filepath)
throws IOException
{
FileReader fr=new FileReader(filepath);
BufferedReader in=new BufferedReader(fr);
String text="";
String line=null;
while((line=in.readLine())!=null){
text+=line;
}
in.close();
return text;
}
private void storeText(String text,String filepath)
throws IOException
{
FileWriter fw=new FileWriter(filepath);
PrintWriter out=new PrintWriter(fw);
out.print(text);
out.close();
110
}
111
public static void main(String[] args){
112
TextEditor editor=new TextEditor();
113
editor.setVisible(true);
114
}
115 }
Dosya Listesi

TextEditor.java
XML'e Kısa Bir Giriş
XML Nedir?
XML (Extensible Markup Language), veriyi belli bir yapıda tanımlamak için kullanılan bir
dildir. Bir verinin belli bir yapıda olması, o veri içerisindeki bilginin gerektiğinde kullanılabilir,
değiştirilebilir ve başka biçimlere dönüştürülebilir olmasını sağlar.
XML - Düz Metin Karşılaştırması
Diyelim ki saklamak istediğimiz veri bir sınavının soruları olsun. Sınavı düz metin (plain text)
şekilde yazalım :
Matematik Dersi 2. Ara Sınavı
Soru 1 : İki kere iki iki kaç eder?
a) 22
b) 3
c) 4
d) 5
Soru 2 : Kendimi kendimden çıkarsam kaç kalır?
a) 1
b) 2
c) 0
d) FD
Bu metin bir insanın çok rahat okuyabileceği ve anlayabileceği bir biçimde yazılmıştır. Ama bir
bilgisayar programı bu metnin içindeki bilgileri okuyamaz. '1. sorunun ikinci şıkkı' gibi bir
bilgiyi belge içerisinden nasıl bulunabileceğini düşünelim. En basit yol metni satırlara bölmek ve
4. satırı almak, sonra da ilk boşlıktan sonraki kısmı okumaktır. Peki ya sınav adından sonra bir
boşluk eklenirse? Program bu kez yanlış satırı getirecektir. Ya 'b' şıkkında 'b' ile ')' arasına bir
boşluk konursa? O zaman sayı yerine bir parantez elde edeceğiz! Görüldüğü gibi düz metin bir
programın veri saklaması ve erişmesi için uygun bir biçim değildir.
XML - Tablo Karşılaştırması
Geleneksel olarak veri tablolarda tutulur. Bir okuldaki öğrenciler
123
234
542
423
Barış Manço
Cem Karaca
Edip Akbayram
Ersen
Tablo tarzı veriler düz bir dosya'da (flat file'da) saklanabilir. Her kayıt bir satıra konur ve bir
kayıtta her alan arasına boşluk, sekme (tab), noktalı virgül (;), virgül(,) gibi ifadeler konur.
Olmayan değerler boş geçilir. O zaman bir programın bunları anlaması kolay olur. Düz tabloların
gelişmesiye veritabanları doğmuştur. Bir veri tabanında tablolarda hangi alanların olacağı ve bu
alanlarda bulunabilecek verinin (metin,tamsayı veya kesirli sayı gibi) tipleri belirenir. Bunlara
erişmek için SQL diye bir dil bulunmaktadır. 542 numaralı öğrencinin adını öğrenmek için
select Name form Student
şeklinde bir 'sorgu' (query) yazılır.
Zamanla, tablo yapısının çok kısıtlı olduğu ortaya çıkmıştır. Birbirine eşdeğer maddelerden
oluşmayan veriler için tablo yapısı yetmez. Basit bir liste bile tablolarla kolay olarak
gösterilemez. Bir şeyin altında başka birşey, onun altında da başka bir şey varsa tablolar gittikçe
karmaşıklaşmaya, düzenli veri saklamak yerine giderek düzensizleşmeye başlar. Bir sınavın
sorularını saklamayı düşünelim. Diyelim ki her sınavda bölümler, bölümlerde sorular, sorularda
da şıklar olsun. Bunun için nasıl bir tablo yapmamız gerekir? Bir tabloda hem soru hem de şıklar
saklanamaz. Bu yüzden birden çok sayıda tablo yapmak zorunda kalırız ver aralarında 'ilişki'
(relation) kurmak gerekli hale gelir. Tablolar Sınav, Bölüm, Soru ve Şık şeklinde dört adettir.
Üstelik aynı sınavın sorusu bir tabloda şıkkı başka tablodayken, bir sınavın sorusu ile başka
sınavın sorusu aynı tabloda yer alır. Bir sınavdaki soruları öğrenmek için dört tablodan veri
toplanması gerekir. Oysa XML ne kadar karmaşık yapıda olursa olsun veriyi bir arada tutar ve
kolayca erişim sağlar.
XML-HTML Karşılaştırması
HTML'de veri belli bir yapı içerisinde bulunur. Ancak bu yapı bilginin gerektiğinde
erişilebilmesini değil, belli bir biçimde ekranda gösterilmesini sağlar. HTML içerisindeki veriye
kolay kolay erişemezsiniz. Bir yazının başlığını bir kişi H1 etiketini kullanarak gösterir, başka
bir kişi H2. Hatta font'u büyük vererek de başlık verilebilir. Bu durumda HTML belgesi içinde
belli bir verinin tam olarak nerde olduğunu bulmak mümkün değildir. HTML, veri (data) ile
biçim (style)'ın iç içe olduğu bir yapıdır. Oysa XML'de veri ayrı biçim ayrı tutulabilir. Aynı
biçimle bir çok veri gösterilebilirken aynı veri bri çok biçimde gösterilebilir.
Basit bir XML örneği
Bir sınavı XML olarak belirmek için şöyle bir yapı kurmak yeterlidir.
<exam id="math-3">
<title>Matematik Dersi 2. Ara Sınavı </title>
<question number="1">
<text>İki kere iki iki kaç eder?</text>
<option id="a">22</option>
<option id="b">3</option>
<option id="c">4</option>
<option id="d">5</option>
</question>
<question number="2">
<text>Kendimi kendimden çıkarsam kaç kalır?</text>
<option id="a">1</option>
<option id="b">2</option>
<option id="c">0</option>
<option id="d">FD</option>
</question>
</exam>
Burada veri belki daha çok yer kaplar ama artık herhangi bir veriye ulaşmak çok basittir. Belki
bir kişinin kendi yazığı bir programla bu belgeden veri alması daha zordur ama en azından araya
bir şey eklenirse veya çıkartılırsa program yanlış bilgiye erişmez. Dahası, bir XML belgesinden
herhangi bir bilgiyi almak için çeşitli olanaklar bulunaktadır. Programcı her zaman kendisi bir
şey yapmak zorunda kalmaz. Örneğin XPath'le ilk sorunun 2. şıkkına erişim için
/exam/question[number="1"]/option[id="1"]]
yazmak yeterlidir. Aynı şekilde 2. sorunun metnine
/exam/question[number="1"]/text
şeklinde erişmek mümkündür. XPath olmadan da bir 'parser' programla XML belgesi
programlar tarafından okunması için 'document' nesnesine okunabilir.
XML'in bütün espirisi bir veriyi metin olarak saklamak ve gerektiğinde kolayca erişmektir. Bu,
göründüğünden çok daha güçlü özelliktir.
Temel XML Terimleri
Her XML birimine document denir. Bu genellike bir dosyaya karşılık gelir. Document'ler
element'lerden oluşur. Element içerisinde belli bir bütünlük içeren veridir. Bir belge içerisinde
herşeyi içine alan bir ana element olmalıdır ki buna 'root' veya da 'document element' denir. Her
element attribute'lerden, child element'lerden ve text'lerden oluşur. Attribute bir element
hakkında bilgi veren özelliklerdir. Text'se bir element'in içinde bulunan düz metindir. XML'de
element, attribute ve text gibi birimlere node denir. Burda anlatılan yapı sadece XML için değil
HTML ve JavaScript gibi DOM standardını destekleyen bütün yapılar için geçerlidir.
Yazım kurallarına uygun olarak yazılmış bir belgeye 'well-formed' denir. Ancak bu içerisindeki
verinin mantıksal olarak doğru yapıda olduğu anlamında gelmez. '<' ile başlayan bir etiketi '>' ile
kapatmak gibi kurallara uymak anlamına gelir. Bir XML belgesinin mantıklı bir veri içermesi
durumunda 'valid' olur. Örneğin sorunun içine şık koymak yerine şıkkın içine soru koyarsanız
veri yine well-formed olabilir, ama valid olmaz.
Temel XML Teknolojileri
XML'le birlikte bir çok dil ortaya çıkmıştır. Bir XML document'inde ne gibi element'ler ve
attribute'ler olduğunu göstermek için kullanılan dile DTD denir. DTD ile benzer bir işlev gören
ancak element ve attributelerin değerlerinin geçerlilik kriterlerini belirleme gibi fazladan
özellikleri bulunan XSchema diye bir dil daha vardır ki bu dil de aslında XML'le yazılmıştır. Bir
XML document'inde belli bir düğümün konumunu belirtmek için XPath kullanılır. Bir XML'i
başka bir biçime, yani başka bir XML'e, düz metne veya HTML'e dönüştürmek için XSL
kullanılır. XSL'de bir XML dilidir. Bir XML belgesinden diğer bir XML belgesine bağlantı
kurmak için XLink, aynı XML belgesinde bir düğümden diğerine işaret etmek için XPointer
kullanılır.
XML'in çok fazla uygulaması bunmaktadır. XHTML, HTML'in XML versiyonu; MathML
matematiksel ifadeleri belirlemek için kullanılan bir dil; SVG iki boyutlu grafikleri metin
yoluyla oluşturmak için kullanılan bir dil, SMIL multimedya bileşenlerini birlikte kullanmak
için kullanılan bir dildir. Ancak XML bunlarla sınrılı değildir. Hatta her programcının kendine
bir veya daha fazla dil oluşturabilir.
Bir XML Document'i Oluşturmak
XML Dosyası Yaratmak
Bir metin dosyasına '.xml' uzantısı verilip içerisine well-formed bir XML belgesi yazarsak
herhangi bir uygulama tarafından işlenebilecek bir belge oluşturmuş oluruz. Yapılacak işlemleri
sırasıyla verirsek :

Bir klasörde ('C:\Java\Xm' olsun) bir metin dosyası yaratıp (adı 'test' olsun) uzantısını
'xml' verin

Bu dosyayı bir metin düzenleyicide (NotePad veya WordPad'te) açın

İçerisine well-formed XML yazıp kaydedin

XML'i gösterebilen bir programda (örneğin Internet Expolorer) yarattığınız belgeyi açın.
Eğer yarattığınız XML dosyası XML açabilen herhangi bir programda hatasız açılabiliyorsa
XML 'well-formed' demektir. Bu şekilde Java veya herhangi bir programlama ortamına ihtiyaç
duymadan XML çalışabilirsiniz.
XML Dosyasının İçeriği
Bir XML belgesinde olması gereken tek şey bir root element'tir. Yani
<exam/>
şeklindeki ifade yeterlidir. Zorunlu olmamakla birlikte 'prolog' denilen giriş kısmı genellikle
konur
<?xml version="1.0" encoding="ISO-8859"?>
Bir XML document'inde prolog 'version' ve encoding bilgisi içerebilir. Burada version XML'in
versiyonudur, aşağıda kullanılan herhangi bir xml dilinin değil. Genellikle 1.0 konur. Zaten bu
yazının yazıldığı tarih itibariyler sadece 1.1 versiyonu bulunmaktadır ki sadece az kullanılan
dillerin karakter kodlamalarını desteklemek gibi çok önemli olmayan değişiklikler içermektedir.
Belgelerdeki 'encoding' önemlidir, türkçe karakterle için türkçe encoding (ISO-8859-9)vemek
gerekir. Encoding değeri olarak 'UTF-8' de verilebilir.
Aşağıdaki metni bir dosyaya kaydedederseniz geçerli bir XML belgesi yazmış olursunuz.
<exam id="math-3">
<title>Matematik Dersi 2. Ara Sınavı </title>
<question number="1">
<text>İki kere iki iki kaç eder?</text>
<option id="a">22</option>
<option id="b">3</option>
<option id="c">4</option>
<option id="d">5</option>
</question>
<question number="2">
<text>Kendimi kendimden çıkarsam kaç kalır?</text>
<option id="a">1</option>
<option id="b">2</option>
<option id="c">0</option>
<option id="d">FD</option>
</question>
</exam>
Buradaki XML'in konulduğu örnek :
ExamTest.xmlİndir Göster Gizle Kopar Satır Gizle Satır Göster
1 <?xml version="1.0" encoding="ISO-8859-9">
2 <exam id="math-3">
3
<title>Matematik Dersi 2. Ara Sınavı </title>
4
<question number="1">
5
<text>İki kere iki iki kaç eder?</text>
6
<option id="a">22</option>
7
<option id="b">3</option>
8
<option id="c">4</option>
9
<option id="d">5</option>
10
</question>
11
<question number="2">
12
<text>Kendimi kendimden çıkarsam kaç kalır?</text>
13
<option id="a">1</option>
14
<option id="b">2</option>
15
<option id="c">0</option>
16
<option id="d">FD</option>
17
</question>
18 </exam>
Download