Copyright @ Tm Esercan oyun 2015

Java

JAVA

Egitim Notları

2

JAVA ile Programlama

Giris

Bu egitimde iyi bir java programcısı olmak için gerekli olan tüm bilgileri yogun uygulamalar çerçevesinde

inceleyecegiz. Bu bilgileri ögrenirken aslında bilgisayar programcılıgının tüm temellerini de ögrenecek, çalısmamızı

tamamladıgımızda da java programlama dilinin tüm sözdizimi yapısını, dilin kurallarını ve bu dil içerisinde yer alan

temel paketlerin kullanımını rahatlıkla kavramıs olacaksınız. Ayrıca temel kavramları ögrendikten sonra ileri

düzeyde interaktif bir program yazabilmeniz için gerekli olan kullanıcı arayüz tasarımının Java ile nasıl

yapılabilecegini de görecegiz.

Bu Egitim Kimler çin?

Teknik detaylara girmeden önce sunu belirtmek gerekir ki bu çalısma daha önce hiç bilgisayar programcılıgı ile ilgili

çalısmayanlar için çok iyi bir baslangıç ve az çok bu isi bilenler için de iyi bir arsiv olacak sekilde hazırlanmıstır.

Egitim içerisinde en temel kavramları anlatırken hem mevcut bilgilerinizi ilerletecek hem de önceden ögrendigimizi

sandıgımız temel bilgilerinizi tekrarlamıs olacaksınız. Ayrıca arasıra deginecegimiz pratik ipuçları sayesinde de, uzun

zaman harcayarak elde edecegimiz bazı bilgilere, hemen erisme sansına sahip olacagız.

Java Platform Bagımsızdır

Dogasında platform bagımsız olarak çalısan Java uygulamalarımızı ve uygulamaları olusturmak için kullanacagımız

araçları hem Windows hem de Linux isletim sistemlerine yönelik hazırladıgımızdan herhangi bir kısıtlama içerisine

de girmeyeceksiniz.

Bu dersimizde Java programcılıgına giris yapacak ve asagıda listelenen baslıkları ögrenmis olacagız:

* Java nedir? Nerelerde kullanılır?

* Nesne yönelimli programcılık nasıl olur?

* Java paketleri

* Kurulum ve ilk ayarlar

* Java ile bir uygulamanın çalıstırılması

* Nesne kavramı ve sınıf tasarımı

* Temel yazım kuralları

Egitim boyunca ögrenecegimiz tüm bilgileri dikkatlice okumanızı ve sıklıkla tekrar etmenizi öneririm. Ayrıca anlatım

sırasında ve pratik amaçlı verilecek örnekleri de mutlaka kendiniz de yazıp denemelisiniz. Unutmayınız ki iyi bir

bilgisayar programcısı olmak, bir müzik aletini iyi çalabilmeye benzer. Bunu basarmanın en kolay yolu da sayısız

pratik yapmaktır. 1lk baslarda anlamsız ve kolay gibi görünen uygulamaları sabırla yazıp denediginizde ne kadar çok

yere takıldıgınızı farkedeceksiniz. Ayrıca bu pratiklerin ilerleyen haftalarda nasıl bir yetenek kazandırdıgına

inanamayacaksınız

Nedir Bu Java?

1lk olarak Java programlama dili ve nesne yönelimli programlama teknigi hakkında kısaca bilgi edinmek iyi bir

baslangıç olacaktır.

Adı “Green Project” olarak bilinen bir projenin içerisinde yer alan James Gosling, proje için en uygun dilin

belirlenmesi isini üstlenmisti. 1984'de Sun Microsystems'de göreve baslayan Gosling, çalısmalarına C++ ile baslamıs

ancak bu dilin proje için yeterli olmayacagı düsüncesiyle, yine bu dilin bir türevi olan ve ilk adı “Oak” olan yeni bir

dili gelistirmeye baslamıstı. Daha sonra yerel bir kafeden çagrısım yaparak bu dilin adını Java olarak degistirmistir.

O günlerden bu güne Java halen gelistirilmekte olan ve günümüzde pöpülaritesi tartısılmaz olan bir dil olarak

kullanılmaktadır.

Java nesne yönelimli bir dildir

Java nesne yönelimli bir programlama dilidir. Bir programlama dilinin nesne yönelimli olması, dilin kendi özelligi

itibariyle aynı amaca yönelik görevlerin sınıf (class) denilen yapılar içerisinde toplanmasına ve bu prensibe göre

kullanımına izin vermesidir. Nesne yönelimli programcılıgın bir çok avantajı vardır. Bunlardan en önemlisi, bir

projede birbirinden bagımsız olarak tasarlanan sınıf nesneleri kullanılmasıdır. Böylece projeye belli görevlerin

eklenmesi veya çıkarılması projenin bütününe dokunmadan mümkün hale gelebilmektedir.

3

Bunu bir örnekle daha kolay kavrayabiliriz: Mesela icq benzeri bir program yazdıgımızı düsünelim. Böyle bir projede

kullanıcının karsısına gelecek uygulamanın görüntüsü ayrı bir mödül, sisteme kaydolan kullanıcıların kayıt islerinin

yürütülmesi ve veri tabanında saklanması isi ayrı bir mödül, ag baglantıları ve aga giris çıkıs kontrollerinin

yürütülmesi de ayrı bir mödül olarak tasarlanmakta ve daha sonra birlestirilmektedir. Bu tasarım sırasında herhangi

bir modülde meydana gelen aksama diger mödülleri etkilemeyecektir.

Bundan baska, belli bir görevi üstlenen bir sınıf nesnesi temel alınarak bu göreve yeni eklemeler yapmak (türetme)

Java gibi bir nesne yönelimli programlama dili ile oldukça kolaydır. Örnegin; ileriki konularda bahsedecegimiz

sekilde, siz bir pencere uygulaması tasarlamıs olabilirsiniz. Daha sonra bir baskası sizin tasarladıgınız bu pencereyi

hiç bozmadan kullanarak ve üzerine eklemeler yaparak internet explorer'a çok benzeyen baska bir pencere

uygulaması haline getirebilir. Egitimimiz devam ettikçe zaten bu teknigin aslında ne kadar vazgeçilmez oldugunu

daha iyi kavrayacaksınız.

Java Multithread Programlamayı Destekler

Aynı anda birden fazla isi yürütebilecek fonksiyonların çalısması ancak mutlithread destegi sayesinde mümkün

olacaktır. Java halihazırda buı yetenege sahiptir.

Güvenli ve Saglamdır

Java'da, C ya C++ da oldugu gibi pointer kullanımı kullanıcıya o kadar açık degildir. Bu nedenle pointer gibi kritik

kullanımlar neticesinde dogacak güvenlik problemlerine java da rastlanmaz.

Ayrıca Java'da built-in olarak bulunan birtakım araçlar sayesinde hafıza yönetimi dinamik olarak ele alınmaktadır.

Böylece hafızanın bir süre sonra dolması gibi problemler de Java dili içerisinde engel teskil etmez. Bu araçlardan en

önemlisi

 

 

Garbage Collector denilen araçtır. Bu araç hafızada tutulan ve artık kullanılmayan nesneleri otomatik

olarak temizler.

Java'nın güvenli olmasının bir diger nedeni de içerisinde sagladıgı çalısma mekanizmasıdır. Bu mekanizmayı söyle

özetleyebiliriz:

Classloader ile gelen güvenlik

Yazılan ve derlenen programlar içerisinde gerekli sınıflar

 

 

class loader denilen bir araçla programa dahil edilirler.

Ancak Class Loader ag üzerinden gelen sınıflarla lokal makinede yer alan sınıfları ayrı yerlerde tutar. Böylece daha

önceden güvenilen lokal sınıfların üzerine yazılma ihtimali ortadan kalakacaktır.

Ayrıca JVM tarafından yorumlanan byte-code ların da güvenilirligi test edilmektedir. Bu testi

 

 

byte-code verifier

denilen bir araç üstlenir. Bu islem çalısma zamanı sırasında (run-time) gerçeklestirilmektedir.

Enterprise Uygulamalar çin Gelistirlmistir.

Java sagladıgı platformlar sayesinde dagıtık (distrubited uygulamaları gelistirmek için oldukça uygundur. Dagıtık

uyuglamardan kasıt, sunucu-istemci etkilesimli, veri tabanı kullanan çok katmanlı yapılardır. Bunun için Java

Teknolojilerini incelemek gerekmetedir.

Java Paketleri

Paket denilen seyi aslında daha önce baskalarının yazıp dil içerisinde kullanılacak sekilde hazırladıgı program

parçaları olarak düsünebilirsiniz. Bu parçalar içerisinde ana programınızı yazmak için bazı özel isleri yapabileceginiz

(dosya islemleri, ag islemleri, ekran islemleri v.b.) araçlar yer almaktadır. Bu araçlar aslında tüm önemli islerini

temelini olusturacak görevleri yapabilmektedir. Daha özel uygulamalar bu temel araçların üzerine gelistirilir. Bu

nedenle temel araçları en bastan tekrar yazmak yerine paket içerisinden kullanırız. Daha teknik anlamda bu araçlar;

sınıflar ve bu sınıflara ait metod ve degiskenlerdir. Bu paketlere aynı zamanda Sınıf Kütüphanleri (Class Libraries)

de denilir.

JDK (Java Development Kit)

Bu kütüphanelerden, Pencere Yönetimi (Window Management), Giris/Çıkıs (I/O) ve Ag 1letisimi (Network

Communication) uygulamalrına yönelik olan sınıf kütüphaneleri JDK (Java Development Kit) denilen ortam içerisine

yerlestirilmistir. Bunun dısında Java içerisinde bazı isleri kolaylastıran araçlar da mevcuttur. Bu araçlar debug,

deployment ve dökümantasyonu kolaylastırmak amacıyla kullanılır.

4

Java Dökümantasyonu

Java programlama dilinin yapısını olusturan temel paketler dısında birçok farklı alanda program gelistirebileceginiz

yüzlerce paket mevcuttur. Ayrıca bu paketlerde yer alan genel konuya iliskin yüzlerce sınıf nesnesi yer almaktadır.

Bu sınıf nesnelerinin dökümantasyonunu kullanmadan iyi bir Java uygulaması gelistirmenin neredeyse imkansız

oldugunu söyleyebilirim.

Bunun için, yazılmıs kitapların yanında Java ile ilgili herseyi bulabileceginiz http://java.sun.com/ adresini

incelemenizi tavsiye ederim. En kısa yoldan bu Java paketlerini incelemek istiyorsanız

http://java.sun.com/j2se/1.4.1/docs/api/ adresinde aradıgınız herhangi bir sınıfa iliskin tüm method ve degiskenleri

bulabilirsiniz.

Java ile gelistirebileceginiz bir çok alanda uygulama oldugunu söylemistim. Aslında bu uygulamaları birbirinden

kesin bir çizgiyle ayırmak pek dogru olmaz. Ag üzerinde ortak bir veri tabanını kullanan ve görsel bir kullanıcı grafik

arayüzüne sahip olan bir projeyi gelistirmek için veri tabanı, ag uygulaması ve grafik arayüz tasarımı seklinde üç

ayrı uygulama alanında birden çalısmak gerekir. Ancak güzel olan, Java'nın nesne yönelimli bir programlama dili

olması itibariyle, bu uygulamaların ayrı ayrı gelistirilip daha sonra tek bir proje çatısı altında birlestirmenin mümkün

olmasıdır.

Java Sanal Makinesi (Java Virtual Machine)

Java'nın platform bagımsız olması demek, herhangi bri makinede yazılmıs ve bir islemci ile derlenmis bir java

uygulamasını, tek bir noktasını bile degistirmeden baska bir makine ya da islemci altında çalıstırabilmek anlamına

gelmektedir. Java'ya bu özelligi kazandıran mekanizma ise içerisinde barındırdıgı JVM (Java Virtual Machine) dir.

Bilgisayarınızda bir java uygulaması çalıstırabilmeniz için, içerisinde java sanal makinası ve kütüphanelerinin de yer

aldıgı sdk setini yüklemeniz gerekir. Yazdıgınız uygulama, makinada yer alan bu SDK ile gelen, JVM içerisinde

çalısacagından, program kodunuzda hiç bir degisiklik yapmadan ister windows altında, ister linux altında, ister

Intel, SPARC ya da Alpha islemcili bir makinada çalıstırabilirsiniz.

Java kaynak kodları .java uzantılı dosyalarda yer almaktadır. Her java dosyası çalıstırılmadan önce derlenerek aynı

isimle .class dosyasına dönüstürülür. Bu derleme islemini yapan program ise javac programıdır. Daha sonra

derlenmis olan bu .class dosyası yine jvm içerisinde yer alan java programı tarafından yorumlanır ve böylece

yazdıgınız uygulama çalıstırılmıs olur. Bunu asagıdaki resimde görmekteyiz:

Kurulum ve lk Ayarlar

SDK setinin son versiyonu ve dökümantasyon paketini http://java.sun.com/j2se/downloads.html adresinden

indirebilirsiniz. Ancak bu egitim kapsamında 1.4.2 versiyonu yeterli olacaktır.

Yukarıda seti indirebileceginiz adresi ziyaret ettiginizde, indirmek istediginiz seti belirlediginiz zaman karsınıza gelen

ikinci sayfada yine bu set ile ilgili hangi dilde, hangi platform için ve hangi paketi indireceginiz konusunda bir seçim

yapmanız istenecektir. Ayrıca yine bu sayfada daha önce web adresini verdigim dökümantasyon paketini de

indirebileceginiz bir baglantı bulacaksınız.

5

Burada “Windows (all languages, including English)” yazılı satırda SDK sütunu altındaki baglantıda yer alan set

Windows kullanıcıları için uygundur. Dilerseniz aynı sekilde Linux isletim sistemi için de uygun setleri indirebilirsiniz.

1ndirme islemi tamamlandıktan sonra Windows kullanıcıları için .exe uzantılı gelen seti üzerine tıklayarak kurmaya

baslayabilirsiniz.

Linux kullanıcıları isterlerse .rpm uzantılı kurulum paketini, isterlerse de .bin uzantılı kurulum dosyasını aynı yerden

indirebilirler. 1ndireceginiz dosya j2sdk-1_4_1_04-linux-i586.bin ya da j2sdk-1_4_1_04-linux-i586.rpm gibi bir isme

sahip olacaktır. Eger .bin dosyası ile kurulum yapacaksanız, asagıdaki gibi önce bu dosyaya çalıstırma izni verip

daha sonra da çalıstırarak kurulumu tamamlayabilirsiniz:

$ chmod a+x j2sdk-1_4_1_04-linux-i586.bin

$ ./ j2sdk-1_4_1_04-linux-i586.bin

.rpm uzantılı paketi kurmak için ilk once root kullanıcısı olmanız gerekmekteir. Daha sonar da yine asagıdaki

komutu kullanarak kurulumu tamamlayabilirisiniz:

$ su

# rpm -ivh j2sdk-1_4_1_04-linux-i586.rpm

Not:

 

 

Yukarıda bahsettigim linux ve windows platformları için kurulum islemlerine iliskin açıklamaları, kurulum

dosyalarını indirdiginiz sayfada da bulabilirsiniz.

PATH Ayarı

Kurulum islemi tamamlandıktan sonra PATH ayarını yapmamız gerekmektedir. 1sletim sistemlerinde yer alan ve

orjinal adıyla “Environment Variables” denilen bir takım anahtar degerler içerisinde çesitli bilgiler tutulur. Bu

degiskenlerden birtanesi de sistem içerisinde yazılan komutların aranacagı dizinlerin hangi dizinler olacagı bilgisini

tutan PATH degiskenidir. Java uygulamalarımızı çalıstırırken kullanacagımız komutların isletim sistemi tarafından her

yerden tanınması için bu PATH degiskenine java sanal makinasının komutlarının yer aldıgı dizinini de ekleyecegiz.

Burada bu islemi hem Windows 2000 isletim sistemi hem de Linux isletim sistemi için anlatılacagım. Ancak yukarıda

verdigim bilgiyle birlikte siz de aynı islemi baska sistemlerde de kolaylıkla yapabilirsiniz. Çünkü neticede yapılacak

sey sadece bu PATH degiskenine yeni dizini eklemek olacaktır.

Windows kullanıcılar için:

Masaüstünde yer alan Bilgisayarım (My Computer) simgesine sag tıklayınız ve Özellikler (Properties) seçenegini

seçiniz. Daha sonra karsınıza çıkan pencerede Gelismis (Advanced ) sekmesini seçiniz ve burada yer alan Çevresel

6

Degiskenler (Environment Variables) seçenegini seçiniz:

Bu sefer karsınıza çıkan pencerede Path isimli degiskeni göreceksiniz. Bu degiskeni seçip Düzenle (Edit) dügmesine

basarak eklemek istediginiz yeni dizini karsınıza çıkan söz diziminin en sonuna önce bir noktalı virgül (;) koyarak

yazınız ve degisiklikleri kaydederek sisteminizi yeniden baslatınız. Bundan sonra artık java komutlarını rahatlıkla

kullanabiliriz. (Buradaki örnekte sanal makinanın yer aldıgı dizin C:\jdk1.4\bin olarak kullanılmaktadır. Bu bilgi sizin

makinanızda farklı olabilir)

Linux kullanıcıları için:

Bir terminal içerisinde PATH degiskenine asagıda gösterildigi gibi java sanal makinasının yer aldıgı dizini ekleyiniz ve

asagıdaki gibi export komutu ile bu degiskeni yeni degeri ile tüm kabuklar için kullanıma hazır hale getiriniz

(Buradaki örnekte sanal makinanın yer aldıgı dizin /usr/local/jdk1.4/bin olarak kullanılmaktadır. Bu bilgi sizin

makinanızda farklı olabilir) :

$ PATH=$PATH:/usr/local/jdk1.4/bin

[academytech@localhost academytech]$ export PATH

Simdi de degiskenin yeni degerini alıp almadıgını kontrol edelim:

$ echo $PATH

/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/academytech/bin:/usr/local/jdk1.4/bin/

Gördügümüz gibi çıktının en sonunda bizim ekledigimiz yeni dizin de yer almaktadır. Bu çıkıs bize islemi düzgün

yaptıgımızı anlatmaktadır. Ancak sunu da eklemek gerekir ki linux altında yapılan bu ayar sadece o andaki oturum

için geçerlidir. Bu bilginin kalıcı olmasını istiyorsanız home dizininizde yer alan “.bash_profile” dosyası içerisine su

satırı ekleyin:

PATH=$PATH:/usr/local/jdk1.4/bin

Bu anlatılanları yaptıysanız artık sistem içerisinde hangi dizinde olursanız olun java sanal makinanıza ait komutları

dogrudan kullanabileceksiniz.

Java ile Uygulamaya Giris

1lk ayarları ve kurulumu tamamladıgımıza göre artık en temel java uygulamamızı yazalım ve çalıstıralım. Bu

uygulama kullanıcıya asagıdaki gibi bir mesaj penceresi çıkaracaktır:

7

Resim 4:

 

 

Ornek 1 ile yazılan uygulama sonunda ekrana gelecek olan mesaj penceresi

Herhangi bir editorde asagıdaki kodu yazarak “Mesaj.java” adıyla kaydediniz:

import javax.swing.*;

import java.awt.*;

public class Mesaj { //1. satır

public Mesaj() { //2. satır

JOptionPane.showMessageDialog(null, "java ile hayat guzel ");

}

public static void main(String[] args) { //3. satır

Mesaj A = new Mesaj();

System.exit(0);

}

}

Simdi de komut satırında önce bu dosyayı kaydettiginiz klasöre gidiniz (bu örnekte bu klasör c:\temp olarak

yaratılmıstır) ve asagıdaki gibi önce “javac Mesaj.java” yazıp enter tusuna basın. Bunu yaptıgınızda bilgisayar kısa

bir süre yazdıgınız kodu jvm’nin anlayacagı sekilde derleyecektir. Daha sonra da yine komut satırında “java

Mesaj.java” yazıp enter tusuna basın. Bu sefer de jvm derlenmis dosyayı çalıstıracaktır:

C:\temp> javac Mesaj.java

C:\temp> java Mesaj

Not:

 

 

Linux altında da bu uygulamayı ve bundan sonra gösterecegimiz uygulamaları aynı sekilde çalıstırabilirsiniz.

Bir java uygulaması en temel sekilde böyle çalıstırılmaktadır. Bu islem linux isletim sistemi altında da

degismeyecektir. Programımıza kısaca bir göz atalım:

lk satırlarda

 

 

yer alan “import javax.swing.*” ve “import java.awt.*” bildirimleri kullanacagım nesnelerin tanımlı

oldugu paketleri program içerisinde de erisebilir hale getirmektedir. Eger bu satırlar yazılmasaydı program,

gördügümüz mesaj penceresinin olusmasını saglayan JOptionPane adındaki sınıf nesnesini tanımayacak ve bu

nesneyi bulamadıgına dair bir hata verecekti. Bu yüzden kullandıgınız nesnelerin hangi kütühanelerde oldugunuz

bilmeniz ve programın en basında import anahtar sözcügü ile koda dahil etmeniz gerekmektedir.

Yazdıgınız java uygulaması da kendi basına bir sınıf nesnesidir ve bu nesne adı ile (bakınız: Mesaj.java - 1. satır)

dosya ismi aynı olmak zorundadır. Aksi takdirde programınız düzgün bir sekilde derlenmeyecek ve dolayısı ile

çalısmayacaktır.

kinci satırda

 

 

“public Mesaj()” seklinde bir metod tanımlandıgını görüyoruz. Nesne ismi ile aynı isme sahip olan

bu özel metodlara “baslangıç metodları” (constructor) denilmektedir. Yazılan her java programı bir sınıf nesnesi

olduguna göre bu nesneyi kullanmak için önce bu nesne türünden bir degisken yaratmak gerekir. 1ste bu degisken

yaratıldıgı anda bu özel metodlar otomatik olarak çagrılırlar. Baslangıç metodlarıyla ilgili ayrıntılı bilgiyi daha sonra

ögrenecegiz.

8

Üçüncü satırda

 

 

yer alan ve “main” adıyla tanımlanmıs metod ise yine özel olarak programın çalıstırıldıgı ilk

metoddur. Burada yukarıda bahsettigim nesne yaratma islemi yapılmaktadır. Daha genel söylemek gerekirse;

yazdıgınız programın çalısabilmesi için, temel programın main metodu içerisinde yazılması gerekir. Biz burada,

“Mesaj” sınıf nesnesini eger main metodu içerisinde kullanmasaydık program yine derlenecekti ancak hiç bir sey

çalısmayacaktı. Fakat bu örnekte yazdıgımız nesne main metodu içerisinde yaratıldı ve yaratıldıgı anda bu nesnenin

baslangıç metodu otomatik olarak çagrıldı. Bu çagrım neticesinde de ekrana bir mesaj penceresi çıkmıs oldu. Her ne

kadar daha önce java ile çalısmamıs olan arkadaslar için main metodunun nesne içindeki bu kullanımı biraz tuhaf

gelse de, alısıldıgında ne kadar basit ve anlamlı oldugu anlasılacaktır .

Amacımız su an için sadece bir giris yapmak oldugundan main metoduna aktarılan parametre yapısı ve bundan

sonraki örneklerde de göreceginiz “public”, “private” gibi anahtar sözcüklerin kullanımı hakkında burada hemen bilgi

vermeyecegim. Simdilik sadece kullandıgım nesnelerin nasıl yazıldıgı ve ilerki konularda da görecegimiz sekilde nasıl

ele alındıgını ve ayrıca nesneler arasındaki hiyerarsinin nasıl saglandıgını incelemenizin daha faydalı olacagını

düsünüyorum.

Örnek 1’de adı messageDialog olan sadece bir tane nesne kullandık. Bu nesneyi göstermek için JOptionPane

sınıfında yer alan showMessageDialog metodunu, mesaj penceresinde görülmesini istedigimiz yazıyı parametre

olarak girerek çagırdık.

pucu:

 

 

Bir java uygulamasını tek bir tıklama islemi ile çalıstırmak da mümkündür. Bunun için windows altında

asagıdaki gibi bir dosyayı “uygulama.bat” adıyla kaydedersiniz dosya üzerine tıkladıgınızda uygulamanız direk olarak

çalısacaktır:

/*---

 

 

uygulama.bat ---*/

javac Mesaj.java

java Mesaj

/*--------------------*/

Aynı islemi linux altında yapmak için uygulama.sh adında bir dosya içerisine yukarıdaki satırların aynısını yazarak

dosyayı kaydediniz ve konsol üzerinde bu dosyaya asagıdaki gibi çalıstırma izni vererek dosyayı çalıstırınız:

$ chmod 700 uygulama.sh

$ ./uygulama.sh

Nesne Kavramı ve Sınıf Nesnelerinin Tasarımı

Java'da her sey bir nesnedir. Nesneler sınıf denilen yapılar ile meydana getirilir. Her nesne kendisine ait bazı

bilgileri barındırmaktadır. Bu bilgiler nesneye iliskin çesitli degiskenler, nesne ile ilgili bazı isleri yapacak çesitli

fonnksiyonlar ve sabitlerdir. Ayrıca yine bir nesne içerisinde nesnenin kullanacagı baska nesneler de olabilir.

Buradan da anlıyoruz ki aslında bir sınıf nesnesi birden fazla veri tipinin bir arada bulundugu ve belli bir isi yapmaya

yönelik hazırlanan birlesik bir yapıdır.

Bir sınıf nesnesi yaratılırken degismeyen bazı kurallar vardır. Bu kurallar neticesinde siz de kendinize ait sınıflar

yaratabilirsiniz. Simdi temel olarak bir sınıf nesnesinin nasıl yaratıldıgına bakalım:

public class Kitap {

String kitap_adi;

String yazar_adi;

int sayfa_sayisi;

float ucret;

...

float ucretiSoyle() {

....

}

void ucretiDegistir(float yeni_ucret) {

....

9

}

}

Bu örnekte de görüldügü gibi bir sınıf nesnesi yaratırken “class” anahtar sözcügünü kullanmaktayız. Nesnemizin

tamamı, class anahtar sözcügü ile onu takip eden ve bizim verecegimiz isimden sonra açılan küme parantezi ile en

sonda kapatılan küme parantezi içerisine yazılmaktadır. Nesne yaratılırken ilk kullanılan “public” anahtar sözcügü

nesnenin baska nesneler içerisinde de dogrudan kullanılabilecegini belirtmektedir. Bu anahtar sözcük gibi nesnenin

dogrudan kullanılamayacagını belirtebileceginiz “private” anahtar sözcügü de mevcuttur. Bunu dısında yeri geldikçe

kullanılabilecek baska anahtar sözcüklerin oldugunu da belirtmeliyim. Ancak su anda yolumuza sadece bu bilgilerle

devam etmek daha verimli olacaktır.

Gördügümüz gibi Kitap isimli sınıf nesnemizin içerisinde “kitap_adi”, “yazar_adi” gibi degiskenler yer almaktadır. Bu

degiskenlere sınıf degiskenleri denilir ve nesnenin özelliklerini meydana getirirler. Bu özellikler her Kitap nesnesi için

degisecektir ancak her Kitap nesnesi, degerleri farklı olsa bile bu özelliklere sahip olacaktır. Ayrıca yine nesnemiz

içerisinde bu degiskenlere ek olarak bazı metodların yazılabilecegini de görmekteyiz. Java'da “metod” olarak

isimlendirilen kavramlar C ya da C++ programlama dillerindeki “fonksiyon” kavramı ile aynı seyi anlatmaktadır.

Metodlar sayesinde belirli islerin tek seferde yapılmasını saglayabiliriz. Mesela bu örnek sınıf nesnesini kullanırken

sınıf degiskenleri içerisine sırasıyla kitap adını, yazar adını ve kitabın ücretini yükledigimizi kabul edelim. Bundan

sonra herhangi bir anda kitabın ücretini ögrenmek istedigimizde önce hangi degiskenler oldugunu, hangi

degiskende aslında kitap ücretinin yer aldıgını ögrenmek yerine bu isi bizim için yapıp bize sadece sonucu üretecek

bir metod yazmak daha akıllıca olacaktır. Bu amaçla yazdıgımız “ucretiSoyle” isimli metodu çagırısak isimizi kısa

yoldan halletmis oluruz.

Metodların yazımı ve kullanımına iliskin daha ayrıntılı teknik bilgileri ilerleyen sayfalarda verecegim. Burada sadece

kavram olarak metodları anlamak konuyu kavramak açısından yeterli olacaktır. Sonuç itibariyle yazılan bu sınıf

metodları bu sınıf nesnesi ile yapılabilecek operasyonları tanımlar.

Yazım Kuralları Üzerine Bir Not

Bir uygulama yazarken dikkat edilmesi gereken önemli konulardan birtanesi de yazım kurallarıdır. Aslında burada

bahsedecegim bu kuralların bazılarına uymak bir zorunluluk olmasa da ileride iyi bir programcının sahip olması

gereken alıskanlıkları edinmenize yardımcı olur.

Parantezlere Dikkat

Bahsedilebilecek ilk kural parantezlere dikkat etmeniz gerektigidir. Sınıf nesnesini yaratırken açılan parantezi hemen

aynı anda kapatıp daha sonra bu iki parantezin arasına yazmaya baslamanız, açılan bir parantezi kapatmayı

hatırlama zorunlulugunu ortadan kaldırır ve hata yapma riskinizi azaltır.

simlendirme

1kinci kural olarak isimlendirmeden bahsedilebilir. Java'da sınıf nesneleri genellikle büyük harfle isimlendirilir. Ayrıca

aslında yazılan her .java dosyasının bir sınıf nesnesi oldugunu da unutmamalıyız. Bir .java dosyasında baska sınıf

nesneleri de olabilir ancak bunlardan bir tanesi asıl nesnedir ve diger nesneler bu ana sınıf nesnesi tarafından

kullanılır. Dosya ismi de bu sınıf nesnesi ile aynı isimde olmak zorundadır. Metodların isimlendirilmesi, ilk harf küçük

harf, diger kelimelerin de ilk kelimeye bitisik ve ilk harflerinin büyük harf seklinde yazılması kuralına uymakta yarar

vardır. Örnegimizde yer alan ucretiSoyle ve ucretiDegistir isimli metodlarda bu kurala uydugumuzu görmekteyiz.

Degiskenlerin isimlendirilmesi küçük harflerle yapılmaktadır.

Kodlamada Girintiler (Indentation)

Son olarak bahsedilebilecek kural ise kod yazımı sırasında kullanılan girintilerdir. Dikkat ederseniz yukarıdaki

örnekte ilk satırda açılan parantezden sonra diger bütün bilgileri bir tab içeriden yazdım. Daha sonra metodlara

iliskin parantezleri de açtıktan hemen sonra yazılı kodları temsil eden üç noktayı da (...) yine bir tab içeriden

yazdım. Böylece hangi kodların hangi faliyet alanına ait olduklarını daha net bir sekilde görebiliyorum.

Yukarıda bahsedilen bu kurallara uymak, bize yazdıgımız kodu daha sonra kolaylıkla anlama sansı saglar. Ayrıca

yardım almak ya da rapor vermek amacıyla kodu inceleyen baska kisiler de bu isi daha rahat yapabilirler. Bu amaçla

bu kurallara özen göstermenizi tavsiye ederim.

10

Simdi su ana kadar edinmis oldugumuz bilgiler ısıgında bir örnek daha yazalım. Bu örnegimizde bir tane Kitap isimli

sınıf nesnesi yazıp bu nesne türünden iki farklı degisken yaratacagım. Daha sonra da bu degiskenlerin sahip

oldukları özellikleri inceleyecegim.

public class Kitap {

String kitap_adi;

String yazar_adi;

int sayfa_sayisi;

public int sayfaSayisiniVer() {

return sayfa_sayisi;

}

public void kitabiGoruntule() {

System.out.println("\nRapor");

System.out.println("********");

System.out.println("Kitap Adi: " + kitap_adi);

System.out.println("Yazari: " + yazar_adi);

System.out.println("Sayfa Sayisi: " + sayfa_sayisi);

System.out.println("\n");

}

public static void main(String[] args) {

Kitap kitap1 = new Kitap();

Kitap kitap2 = new Kitap();

kitap1.kitap_adi = "Puslu Kitalar Atlasi";

kitap1.sayfa_sayisi = 238;

kitap1.yazar_adi = "Ihsan Oktay Anar";

kitap2.kitap_adi = "Vadideki Zambak";

kitap2.sayfa_sayisi = 307;

kitap2.yazar_adi = "Balzac";

kitap1.kitabiGoruntule();

kitap2.kitabiGoruntule();

}

}

Daha öncede anlatıldıgı sekilde kodu yazıp çalıstırdıgınızda asagıdaki gibi bir çıkıs alacaksınız:

Rapor

********

Kitap Adi: Puslu Kitalar Atlasi

Yazari: Ihsan Oktay Anar

Sayfa Sayisi: 238

Rapor

********

Kitap Adi: Vadideki Zambak

Yazari: Balzac

Sayfa Sayisi: 307

Simdi gelin neler oldugunu inceleyelim: Örnek programımızda daha önce de dedigimiz gibi Kitap isimli sınıf

nesnesini çesitli degiskenleri ve metodlarıyla yarattık. Aynı zamanda nesne içerisine yazdıgımız main metodu

sayesinde de programımız derlendi ve çalıstırıldı. Sunu hatırlatmakta fayda var: Bir sınıf nesnesi yazılıp

derlendiginde aslında çalısmaz. Sadece o nesne kullanılabilir durumdadır. Bir java programının çalısması demek

11

aslında sadece main metodunun çalısması demektir. Bu örnekte de Kitap isimli sınıf nesnesini yine Kitap sınıf

nesnesi içerisinde yazdıgımız main metodu içerisinde kullanıyoruz.

Bu kullanımda Kitap nesnesi türünden iki farklı degisken yaratıyoruz. Bunun anlamı bu iki farklı degiskenin kendine

ait olan ama aynı niteliklerde degisken ve metodları oldugudur. Daha farklı bir deyisle; aslında kitap1 degiskeninde

de kitap2 degiskeninde de kitap_adi isimli bir String türünden degisken vardır ancak içerdikleri degerler farklı

olabilir. Zaten main metodunun son iki satırında da kitap1.kitabiGoruntule() ve kitap2.kitabiGoruntule()

metodlarının üretecekleri degerler her iki degisken için farklı olacaktır. Ancak her iki degisken de aslında bir Kitap

nesnesi oldugundan kendilerine ait bir kitabiGoruntule() metoduna sahipler demektir.

Buradan çıkaracagımız sonuç sınıf nesneleri aslında birer modeldir ve bu nesneler türünden yaratılan degiskenler de

bu modelin birer örnegidir.

Bugünkü çalısmamızı burada noktalıyoruz. Yukarıda anlatılan nesne kavramları, sınıf nesnesi tasarımı ve metodlara

iliskin açıklamaları aslında sadece iyi bir giris yapabilmeniz amacıyla inceledik. 1lerleyen dersler boyunca bu konuları

tek tek kendi içlerinde detaylandıracagız.

Degisken Kavramı

Tüm programlama dillerinde oldugu gibi Java'da da degiskenler kullanılmaktadır. Degisken; program yazılması

sırasında, içerisinde birtakım degerleri tutan ve kendine ait bir türü olan yapıdır. Bir degiskenin içerisinde tuttugu

deger, program akısı sırasında degistirilebilir. Ayrıca her degiskenin bir türü vardır ve degiskenlerin içlerinde

tuttukları bu degerler de aynı türden olmalıdır.

Kullanılmadan önce degiskenlerin özellikleri hakkında derleyiciye bilgi verilmesi islemine “bildirim” denir. Bir

degisken nesnesi su özelliklere sahip olur:

degisken ismi

degisken türü

degisken içerisindeki deger

degiskenin faliyet alanı

Degisken simlendirme

Degisken ismi, degisken nesneyi temsil eden karakterlerdir. Bu isim belli kurallar dahilinde verilmektedir. Bu

kurallar kısaca söyle açıklanabilir:

degisken isimlerinde bosluk olmamalıdır,

sayfa sayisi -> yanlis

sayfa_sayisi -> dogru

sayfaSayisi -> dogru

degisken isimlendirmede türkçe karakterler kullanılmamalıdır,

ÖzelDegisken -> yanlis

OzelDegisken -> dogru

Degiskenin türü

 

aslında içerisinde tutacagı degerin özelligidir. Mesela içerisinde tamsayı degerleri tutan bir

degisken ile ondalık sayı degerleri tutan degisken aynı türden degildir.

Bir degiskenin içerisinde degerler saklanarak aktarılır ve kullanılırlar. Degiskenler içerisinde saklanan degerlerin de

bir türe iliskin olduklarını ve içlerinde saklanacak degiskenin türü ile aynı türden olmak zorunda olduklarını

unutmayınız. Asagıdaki örnekte integer türünden bir degisken yaratıp içerisinde de 200 sayisini saklayacagız:

public class Degisken {

public static void main(String arg[]) {

int a = 200;

12

System.out.println("a degiskeninin sakladigi deger: " + a + " degeridir");

}

}

Bu kodu yazdıktan sonra daha önceki derslerimizde gösterdigimiz gibi çalıstırınız:

Kodun çalısması sonucunda ekranda su yazıyı göreceksiniz:

a degiskeninin sakladigi deger: 200 degeridir

Java’da “primitive type” denilen degisken türleri vardır. Bu türlere biz ilkel ya da temel türler diyoruz. Daha sonraki

derselerimizde görecegiz ki temel türlerin dısında bir de nesnel türler vardır.

Kullanılan temel veri tiplerini inceleyelim:

Sayısal Veri Tipi Hafızada kapladıgı alan (byte) Sınırları

int 4 -2.147.483.648, +2.147.483.647

short 2 -32.768, +32.767

long 8 -9.223.372.036.854.775.808L ,

+8.223.372.036.854.775.807L

byte 1 -128, 127

float 4 -+ 3.40282347E+38F

double 8 -+ 1.79769313486231570E+308

Ön Eklere liskin NOT:

 

Yukarıdaki tabloda görüldügü gibi bazı veri tiplerinin sonuna F ve L gibi ekler getirilmistir.

Bunun nedeni bu veri tiplerinin eklerle birlikte ifade edilmesidir. Bu durum tür bilgilerinin birbirine karısmasını

engeller.

Sayısal Olmayan Veri Tipleri

Yukarıdaki tabloda incelemis oldugumuz veri tipleri sayısal bilgiyi ifade etmek için kullanaılır. Sayısal olmayan bilgiyi

ifade etmek için kullanılan veri tipleri de vardır. Simdi bunları incleyelim:

“char” Veri Tipi:

char veri tipi karakterleri temsil etmek amacıyla kullanılır. Bir karakter klavye ile sisteme tek tus ya da birkaç tus

kombinasyonu ile ama tek seferde girdigimiz sembollerdir.

Hafızada 2 byte yer kaplarlar.

Karakter Kümeleri ve Unicode

Aslında tüm dillerdeki sembolleri içine alan en geis karakter kümesi Unicode karakter kümesidir. Bu küme içerisinde

kullanılabilecek tüm karakterler yer alır ve her karakter hexadecimal olarak ifade edilir. 65536 tane karakteri

içerecek genislige sahiptir. Ancak halihazırda 35000 karakter kullanır.

\u0008 (backspace), \u0009 (tab) gibi...

ASCII karakter kümesi aslında Unicode karakter kümesinin bir alt kümesidir ve ASCII karakterleri 128 tanedir.

Hafızada 1 byte yer kaplarlar.

Bunun dısında bildigimiz ISO8859-9 (latin-5) gibi karakter kümeleri ASCII nin uzantıları olup aslında yine unicode

karakter kümesinin bir alt kümesidir.

13

“boolean Veri Tipi:

Bu veri tipi mantıksal bilgiyi ifade eder ve alacagı deger true ya da false olabilir. Bu degerler ileride görecegimiz

mantıksal operatörler içerisinde ve if, while, for gibi deyim ve döngüler içerisinde kullanılabilir.

Degisken Bildirimi:

Degisken bildiriminde, ilk önce bu degiskenin içerisinde tutacagı degerlerin hangi türden olacagı ve degiskenin

hangi isimle anılacagı bildirilir.

Örnegin:

int a;

double benim_degiskenim;

String isim;

System.out.println() metodu üzerine bir not:

Bu metod java tarafından tanınan ve daha önce yazılmıs bir metoddur. Bu metodu kullanırken parantezler içerisine

yazılan (parametre olarak yazılan) degisken ve sabitler ekranda görüntülenir. Eger parantez içerisine bir degisken

yazılmıs ise bu degiskenin içerisindeki deger ekrana yazılacaktır. Ayrıca + operatörü yardımıyla parantez içerisine

birden fazla tür yanyana yazilabilir. Örnegin:

Degiskenler.java

public class Degiskenler {

public static void main(String arg[]) {

int a; //satır 1

a = 200; //satır 2

int b, c; //satır 3

b = 100; //satır 4

c = 400; //satır 5

int d = 0; //satır 6

System.out.println("a nin degeri: " + a);

System.out.println("a nin degeri: " + a + " b nin degeri: " + b);

d = a + b + c;

System.out.println("Toplam deger: " + d);

}

}

Program çalıstıgında sunu göreceksiniz:

a nin degeri: 200

a nin degeri: 200 b nin degeri: 100

Toplam deger: 700

Bu örnekte aslında degisken bildirimine iliskin farklı yöntemleri görmekteyiz. Bir degisken satır 1'de oldugu gibi ilk

önce yaratılıp daha sonra satır 2'de oldugu gibi içerisine deger verilebilir. Ya da satır 6'da oldugu gibi aynı anda

yaratılıp ilk deger verilir. Bunun yanı sıra virgül kullanılarak aynı türe iliskin olmak üzere satır 3'de oldugu gibi tek

satırda birden fazla degisken yaratılabilir. Bu örnekte aynı zamanda System.out.println metodunun kullanımını

görmekteyiz.

Özel Karakterler liskin Bir Not:

C ve C++ programla dillerinde de oldugu gibi Java'da klavyeden girilen bir takım özel karakterlerin karsılıgı vardır.

Bu özel karakterler bip sesi, enter tusu, alt satır bası, tab tusu gibi karakterlerdir. Bu karakterler kullanılırken

baslarına \ isareti koyulur ve uygun sembol yerlestirilir. Buna göre:

\n : alt satır basına

\t : tab tusu

\\ : \ isareti

14

\” : “ isareti

\b : backspace (bir önceki karakteri silme)

\r : kendisinden önce gelen tüm karakterleri satır basına kadar silme

anlamına gelmektedir.

Simdi kullanıcıdan bir takım bilgileri alan ve daha sonra bu bilgileri ekranda gösteren bir program yazalım. Bu

program çalıstıgında Resim 6'daki gibi JOptionPane sınıfının showInputDialog isimli metodu yardımıyla meydana

gelen bir pencere aracılıgıyla bilgiler kullanıcıdan istenecek ve sonra bundan önceki dersimizde de gördügümüz

JOptionPane sınıfının showMessageDialog isimli metodunun meydana getirdigi mesaj penceresi aracılıgıyla girilen

bilgiler ekranda tekrar gösterilecektir.

Programımızı yazalım:

simGir.java

import javax.swing.*; //s1

public class IsimGir {

public static void main(String arg[]) {

String isim, yas; //s2

isim = JOptionPane.showInputDialog(null, "Lutfen isminizi giriniz: "); //s3

yas = JOptionPane.showInputDialog(null, "Simdi de yasiniz giriniz: "); //s4

String rapor = "Adiniz: "+isim+"\nYasiniz: "+yas; //s5

JOptionPane.showMessageDialog(null, rapor); //s6

//JOptionPane.showMessageDialog(null, "Adiniz:\t"+isim+"\nYasiniz:\t"+yas);s7

System.exit(0);

}

}

Bu örnekte görüldügü gibi ilk olarak kullanıcının girecegi bilgilerin tutulacagı degiskenler s2'de yaratılmaktadır. Eger

bu degiskenler olmazsa kullanıcının girecegi bilgiler bir yerde saklanamayacagı için kullanılamazdı. Daha sonra s3 ve

s4'de JOptionPane.showInputDialog() metodu yardımıyla ekranda giris yapılacak olan input dialog penceresi

çıkartılmaktadır. Ancak bu metodun özelligi, çagrıldıktan sonra geriye, kendisine girilen yazıyı deger olarak üretir ve

bu deger s3 ve s4'de sırasıyla isim ve yas degiskenlerine aktarılmıstır. s5'de ekranda en son bilgilerin gösterilecegi

pencereye yazılacak olan yazı hazırlanmıs ve rapor isimli degiskene aktarılmıstır. Daha sonra String türündeki bu

rapor degiskeni JOptionPane.showMessageDialog() metoduna parametre olarak gönderilerek mesaj penceresi

hazırlanmıstır. Aynı sekilde ekranda belirecek mesaj, s5'de oldugu gibi önceden hazırlanabilecegi gibi hemen o anda

s7'deki gibi parametre olarak da hazırlanabilir. Bu örnekte s5 ve s6 yerine sadece s7'de kullanılabilir.

Not:

 

 

Basında “//” olan satırların Java derleyicisi tarafından es geçildigini ve programın sanki bu satırlar yokmus gibi

çalısacagını hatırlayınız.

Sabitler:

Degisken nesnelerin içlerindeki degerlerin degisebileceginden bahsetmistik. Bazı durumlarda tüm program boyunca

yanlıslıkla da olsa degerinin degistirilmemesi gereken nesnelere ihtiyaç duyabiliriz. Bu talebi karsılamak için sabitler

kullanılmaktadır. Sabitlerin bildirimi aynen degisken bildiriminde oldugu gibidir ancak tek fark sabitlerin bildiriminin

basına final anahtar sözcügü getirilmesidir:

Sabitler.java

public class Sabitler {

public static void main(String arg[]) {

15

final double BIRIM_UCRET = 200.5;

double sure = 2.3;

//BIRIM

 

 

_UCRET = 200.8; //s1

System.out.println(“Bu ay odeme bedeli: ” + BIRIM_UCRET * sure + “ liradir.”);

}

}

Bu örnekte gördügümüz gibi BIRIM_UCRET adında ve türü double olan bir sabit ile sure adında ve türü double olan

bir degisken tanımladık. Bu durumda siz isteseniz bile bu sabiti s1'de oldugu gibi degistiremezsiniz. Eger s1'in

basındaki // ifadesini kaldırırsanız programın hata verdigini göreceksiniz. Sonuç itibariyle sabitleri program içerisinde

bir degerle yaratıp, içerisinde hep bu degeri tutmasını garanti edebilirsiniz. Sabitin içerisinde tutacagı deger ancak

bilinçli olarak ve ilk defa verildigi yerde degistirilebilir.

Operator Kavramı ve Operatörlerin ncelenmesi:

Operatörler sayısal ya da mantıksal ifadelerin birbirleri ile isleme sokulmasını saglayan araçlardır. Program yazarken

bir çok defa hesap yapmak gerekecektir. Bu sayısal hesapların yapılabilmesi için çesitli sayısal operatörler

kullanılmaktadır. Ayrıca yine operatörler yardımıyla bazen de sayısal olmayan ve kelimelerin karsılastırılması,

esitliklerin saglanması ve bunun gibi birbirinden farklı mantıksal islemler de yapmak gerekmektedir.

Not:

 

 

Sunu kesinlikle unutmayınız ki; az sonra bazılarını ögrenecegimiz operatörler, kullanıldıkları zaman geriye

mutlaka bir deger üretirler. Üretecekleri bu degerler bir sayı, true ya da false gibi boolean bir deger veya bunun

gibi operatöre göre degisen degerler olabilir. Ama sonuçta operatörün bir deger ürettigini ve islem sonucunda

ortada sadece bu degerin kaldıgını anlamaya çalısınız. Simdi bu operatörleri inceleyelim

 

 

:

= operatoru

Bilinen en genel operatörlerden olan esitlik operatörü çift taraflı kullanılır. Sag tarafında yer alan degeri sol

taraftaki degiskene atamaya yaramaktadır. Daha önce yaptıgımız IsimGir isimli örnekte s3 ve s4'de de oldugu gibi,

bazen metodlardan gelen degerleri de degiskenlere aktarmaya yarar. Aslında mantık hep aynıdır. Sagdaki deger

soldaki degiskene aktarılır. Bu operatör kullanıldıgında, ilk once sag taraf hesaplanmaktadır.

+, -, *, / operatorleri:

Bu operatörler klasik matematik islemlerinin hesabında kullanılmaktadır. Ancak istisna olarak + operatorünün daha

önce de gördügümüz IsimGir örnegindeki s5'de oldugu gibi Stringleri birbirleri ile ya da String ve degiskenleri

birbirleri ile baglamak gibi islemlerde de kullanılması mümkündür.

+=, -= /= ve *= operatörleri:

Bu operatörler birlesik operatörlerdir. Genellikle bir degiskenin degerini eski degeri ve yeni bir sabit artımının

toplamı, farkı, bölümü veya çarpımı seklinde degistirmek için kullanılır. Örnegin:

int x = 10;

x = x + 4;

isleminde x degiskeninin son degeri 14 olacaktır. Bu islem aynı sekilde += operatoru kullanılarak da yapılabilir.

Söyle ki:

int x = 10, sayi = 6;

x += 4; //x = x + 4 ile aynı anlamdadır.

sayi = sayi – 6; //sayi -= 6;

++ ve –- operatorleri:

Bu operatorlerin her ikisi de tamamen aynı mantıkta olup verinin degerini 1 artırmak ya da1 eksiltmek amacıyla

kullanılır. Ornegin x = x +1; yazmak yerine x++; yazabilirsiniz. Aynı sekilde x = x -1; yazmak yerine x--;

yazabilirsiniz.

boolean Operatörleri :

16

Daha önce de belirttigimiz gibi eger bir degisken boolean türünde ise alabilecegi sadece iki tane deger vardır. Bu

degerler “true” ya da “false” degerleridir. Bu iki degeri bilgisayar mantıgında 1 ya da 0 a benzetebiliriz.

Bu iki degeri içerisinde saklamak amacıyla kullanılan degiskenler de boolean türünden olacaktır. Bazı operatörler

kullanıldıkları zaman sonuç olarak bu iki degerden birtanesini üretirler. Bu operatörlere mantıksal operatörler denilir.

== ve != operatorleri:

Bu operatör aslında “esit mi? ” sorusunun cevabını üreten mantıksal bir operatördür. Çift taraflı olarak

kullanıldıgında sagdaki ve soldaki degerlerin esit olması durumunda “true” sonucunu üretir. Esitlik yok ise “false”

sonucu üretilecektir. Mesela 3 == 5 islemi false degerini üretir.

== operatorune benzer olan, ancak tam tersini yapan diger bir operatör de != operatörudur. Bu operatör de yine

çift taraflı olarak çalısır ve her iki tarafın birbirine esit olmaması durumunda “true”, esit olmaları durumunda da

“false” degerini üretir. Örnegin 3 != 5 islemi true degerini üretir.

&& ve || (and ve or) Operatorleri:

Bu iki operator mantık islemlerinde kullandıgımız and ve or operatörleridir. Bunlar da çift taraflı kullanılır.

&& operatoru her iki tarafındaki deger true ise true sonucunu üretecek ama sag ya da sol taraftan bir tanesi false

olması durumunda false degerini üretecektir.

|| operatoru de iki tarafındaki degerlerden en az bir tanesi true olması durumunda true degerini üretecek, her iki

tarafın da false olması durumunda false degerini üretecektir.

AnaSinif.java

import javax.swing.*;

public class AnaSinif{

public static void main(String arg[]){

boolean deger1 = true;

boolean deger2 = false;

boolean sonuc1 = deger1 && deger2;

JOptionPane.showMessageDialog(null, "deger1: " +deger1+"deger2: "+deger2+

"deger1 && deger2 ->"+ sonuc1);

boolean sonuc2 = deger1 || deger2;

JOptionPane.showMessageDialog(null, "deger1: " +deger1+"\ndeger2: "+deger2+

"\ndeger1 || deger2 -> "+ sonuc2);

deger2 = true;

sonuc1 = deger1 && deger2;

JOptionPane.showMessageDialog(null, "deger1: " +deger1+"\ndeger2: "+deger2+

"\ndeger1 && deger2 -> "+ sonuc1);

deger1 = false;

deger2 = false;

sonuc1 = deger1 || deger2;

JOptionPane.showMessageDialog(null, "deger1: " +deger1+"\ndeger2: "+deger2+

"\n\ndeger1 && deger2 -> "+ sonuc1);

}

}

>, <, >=, <= operatöleri:

Bu operatörler de çift taraflı çalısırlar ve eger sag sol degerleri gerçeklenirse true aksi taktirde false degerini

üretirler. Örnegin:

3 > 5 //false

17

4 < 10 //true

3 >= 3 //true

() Tür Dönüstürme Operatörü

Su ana kadar ögrendigimiz kadarıyla belli bir türe iliskin degerleri aynı türden degiskenler içerisinde saklıyor ve

kullanabiliyorduk. Ancak bazı durumlarda farklı türlerin birbirleriyle isleme girmeleri ve bir türe iliskin bir degerin

aynı olmayan türde bir degiskene atanması gibi islemler gerekebilir. 1ste bu gibi durumlarda bir tür dönüsümü söz

konusu olabilir.

Tür dönüsümleri de belirli kurallar dahilinde ve belirli bir hiyerarsi ile olmaktadır. Tür dönüsümleri sırasında bazen

bilgi kaybının da olabilecegini unutmamak gerekir. Bunun nedenin her türün ifade ettigi bilginin sınırlarının ve

hafızada kapladıgı alanın farklı olmasından kaynaklandıgını hatırlayınız. Asagıda bilgi legal olan tür dönüsümleri

özetlenmektedir:

byte -> short (bilgi kaybı yok)

short -> int (bilgi kaybı yok)

char -> int (bilgi kaybı yok)

int -> long, double (bilgi kaybı yok), float (bilgi kaybı olabilir)

long -> float, double (bilgi kaybı olabilir)

float -> double (bilgi kaybı yok)

Bilgi kaybı, dönüsümlerde hedef veri tipinin sınırlarının dar olmasından kaynaklanır. Mesela

int n = 123456789;

float f = n; //f in degeri 1.2345692E8 olur.

Yukarıdaki dönüsüler otomatik olarak gerçeklesen dönüsümlerdir. Ancak kasıtlı olarak da tür dönüsümü

yapılabilir.Bir degerin türünü dönüstürmek için degerin soluna parantez içerisinde degistirmek istediginiz türün adını

yazmanız gerekir.

public class AnaSinif{

public static void main(String arg[]){

double k = 12.96;

System.out.println("k nin deeri: "+ k);

int c;

c = (int)k; //burada double türünden bir deer int türünden bir degiskene

atanyor.

System.out.println("c nin degeri: "+c);

}

}

Bu örnekte gördügümüz gibi k degiskeninin içerisindeki deger c degiskenine atandıgı için c nin degerinin de 12.96

olmasını beklerdik. Ancak atama sırasında ( ) operatörü ile bir tür dönüsümü yaptık ve bilgi kaybından dolayı c nin

degeri 12 oldu. Çünkü int türünden bir degisken virgülden sonra deger alamaz.

Tür Dönüsümlerine liskin Özel Metodlar

Tür dönüsümlerini ( ) operatüörü ile yapabilecegimiz gibi bu is için yazılmıs bazı özel metodları da kullanabiliriz.

Mesela String olarak verilmis olan “12” degerini 12 sayısı gibi kullanamayız. Çünkü bu deger çift tırnak içerisinde

18

verilmistir ve bir String'dir. Yani siz bu degerle bir sayıyı toplamaya kalkarsanız sonuç da otomatik tür

dönüsümünden dolayı bir String olacaktır. Su örnege dikkat edelim:

public class AnaSinif{

public static void main(String arg[]){

String a = "12";

int b = 13;

String c = a + b;

System.out.println("Sonuc: "+c);

}

}

Gördügünüz gibi java a+b isleminin sonucunu bir String türü olarak belirlemek konusunda bizi zorlamaktadır.

Sonucu string olarak hesapladıgımzda da bu sefer cevap 25 olması gerekirken 1213 tür. Aslında bu sonuç bir sayı

degil bir Stringdir. Yani bir görüntüdür. O halde sayı gibi verilmis bir Stringi nasıl sayıya çevirecegiz? Bunun için

kullanılacak metod Integer isimli bir sınıfın parseInt() isimli metodudur. Mesela kullanıcıdan

JOptionPane.showInputDialog() metodu ile yasını isteylelim ve girdigi yas ile 3 sayısını çarpıp sonucu bulalım.

Ancak biliyoruz ki bu sekilde alınan girisler sayı olarak degil String olarak algılanıyorlar. O halde bu String'i de

Integer.parseInt() metodu yardımıyla int türüne dönüstürelim:

import javax.swing.*;

public class AnaSinif{

public static void main(String arg[]){

String yas = JOptionPane.showInputDialog(null, "Yasinizi

giriniz: ");

int sonuc = Integer.parseInt(yas) * 3;

JOptionPane.showMessageDialog(null, "Hesap sonucu: "+sonuc);

}

}

Buna benzer diger metodlar:

Integer.toString(12); --> parantez içerisinde verilen int türünü String'e çevirir.

Double.parseDouble(12); --> parantez içerisinde verilen int türünü double türüne çevirir.

Double.toString(12.45); --> parantez içerisinde verilen double türünü String'e çevirir.

Bunlar gibi daha birçok metod vardır. Bunların kullanımı yeri geldikçe dökümantasyon yardımıyla ögrenilebilir.

Stringler

Daha önce sözdizimi olarak da bahsettigimiz bu tür aslında bir karakter dizisidir. Stringler çift tırnak içerisinde yazılır

ve kendilerine ait bir takım özel metodlara sahiptir. Bu bakımdan diger türlerden biraz daha farklıdır. Burada

istenen, Stringlerin metodlara sahip oldugu kavramını vurgulamak ve gerektikçe bu metodları kullanabilecegimizi

göstermektir. Bu amaçla bütün metodlar burada anlatılmayacaktır:

“string”.length Degiskeni

Bu degisken bir stringin kaç karakterden olustugunu yani uzunlugunu verir.

“string”.equals(“diger string”) Metodu

1ki String türüne iliskin degerlerin esitligini sayısal degerlerde kulandıgımız == operatörü ile kontrol edemeyiz.

Bunun yerine String.equals metodunu kullanırız. Bu metod, kendisine parametre olarak verilen “diger string” degeri

eger “string” degerine esitse true, degilse false degerini üretir.

“string”.compareTo(“diger string”) Metodu

 

:

19

Bu metod kendisine parametre olarak verilen “diger string” ile “string” degerini kıyaslar. Eger iki string esitse metod

0 degerini, “string” büyükse 1 degerini, “diger string” büyükse de -1 degerini üretir.

import javax.swing.*;

public class AnaSinif{

public static void main(String arg[]){

String isim = JOptionPane.showInputDialog(null, "Lutfen adnizi

giriniz");

int uzunluk = isim.length;

String mesaj = "Isminiz "+uzunluk+" tane karakterden

olumaktadir";

JOptionPane.showMessageDialog(null, mesaj);

String gercekSifre = "kkVVuuNN";

String girilenSifre = JOptionPane.showInputDialog(null, "Sifreyi

giriniz: ");

boolean sonuc = gercekSifre.equals(girilenSifre);

JOptionPane.showMessageDialog(null, "Girdiiniz sifre: "+sonuc);

}

}

Yukarıdaki örnekte, JOptionPane sınıfının showInputDialog() isimli metodu yardımıyla kullanıcının klavyeden girdigi

string, isim degiskenine atılmakta ve daha sonra da girilen bu stringin uzunlugu öntanımlı isim.length degiskeni ile

alınıp uzunluk degiskenine atanmaktadır. Biz aslında length isminde bir degisken yaratmadıgımız halde, yukarıda

anlatıldıgı gibi isim degiskeni aslında bir String oldugu için, kendi bünyesinde otomatik olarak bu length degiskenini

ve diger String metodlarını barındırmaktadır. Nitekim örnekte de gördügümüz gibi; gercekSifre isimli String

degiskeni ile equals isimli öntanımlı metodu kullanarak, iki stringi birbirleriyle kıyaslayabilmekteyiz.

Vazgeçilmez Kaynagınız: Java Dökümantasyonu!

Daha önce de sık sık Java'da bir çok sınıfın kullanım amacı ile daha önceden yazılmıs olduguna ve bu sınıfların

içerisinde de, kullanabilecegimiz bir çok degisken ve metod olduguna deginmistik. Hangi sınıfların ne ise

yaradıklarını, ve içlerinde hangi metod ve degisken barındırdıklarını ve bunları nasıl kullanabilecegimizi ezbere

bilmek imkansızdır. 1ste bu yüzden, her java programcısnın vazgeçemeyecegi java dökümantasyonunu kullanmak

gerekir.

Dökümantasyonu online olarak http://java.sun.com/j2se/1.4.1/docs/api/ adresinde bulacagınızı ilk dersimizde

söylemistik.

20

Bu sayfayı açtıgınızda karsınıza üç çerçeveden olusmus bir ekran gelmektedir. Bu ekranda, sol üst kısımda “All

Classes” isimli baglantıyı tıkladıgınızda, sol at kısma Java'da öntanımlı tüm sınıfları temsil eden baglantılar

yüklenecektir. Hakkında bilgi almak istediginiz sınıf ismini bulup üzerine tıkladıgınızda da sagdaki kısma bu sınıf

hakkındaki tüm metodlar, degiskenler ve bilgiler gelecektir. Resim 7'de çok sık kullandıgımız JOptionPane isimli

sınıfın showMessageDialog isimli metoduna iliskin bölümü görmekteyiz.

Bu dökümantasyonu online olarak görüntüleyebileceginiz gibi, bilgisayarınıza indirip offline olarak da

kullanabilirsiniz. Bu islem için http://java.sun.com/j2se/1.4.1/download.html sayfasından dökümantasyonu

indirebilir ve yine aynı sayfada bulacagını kurulum talimatları ile (Installation Instructions) sisteminize

yükleyebilirsiniz.

21

Java ile Programlama

Bölüm 3:

Bundan önceki dersimizde Java programlama dilinde degiskenlerin nasıl kullanıldıklarını operatörleri ve vazgeçilmez

kaynagınız olan Java Dökümantasyonu'nu nasıl kullanacagımız ögrenmistik. Bu sayımızda isi biraz daha ileri

götürecek ve program akısını kendi istegimiz dogrultusunda yönlendirebilecegimiz deyimler ve döngüleri

ögrenecegiz.

Yeni bir dil ögrenmenin en zor yanı, dilin temel kurallarını ögrenme asamasının oldukça yogu ve sıkıc geçmesidir.

Bunun nedeni de ögrenme asamasında sınırlı bilgiyle henüz ele avuca sıgar uygulamalar gelistiremiyor olmamızdır.

Sizlerin de su asamada aynı sıkıntıyı çektiginizi tahmin ederek, motivasyonunuzu artırmak amacıyla java içerisinde

yer alan demoları göstermek istiyorum. Az sonra nasıl çalıstırabileceginizi anlatacagım bu uygulamaları inceleyerek,

ileride varacagınız noktayı görme sansına sahip olacaksınız:

Okumaktan Sıkılanlar çin

Demolar sdk ana dizini içerisinde bulunan “demo” isimli dizinde bulunmaktadır. Sdk ana dizininiz sizin java'yı ilk

yüklediginiz yerdir ve ismi de muhtemelen

 

j2sdk.1.3.1 ya da j2dk1.4.2 seklinde olacaktır. Benim linux sistemimde

ana dizinin tam yolu:

 

/opt/j2sdk_nb/j2sdk1.4.2/ seklindedir. Buradaki demo isimli dizinin içinde de, jfc ve

onunda için de SwingSet2.jar adındaki uygulamayı önce jfc dizini içerisine girerek su sekilde çalıstırabilirsiniz:

java -jar SwingSet2.jar

Bu uygulamayı dilediginiz gibi karıstırabilir hatta j2sdk dizini içerisindeki demo dizinin ve altındaki diger tüm

uygulamaları da inceleyebilirsiniz.

Java'da Deyim ve Döngüler:

Program yazarken, yazdıgımız kodların yukarıdan asagıya dogru sırasıyla çalıstırıldıgını biliyoruz. Ancak bazen bu

kodların bu sırada degil de belirli sartlara baglı olarak birkaç satırın atlanıp ileriden devam edilmesi ya da aynı

satırların birden fazla sayıda çalıstırılması gibi isteklerimiz olabilir. 1ste bunun için kullnacagımız bazı deyimler ve

döngüler vardır. Bu deyim ve döngüler sayesinde normalde her satırdan bir defa geçen ve yukarıdan baslayarak

asagı satırlara dogru ilerleyen program akısını, bazı satırları belli durumlarda okumadan, ya da bazı satırları birden

fazla defa okuyacak sekilde yönlendirmemiz mümkün hale gelir.

Ancak bu deyim ve döngülerin daha iyi anlasılması açısından öncelikle faliyet alanı kavramına deginmekte yarar

var.

22

Faliyet Alanı Nedir Ne se Yarar?

Faliyet alanı, yazdıgımız program içerisinde belirli bölgeleri temsil eden ve nesnelerin etkin oldugu sınırları belirleyen

alanlardır. Bir nesnenin etkin oldugu bölgeye, o nesnenin “faliyet alanı” denilmektedir.

Faliyet alanı kod içerisinde { ve } ile belirlenmektedir. Bu iki parantez arasında mevcur bir faliyet alanı vardır. Bir

degisken eger { ve } arasında tanımlanmıssa bu degisken bu iki parantez dısında kullanılamaz. Buna göre

degiskenin faliyet alanı da bu iki parantez içerisinde ya da yaratıldıgı alan içerisinde sınırlıdır.

/**** Main.java ****/

import javax.swing.*;

class Main {

public static void main(String[] args) {

int k = 10;

{

int c = 20;

JOptionPane.showMessageDialog(null, "k nin degeri: "+k+

"\nc nin degeri: "+c);

}

System.exit(0);

}

}

/*******************/

Bu örnekte iki tane faliyet alanı görmekteyiz. Birinci faliyet alanı sınıfımızın kendisidir ve sınıf adı Main yazıldıktan

hemen sonra { ile açılmıs ve tüm satırlardan sonra da } ile kapatılmıstır. Bu faliyet alanının içinde de k degiskeni

tanımlandıktan sonra yine { ile baska bir faliyet alanı açılmıs ve bu yeni faliyet alanında da sadece c degiskeni

yaratılmıstır. Ancak dikkat ederseniz bu örnekte, sınıfın faliyet alanı, içeride açılan faliyet alanını kapsamaktadır. Bu

yüzden k degiskeni tanımlanmamıs oldugu içerideki faliyet alanı içerisinde de kullanılabilir. Ancak tersi mümkün

degildir. Yani c degiskenini

 

k'nin tanımlı oldugu faliyet alanında kullanmaya kalksaydık hata

mesajı alacaktık.

/**** Main2.java ****/

import javax.swing.*;

class Main2 {

public static void main(String[] args) {

int k = 10;

{

int c = 20;

}

JOptionPane.showMessageDialog(null, "k nin degeri: "+k+

"\nc nin degeri: "+c);

/*c degiskeni bu faliyet alanında tanımlı degildir*/

System.exit(0);

}

}

//bu program çalısmayacaktır

/*******************/

23

Faliyet alanına iliskin unutulmaması gereken bir sey daha vardır: Aynı faliyet alanı içerisinde, aynı isimli birden fazla

degisken tanımlanamaz. Bu örnekte k nın faliyet alanı, c nin faliyet alanını da kapsadıgından, c nin tanımlandıgı

yerde k adında baska bir degisken daha tanımlayamazsınız. Çünkü baska faliyet alanı olsa da, içerideki faliyet

alanında yukarıda tanımlanan k degiskeni hala geçerlidir. Buna dikkat ediniz.

Faliyet alanına iliskin bu bilgilerle artık deyim ve döngüleri inceleyebiliriz.

if Deyimi:

if deyimi belli bir sart saglanması durumunda program akısını kendi faliyet alanı içerisine yönlendirir. Kendi faliyet

alanının en son satırına kadar kodları çalıstırır ve daha sonra da program akısı if deyiminin faliyet alanının bittigi

yerden devam eder.

/***** Deyimler1.java ********/

import javax.swing.*;

class Deyimler1 {

public static void main(String[] args) {

String notStr;

int not;

notStr = JOptionPane.showInputDialog(null, "Notunuzu giriniz: ");

not = Integer.parseInt(notStr);

if(not > 50) {

JOptionPane.showMessageDialog(null, "Tebrikler. Bu dersten gectiniz ");

24

}

System.exit(0);

}

}

/**********************/

Daha teknik söylemek gerekirse, sartın saglanması demek, aslında if deyiminin kontrol parantezleri içerisindeki

ifadenin true olması demektir. (Bundan önceki sayıda anlattıgımız, “boolean türü ve boolean operatörleri” konusunu

hatırlayınız!). Aynı sekilde bu sartın saglanmaması ise ifadenin false degerini üretmesi anlamına gelir. Yukarıdaki

örnekte not > 50 ifadesi eger false olursa ekrana hiç bir mesaj gelmeyecektir. Ancak true olursa “Tebrikler. Bu

dersten geçtiniz” mesajını alırsınız. Burada girdiginiz notun aslında bir String türünde oldugunu ve bu degerin

Integer sınıfının parseInt metoduyla sonradan integer türüne dönüstürlüp kullanıldıgına dikkat ediniz. (Bundan

önceki sayıda yer alan “Tür Dönüsümlerine 1liskin Özel Metodlar” konusunu hatırlayınız.)

Peki ya eger kullanıcı notu 50'den küçük olsa da bir mesaj almak istiyorsa ne yapacak. 1ste bu durumda

.....

if(ifade) {

....

}

else {

....

}

kalıbını kullanmak gerekecektir. Bu kalıba göre program akısı, eger if içerisindeki ifade true ise if deyiminin, degilse

else deyiminin faliyet alanı içerisine yönlencektir. Az önceki örnegi genellestirelim:

/***** Deyimler2.java ********/

import javax.swing.*;

class Deyimler2 {

public static void main(String[] args) {

String gectiMesaji = “Tebrikler! Bu dersten gectiniz!”;

String kaldiMesaji = “Malesef bu dersten kaldiniz.”;

String notStr;

int not;

notStr = JOptionPane.showInputDialog(null, "Notunuzu giriniz: ");

not = Integer.parseInt(notStr);

if(not > 50) {

JOptionPane.showMessageDialog(null, gectiMesaji);

}

else {

JOptionPane.showMessageDialog(null, kaldiMesaji);

}

System.exit(0);

}

}

/**********************/

Aktif olarak projelerde çalıstıgınız zaman kullanıcı isteklerinin bitmedigini göreceksiniz Diyelim ki bu sefer de

kullanıcı programa girdigi nota göre bir harf ile derecesini ögrenmek istiyor olsun. Bu durumda girilen not belli

aralıklara göre belli dereceler alacaktır ve bu dereceler 2 taneden fazla olabilir. O zaman da if else kalıbı ise

yaramayacaktır. Bu durumlarda if, else if, else if, .... , else kalıbını kullanmak gerekir. Örnegi inceleyiniz

 

:

25

/****** Deyimler3.java ******/

import javax.swing.*;

class Deyimler3 {

public static void main(String[] args) {

String kaldiMesaji = "Dereceniz F: Bu dersten kaldiniz.";

String yanlisNot = "Yanlis not girisi! Tekrar deneyiniz.";

String notStr;

int not;

notStr = JOptionPane.showInputDialog(null, "Notunuzu giriniz: ");

not = Integer.parseInt(notStr);

if(not > 100 || not < 0) {

JOptionPane.showMessageDialog(null, yanlisNot );

}

else if(not <= 100 && not > 86) {

JOptionPane.showMessageDialog(null, "Dereceniz: A");

}

else if(not <= 85 && not > 71) {

JOptionPane.showMessageDialog(null, "Dereceniz: B");

}

else if(not <= 70 && not > 66 ) {

JOptionPane.showMessageDialog(null, "Dereceniz: C");

}

else if(not <= 65 && not > 50) {

JOptionPane.showMessageDialog(null, "Dereceniz: D");

}

else {

JOptionPane.showMessageDialog(null, kaldiMesaji);

}

System.exit(0);

}

}

while Döngüsü:

Kullanıcı istekleri hala bitmiyor Simdi de kullanıcımız bizden program çalıstıgında sürekli notu sormasını ve buna

karsılık düsen dereceyi bize vermesini istiyor. Ne zaman ki giris “Q” karakteri olur, o zaman program sonlansın

diyor. Bu durumda not girisi bir döngü içerisine sokulmalıdr. Bu döngünün en basında önce girisin Q olup

olmadıgına bakılmalı sonra ya döngü tekrar dönmeli ya da sonlandırılmalıdır. Bunun için en uygun döngü while

döngüsü olacaktır. while, eger içerisindeki ifade true ise program akısını kendi içine yönlendirir. Program while

faliyet alanının en sonuna geldiginde tekrar while döngüsünün ilk satırına döner ve ifadeyi yine kontrol eder. Bu

islem, while içerisindeki ifade false olana kadar devam eder.

26

Not:

 

Bu tür döngülerde, eger döngünün faliyet alanı içerisindeyken, while içerisideki

ifadeyi degistirecek bir komut yazmazsanız, ilk durumda bu ifade hep true oldugu için

ve döngü içinde de hiç degismedigi için sonsuz bir döngüye girersiniz.

while(ifade) {

satir 1

satir 2

...

satir n

/*sSimdi akiss tekrar while(ifade) satirina

yönlenecek ve kontrol yapılacaktır. eger

ifade false olmussa program akısı

satir n+1 den devam etmektedir.*/

}

satir n+1

Bu durumda kullanıcımızın yeni istegine göre örnegi tekrar düzenleyelim:

/**** Deyimler4.java ****/

import javax.swing.*;

class Deyimler4 {

public static void main(String[] args) {

String yanlisNot = "Yanlis not girisi! Tekrar deneyiniz.";

String giris = "Bir not giriniz (0 - 100)\nÇikis için notu -1 giriniz";

String notStr;

int not;

notStr = JOptionPane.showInputDialog(null, giris);

not = Integer.parseInt(notStr);

while(not != -1) {

27

if (not > 100) {

JOptionPane.showMessageDialog(null, yanlisNot);

}

else if (not <= 100 && not > 86) {

JOptionPane.showMessageDialog(null, "Not: " +

not + " Derece: A");

}

else if (not <= 85 && not > 71) {

JOptionPane.showMessageDialog(null, "Not: " +

not + " Derece: B");

}

else if (not <= 70 && not > 66) {

JOptionPane.showMessageDialog(null, "Not: " +

not + " Derece: C");

}

else if (not <= 65 && not > 50) {

JOptionPane.showMessageDialog(null, "Not: " +

not + " Derece: D");

}

else {

JOptionPane.showMessageDialog(null, "Not: " +

not + " Derece: F");

}

notStr = JOptionPane.showInputDialog(null, giris );

not = Integer.parseInt(notStr);

}

JOptionPane.showMessageDialog(null, "Program Sonlandi.");

System.exit(0);

}

}

/**************************/

break Anahtar Sözcügü:

Bazen bir döngü içerisindeyken, aslında döngünün bitmesine neden olacak sart saglanmadıgı halde özel olarak

döngüyü sonlandırmak istedigimiz durumlar dogacaktır. Bu durumların saglanması neticesinde program break

komutunu gördügü yerde içerisinde bulundugu ilk döngüyü (çünkü iç içe döngüler de olabilir) sonlandıracak ve

döngüden sonraki satırdan itibaren çalısmaya baslayacaktır

 

.

/**** Sifre.java ****/

import javax.swing.*;

public class Sifre {

public static void main(String arg[]) {

String kontrol_isim = "elvantasbas";

String k_adi = JOptionPane.showInputDialog(null, "Lutfen kullanici adini

giriniz:");

boolean x_flag = false;

while(!k_adi.equals(kontrol_isim)) {

if(k_adi.equals("x")) {

JOptionPane.showMessageDialog(null, "Islem sonland?r?l?yor..");

x_flag = true;

break;

}

k_adi = JOptionPane.showInputDialog(null, "Girdiginiz isim yanlis. Tekrar

28

giriniz:");

}

if(x_flag) {

JOptionPane.showMessageDialog(null, "Hoscakalin");

}

else {

JOptionPane.showMessageDialog(null, "Merhaba "+k_adi);

}

System.exit(0);

}

}

/********************************/

Programda while parantezi içerisinde yazılı olan

 

while(!k_adi.equals(kontrol_isim) komutuna göre eger k_adi

kontrol_isim'e esit olursa

 

k_adi.equals(kontrol_isim) metodu true degerini üretecektir. Ancak bu metodun

basında yazılı olan

 

! operatörü bu degerin degilini alacak ve false degeri üretecektir. Demek ki kullanıcı adı dogru

girilmedigi sürece bu while parantezi içerisinde

 

true degeri olacak, dogru girldigi zaman ise false degeri olacak ve

dolayısı ile while bloguna girilmeyecektir.

Bu örnekte kullanıcı, kullanıcı adını yanlıs girdigi ama x girmedigi sürece while döngüsü bloklarında kullanıcıdan

tekrar isim girmesi istenecektir. 1sim yanlıs girildiginde ve x girildiginde program while içerisindeki if bloguna

girecek ve burada islem sonlandırılıyor mesajı ile döngüden

 

break sayesinde çıkacaktır. Döngüden çıkmadan

hemen önce

 

x_flag degiskeninin degeri de true yapıacaktır. Bu degisken döngüden x ile çıkılıp çıkılmadıgı bilgisini

tutmak için kullanılan bir ara degiskendir. Döngüden çıkıldıktan sonra eger x degiskeninin degeri

 

true ise while

blokları bitimindeki if bloklarına girilecek ve ekrana hosçakalın mesajı yazılacaktır. Eger döngüden x yazıldıgı için

degil de kullanıcı adı dogru girildigi için çıkılmıs ise x degiskenin degeri

 

false kaldıdgı için if bloguna girilmeyecek

onun yerine else bloguna girilecektir. Buradaki mesaj ekrana geldikten sonra else blogundan da çıkılacak ve

System.exit(0)

 

metodu çalıstırılarak program sonlandırılacaktır.

for Döngüleri:

Su ana kadar bir kosul saglandıgı sürece otomatik olarak döngüye girilmesini while deyimi ile yapabilecegimizi

gördük. Ancak bu döngü kosul saglandıgı sürece, belli bir tekrar sayısı kadar degil her zaman devam ediyordu.

Kosul saglansa bile belirli bir tekrar sayısı da belirlemek istiyorsak o zaman for döngüsünü kullanmak gerekir. for

döngüsü söyle çalısmaktadır:

for( <ilk deger> ; <kosul> ; <ifade> ) {

...

}

Buna göre ilk deger ile baslayan döngü ile program for bloguna girdikten sonra blogun sonuna geldiginde kosulun

saglanıp saglanmadıgını kontrol edecek ve kosul saglanıyorsa ifade yi gerçekleyip tekrar döngüye girecektir.

Örnegin:

/**** ForDongusu.java ****/

public class ForDongusu {

public static void main(String arg[]){

for(int i = 0; i < 10; i++) {

System.out.println("i nin degeri: "+i);

}

}

}

/***********************/

29

Bu program çalıstıgında ekrana 10 satır boyunca

i nin degeri: 0

i nin degeri: 1

...

i nin degeri: 9

yazacaktır. Program akısı her döngüye girisinde i nin degeri ekrana yazılmakta ve blok sonunda i++ ifadesinden

dolayı bu deger bir artırılmakta ve kosulun saglanıp saglanmadıgına bakılmaktadır.

switch Deyimi:

switch deyimi kullanımı da, birden fazla else if kullanımına alternatiftir. Mesela yazdıgınız programda kullanıcıdan bir

giris isteyebilirsiziniz. Kullanıcının girecegi bu deger 4 tane degerden birtanesi olabilir ve siz olası her deger içöin bir

islem yapmak istiyor olabilirsiniz. Bunun için

if(deger 1) {

}

else if(deger 2) {

}

...

else {

}

yapısını kullanabilirsiniz. Ancak böyle durumlarda switch daha iyi bir alternatif

olacaktır. switch deyimi de söyle çalısmaktadır:

switch( <degisken> ) {

case deger1:

ifade ya da islemler;

break;

case deger2:

ifade ya da islemler;

break;

...

...

case deger n:

ifade ya da islemler;

break;

default:

ifade ya da islemler;

break;

}

Bu yapıya göre program akısı, degisken içindeki degere göre case anahtar sözcügü ile belirlenmis uygun satıra

atlar. O satudaki ifade ya da islemler gerçeklestirilikten sonra switch deyiminden çıkılır. Asagıdaki örnek

programımızda kullanıcıya bir menü sunalım ve bu menüden bir seçenegi seçmesini isteyelim. Bu seçim neticesinde

de seçime uygun bir mesajın ekrana gelmesini saglayalım. Örnegimizde ilk basta yaratılan secim_flag adındaki

boolean degisken ilk deger olarak true oldugu için, program akısının ilk seferde while döngüsüne girecegini garanti

etmis oluyoruz. Eger kullanıcı listede olmayan bir seçim girecek olursa, secim_flag degiskeni tekrar true degerini

alacak ve kullanıcıdan tekrar bir giris yapması istenecektir. Kullanıcı listede olan bir giris yaparsa program

sonlanacaktır. Bu durumda listede olmayan girsler girldigi sürece program çalısmaya devam edecektir.

30

/**** Menu.java ****/

import javax.swing.*;

public class Menu {

public static void main(String arg[]){

boolean secim_flag = true;

while(secim_flag) {

String secim = JOptionPane.showInputDialog(null, "Bir sayi giriniz: (1, 2, 3,

4)");

int sayi = Integer.parseInt(secim);

secim_flag = false;

switch(sayi) {

case 1:

JOptionPane.showMessageDialog(null, "Sectiginiz sayi: bir");

break;

case 2:

JOptionPane.showMessageDialog(null, "Sectiginiz sayi: iki");

break;

case 3:

JOptionPane.showMessageDialog(null, "Sectiginiz sayi: uc");

break;

case 4:

JOptionPane.showMessageDialog(null, "Sectiginiz sayi: dort");

break;

default:

secim_flag = true;

JOptionPane.showMessageDialog(null, "Beklenenden farkli bir sayi

girdiniz");

break;

}

}

System.exit(0);

}

}

/****************************/

continue Anahtar Sözcügü

Herhangi bir döngü içerisine girildginde, daha döngü blogunun sonuna gelinmeden o andaki adım için islemleri

sonlandırıp bir sonraki döngü adımına hemen geçilmek isteniyorsa continue anahtar sözcügünü kullanmak gerekir.

Mesela yazdıgımız programda 1'den 10'a kadar olan sayılar toplamak istiyoruz ama bu toplam içerisine 3 ve ün

katlarını eklemek istemiyoruz. Bunun için bir for döngüsü kullanmak gerekir. Ancak bu döngüyü 3 ve 3'ün katlarına

gelindiginde durdurup bir sonraki degerle döngüye devam etmek gerekmektedir:

/**** Toplama.java ****/

public class Toplama {

public static void main(String arg[]){

int toplam = 0;

for(int i = 0; i < 10; i++) {

if(i % 3 == 0) {

continue;

}

31

toplam += i;

}

JOptionPane.showMessageDialog(null, "Toplam: " + toplam);

System.exit(0);

}

}

Bu örnekte % operatörünü kullandık. Bu operatör soldaki sayının sagdaki sayıya bölümünden kalan degeri üretir.

Yani i sayısı o anda hangi degere sahipse, bu degerin 3'e bölümünden kalan sayının 0'a esit olup olmadıgı kontrol

edilmektedir. Eger bu kalan sayı 0'a esit ise demek ki sayımız ^ya da 'ün bir katıdır. Bu yüzden if parantezi

içerisindeki == kontrolü saglandıgından dolayı true degeri üretilecek ve dolayısı ile if blogu içerisine girilecektir. If

blogu içerisinde continue anahtar sözcügü sayesinde o andaki for adımı sonlanacak ve bir sonraki i degeri ile for

blogunun en basına dönülecektir.

Diziler

Bu ana kadar programla içerisinde kullanacagımız degiskenler oldugunu ve bu degiskenlerin de belirli türelere sahip

olduklarını görmüstük. Ancak biliyoruz ki her degisken sadece bir deger tutmaktadır. 1çerisinde deger tutan bu

degiskenler de bellekte farklı yerlerde saklanmaktadır.

Dizi denilen degiskenler ise içlerinde birden fazla deger tutarlar ve diger degiskenler gibi belirli bir türe sahiplerdir.

Ayrıca bu degerler de bellekte ardısıl biçimde saklanırlar ve hepsi aynı türe iliskin olmak zorundadır. Buna göre bir

diziyi aslında arka arkaya sıralanmıs bir degisken paketi olarak düsünebiliriz.

Ancak sunu unutmamalıyız: Dizilerin içlerinde tutacakları eleman sayısı sahiptir. Bazı elemanlara siz deger

vermesseniz bile bu elemanlar için bellekte yer ayrılır. Ayrıca dizinin içerisinde saklanan degerlerin türü ile dizinin

türü aynı olmak zorundadır.

Dizilerin Yaratılması:

Normalde degiskenleri yaratırken degiskenin türünü ve sonra da adını yazıyorduk. (int b; ya da double a; gibi)

Dizilerin yaratılması ise biraz daha farklıdır. Bir dizinin yaratılması iki adımdan olusur. Birinci adım “bildirim”

dedigimiz ve dizinin türünü ve dizi degiskeninin adını belirledigimiz adımdır:

int [] sayilar;

Burada “sayilar” adinda ve içerisinde integer degerler tutacak olan bir dizi bildirimi yapmıs olduk. Ancak bu dizi

bildiriminin degisken bildiriminden farkının [ ] karakterlerinin eklenmesi seklinde olduguna dikkat ediniz.

1kinci adım ise tahsisat denilen ve dizi degiskenin kaç tane deger tutacagını belirledigimiz adımdır

 

:

sayilar = new int[10];

Bu örnekte, daha önce bildirimini yaptıgımız sayilar dizisine 10 tane integer sayı tutabilecek kadar alanı tahsis

etmis olduk. Bu islem aslında

 

new anahtar sözcügü sayesinde yapılmıs oldu. Ancak, bu adımdan sonra dizi

degiskenimiz belirlenmis ve degerleri saklayabilecegi alan tahsis edilmis olsa bile, dizimizin içerisinde hala hiç bir

deger saklanmamaktadır. Dizilerin içerisinde elemanlara erismek ve yeni elemanlar eklemek için indeks numarası

denilen bir kavram kullanılmaktadır. Indeks operatörü [ ] ile gösterilir ve dizinin adının yanına ekleneek kullanılır. Bir

dizinin ilk elemanın indeks numarası 0 dır. Buna göre dizimize deger atamak için:

sayilar[9] = 12;

sayilar[0] = 3;

32

seklinde [ ] ve bir indeks numarası kullanılarak atama yapılabilir.

NOT:

 

Burada dikkat edilmesi gereken sey, dizimizin uzunlugundan daha fazla eleman ataması yapmamaktır. Bu

örnegimize göre sayilar dizisinin son elemanına

 

sayilar[9] ile erisebiliriz. Sayilar[10] = 23; hatalı bir atama

olacaktır çünkü 10 nolu indekste 11. eleman olur. Ancak dizimiz sadece 10 eleman tutacak alan tahsis edilmisti!

Simdi kullanıcıdan gelecek olan isimleri bir dizide saklayan bir program yazalım:

/**** Kayit.java ****/

1 import javax.swing.*;

2

3 public class Kayit {

4 public static void main(String arg[]){

5

6 String kayit_str = JOptionPane.showInputDialog(null, "Kac tane kayit

gireceksiniz:");

7 String cikisMesaji = "Hernagi bir anda cikmak icin "

8 int kayit = Integer.parseInt(kayit_str);

9

10 String isimler[] = new String[kayit];

11 for(int i = 0; i < isimler.length; i++) {

12 int sayi = i+1;

13 String giris = JOptionPane.showInputDialog(null, sayi + ". kaydi

giriniz:");

14 if(giris.equals(“X”))

15 break;

16 else

17 isimler[i] = giris;

18 }

19

20 String mesaj = "isim Listesi\n********";

21

22 for(int i = 0; i < isimler.length; i++) {

23 if(isimler[i] != null)

24 mesaj += "\n"+i+" --> "+isimler[i];

25 }

26

27 JOptionPane.showMessageDialog(null, mesaj);

28 System.exit(0);

29 }

30 }

/******************/

Bu programda önce kullanıcının kaç kayıt girecegi sorulmaktadır. Çünkü dizilerin uzunlugu sabittir ve önceden bir

defa yer ayrıldıgından bu uzunluk bilinmelidir. Uzunlugu degisen dizileri için baska algoritmik çözümler vardır ancak

degismeyen ser bir dizinin uzunlugu sabittir ve sonradan uzatılıp kısaltılamaz.

Bu örnekte kullanıcının girecegi kayıt kadar yer tahsisati yapıldıktan sonra for döngüsü ile her adımda girilecek olan

kayıt istenmekte ve diziye atılmaktadır. Eger kullanıcı basta belirledigi kadar kayıt girmekten vazgeçip o anda islemi

sonlandırmak isterse isim yerine X girisi yapabilecektir. Programda her giris yapıldıktan sonra bu degerin X olup

olmadıgına bakılmaktadır (14. satır). Eger giris X olursa döngü break ile sonladırılır (15. satır). Degilse giris diziye

yazılır ve döngü devam eder (16. satır).

NOT:

 

String türünde diziler için tahsis edilen yerlerin içine birsey doldurulmaz ise, bu yerler otomatik olarak null

denilen özel bir degerle doldurulur.

 

null degeri , “ ” gibi bos bir String ya da 0 degildir. Kendi basına anlamlıdır.

Bu döngü bittikten sonra yeni bir for döngüsü ile de diziden her kayıt tek tek okunmakta (22. satır) ve “mesaj”

adındaki String degiskeni içerisine atılmaktadır (24. satır). Daha sonra bu mesaj isimli degisken ekrana yazılacaktır

33

(27. satır). Eger kullanıcı diziye ayrılan yer kadar kayıt girmeyip arada X ile çıkıs yapmıssa, bu durumda diziye

girilmemis olan elemanlar yerine

 

null degeri olacaktır. Bu degerler varsa mesaj içerisine eklenmemektedir. Bu

yüzden o andaki adımda, diziden gelen degerin

 

null olup olmadıgı kontrol edilmekte, deger null degilse mesaj

degiskeninine eklenmektedir (23. satır).

Dizilere iliskin temel bilgileri ögrenmeyi burada sonandırıyoruz. Siz de kendi yeteneklerinizi sınamak icin diger

dersimize kadar tüm ögrendiklerinizi kullanarak asagıdaki uygulamayı yapmaya çalısınız. Bu uygulamanın cevabını

diger dersimiz içerisinde bulabileceksiniz :

Dizi Yaratma Sekilleri

1) int a[];

a = new int[3];

a[0] = 1, a[1] = 2, a[2] = 3;

2) int a[] = {12, 3, 6, 7}

3) new int[] {1,4,5,6}

34

Java ile Programlama:

Bölüm 4:

Dersimize son dersimizde verdigimiz uygulamanın çözümü ile baslayacagız. Uygulamamızı tekrar hatırlatalım:

Uygulama:

 

Kendi basınıza içerisinde isimler saklayan bir dizi yaratınız ve daha sonra bu dizide kullanıcıdan

aldıgınız bir ismi aratınız. Eger isim dizinin içerisinde bulunursa bu ismin indeks numarasını ekrana yazdırınız.

Bulunamazsa ismin bulunamadıgına dair bir mesaj yazdırınız.

import java.awt.*;

import javax.swing.*;

public class Ara {

public static void main(String arg[]) {

String []isimler = {"Hakan Aykac", "Murat Akar", "Cenk Gündüz",

"Cem Daggeçen"};

String aranacak = JOptionPane.showInputDialog(null,

"Aradiginiz ismi giriniz: ");

int index = -1;

for(int i = 0; i < isimler.length; i++) {

if(isimler[i].equals(aranacak)) {

index = i;

break;

}

}

if(index == -1)

JOptionPane.showMessageDialog(null, aranacak+" ismi dizide mevcut degildir.");

else

JOptionPane.showMessageDialog(null, aranacak+" isminin index numarasi:

"+index);

System.exit(0);

}

}

Metod Kavramı ve Java’da Metodlar

Daha önce bazı noktalarda metodlara deginmistik. Metod denilen kavramın, program içerisinde yazılmıs küçük

program parçaları oldugunu söyleyebiliriz. Metodlar aslında önceden tanımlanmıs birtakım islem sekilleridir. Bu

sekilde görevleri metodlar attında olusturarak gerektiginde çagırabiliriz. Bunu söyle bir örnekle hayalimizde

canlandıralım:

Yazmıs oldugumuz programımızı bir robota benzetelim. Bu robota çesitli görevler yükleyelim. Bunlardan bir tanesi

de “su getir” görevi olsun. Bu görev su sekilde tanımlansın:

Mutfaga git

Bardaga su doldur

Su dolu bardagı sahibine getir

1ste siz her su isteme islemi için bu üç komutu robota vermek yerine, sadece 1 defa “su getir” görevini

tanımlayabilirsiniz. Daha sonra da su istediginizde, sadece bu görevi robota vermeniz, bu üç komutun çalıstırılması

için yeterli olacaktır. Sonuçta, Java’da da metodlar bu sekilde birden fazla komutu tek seferde ve istenildigi zaman

çalıstırabilmek amacıyla tasarlanır.

35

Asagıdaki örnekte (Metod.java), ekrana sadece Merhaba yazan bir metod gösterilmektedir:

 

Mesaj.java” örneginde de görüldügü gibi “MesajGoster” isimli metod, main metodunun bittigi yerde

yaratılmıstır. Ancak bu metodun da tıpkı main metodu gibi sınıfın içerisinde yaratıldıgına dikkat ediniz. Metodun

yaratılması sırasında ilk satırda

public static void MesajGoster()

seklinde metodun adı ve daha sonra da

{

}

parantezleri içerisinde bu metodun gerçeklestirecegi komutlar yazılmaktadır.

Metodun adını yazdıgımız bu ilk satıra “metod bildirimi” denilir. Metod bildirimine iliskin ayrıntıları bilgilerimiz

arttıkça tamamlayacagız.

Not:

 

Metodları isimlendirirken bosluk bırakılmaz. (Mesaj Goster geçersiz ancak Mesaj_Goster gecerli bir metod

ismidir)

Not:

 

Main metodu ve sınıf kavramlarına sonraki derslerimizde deginecegiz.

Metodların Çagrılması

Simdi bu Mesaj.java dosyasını çalıstırmaya kalktıgımızda, dosyanın düzgün bir sekilde çalıstıgını ancak ekranda hiç

bir mesaj yazılmadıgını göreceksiniz. Sakın sasırmayın! Böyle olması çok normal. Bir metod yazıldıgı zaman bu onun

aynı zamanda çalısacagı anlamına gelmez. Metodun çalısması için sizin onu çagrmanız gerekmektedir. Bunu robota

“su getir” emrini vermenize benzetebiliriz. Siz bu emri daha önce tanıtmıs olsanız bile, emri vermeden robot size su

getirmez. Aynı sekilde yazılmıs bir metodun çalısması için de metodun “program akısının oldugu yerde” çagrılmıs

olması gerekir. Bir metodu çagırmak için metodun yaratıldıgı sekilde adını ve adın yanına da ( ) parantezlerini

eklememiz gerekir:

...

MesajGoster();

...

gibi... O halde örnegimizde de metodun çalısmasını görmek için main metodu içerisinde MesajGoster isimli

metodumuzu çagıralım:

36

Programımız ilk çalıstırıldıgında her zaman main metodu “otomatik olarak çagrılır” Daha sonra main metodu

içerisinde yazılan her satırdaki komutlar sırasıyla çalıstırılır. Program akısı MesajGoster(); seklinde yazılmıs olan

metod çagırma komutuna geldiginde MesajGoster metodunun yazıldıgı yere atlar ve buradaki komutları sırasıyla

çalıstırırarak tekrar main metodunda kaldıgı yerden çalısmaya devam eder. Tabi ki metod ismi MesajGoster den

baska bir isim de olabilir. Sadece buradaki örnekte bir metod yazılmıs ve adı öyle konulmustur. Bu akıs prensibi her

metod için geçerlidir.

Simdi islerimizi daha da genellestirelim ve ekrana sadece Merhaba degil de, istedigimiz bir mesajı gönderen bir

metod olusturalım. Aslında bu isi zaten

 

JOptionPane sınıfının showMessageDialog isimli metodu ile

yapabiliyorduk. Ancak bu metodun adı çok uzun olmakla beraber program içerisinde birden fazla yerde

çagırdıgımızda çok fazla yer kapladıgını görmekteyiz. Bu yüzden aynı isi yapan ve adı sadece “

 

M” olan bir metod

yazalım. Ancak bu metoda her seferinde hangi mesajı yazacagını da göndermemiz gerekecektir. Çünkü her

seferinde ekrana baska bir mesaj yazılmasını isteyebiliriz. 1ste bu noktada karsımıza parametre kavramı çıkar.

Metodların Parametreler ile Kullanımı

Parametreler yardımıyla metodlara birtakım degiskenler göndermemiz mümkündür. Önceki örneklerimizde

MesajGoster isimli örnek metodumuzu parametresiz olarak kullandık. Asagıdaki örnekte M isimli metod parametre

ile çalısan bir metod olup, ekrana, kendisine parametre olarak gönderilen mesajı basmaktadır.

37

Burada dikkat edilirse 6. satırda çagrılan M metodu 10. satırda parametre ile bildirilmistir. Metod bildiriminde

parametreler metodun ( ) parantezleri arasında önce tür adı ve daha sonra da parametre adı yazılarak ve birden

fazla parametre arasında da virgul kullanılarak tanıtılabilir. Yani:

public static void Metod_Adi(<tür> parmaetre1, <tür> parametre2) {

...

}

seklinde bildirimi genellemek mümkündür. Örnegin:

public static void M(String mesaj):

 

Sadece String türünde bir parametre alan ve bu parametreyi metod

içerisinde “mesaj” ile temsil eden bir metod bildirimi.

public static void Metod2(int x, double y):

 

Adı x olan ve int türünde bir parametre ile adı y olan ve double

türünde bir parametre alan ve kendi adı da Metod2 olan bir metodun bildirimi.

Bu sekilde bildirimi yapılan bir metodu çagırıken de metodun adı ve daha sonra da ( ) parantezleri içerisine

bildirimde verilen sırada ve türlerde degerle göndermemiz gerekir. Mesela M isimli örnek metodumuza her seferinde

String türünde farklı mesajlar gönderebiliriz. Gönderilen b her String degeri, metod bildiriminde “mesaj” isimli

degiskene kopyalanır ve metodun içerisinde de bu degisken aracılıgıyla ele alınır. Mesela bildirimi

public static void Islem(int sayi, String mesaj)

seklinde yapılmıs olan bir metodu su sekillerde çagırabiliriz:

Islem(6, “Bugun hava guzel”);

Islem(12, “Çok çalısmak lazım”);

Islem(4, “Java Ögrenmek Lazım”);

...

Burada yapılan sey aslında metodun çagrılması neticesinde gönderilen degerler, metod bildirimi ile tanımlanan

degiskenlere sırasıyla kopyalanır (ya da atanır.) Öyle ki;

Islem(6, “Bugun hava guzel”);

seklinde metodu çagırdıgımızda 6 degeri sayi degikenine ve “Bugün hava güzel” degeri de mesaj degiskenine atanır

ve metod içinde bu sekilde kullanılır.

Ancak Islem(“Selam”, 12); gibi bir çagrım geçerli degildir. 1slem isimli metodun bildiriminde önce int türünde

sonra da String türünde parametre yazılmıstır. Metodu çagırırken de aynı sıraya uymamız gerektigini unutmayalım.

38

ÖNEML NOT:

 

Özetle, metodları bildirirken metodun alacagı parametreleri tür ve parametre isimlerini yazarak,

metodları çagırıken de parametreler yerine deger göndererek islem yapmaktayız. Bu iki islemi birbirine

karıstırmamalıyız.

Metodlarda Geri Dönüs Degeri Kavramı

Yukarıda da anlattıgım gibi, metodlara birtakım parametreler göndererek bazı islemler yapmalarını saglarız. Bu

islemler kendi içerisinde uygulanıp tamamlanan islemler olabilecegi gibi, sonunda bir sonuç üretilen islemler de

olabilir. 1ste sonuçta elde edilen bu degerleri kullanabilmemiz için, metodun bu degerleri bize geriye göndermesi

gerekir. Metodların islemlerinin tamamlaması neticesinde geriye gönderdikleri bu degere “geri dönüs degeri“

denilmektedir. Asagıdaki örnekte parametre olarak bir çemberin yarıçap degerini alan “alanHesapla” isimli metod,

çemberin alanını hesaplayarak geriye bu degeri bize göndermektedir:

Örnekte de görüldügü gibi, 9. satırda kullanıcıdan istenen yarıçap degeri 10. satırda metoda parametre olarak

gönderilmektedir. Ama aslında parametre olarak gönderilmeden hemen önce “Double.parseDouble()” metodu ile bu

String türündeki yarıçap degeri double türüne dönüstürülmekte ve dönüsüm sonucu gelen deger “alanHesapla”

isimli metoda parametre olarak gönderilmektedir. Gönderilen bu parametre, metod bildiriminde belirtilen “yaricap”

isimli degiskene aktarılmaktadır.

NOT: Bu aktarım neticesinde, gelen parametre artık metod içerisinde yaricap ismiyle kullanılacaktır.

Eger metod, 1'den fazla parametreli bir metod olsaydı, bu durumda gönderilen parametre degerleri

aynı sıra ile, metod bildiriminde tanımlanan parametre degiskenlerine aktarılacaktı.

Daha sonra “alanHesapla” metodu kendisine gelen bu parametre'nin, “Math” sınıfının “power” metodu yardımıyla

karesini alarak 3.14 (pi sayısı) ile çarpmakta ve üretilen sonucu da 17. satırda oldugu gibi alan degiskenine

atamaktadır.

NOT: “Math.power” metodu 1. parametre ile kuvveti alıncak sayıyı, 2. parametre ile de bu sayının

kaçıncı kuvvetini alacagını belirler. Geri dönüs degeri olarak da hesapladıgı sonucu gönderir.

return Anahtar Sözcügü

Alan.java örneginde, 18. satırda kullanılan “return” ifadesi, önündeki degisken degerini metodun çagrıldıgı yere

göndermektedir. Bu durumda hesaplanan alan degeri, return ifadesi ile metodun çagrıldıgı 9. satıra

gönderilmektedir. Buraya geriye gönderilen deger de “sonuc” isimli degiskene atanarak tutulmus olur.

39

Eger 9. satırda

sonuc = alanHesapla( Double.parseDouble(yrcp) );

ifadesi yerine sadece

alanHesapla( Double.parseDouble(yrcp) );

seklinde metodu çagırsaydık, metod içerisinden alan degeri gönderilecek, ancak bu degeri tutacak “sonuc” gibi bir

degisken olmadıgı için geriye gelen deger bosa gidecekti ve ele alınamayacaktı.

Bu örnekte dikkat edilmesi gereken bir diger konu da; geri dönüs degeri olan metodların bildirimlerinde void yerine

bir tür adı yazılması gerektigidir. Örnegimizde geriye gönderilen degerin türü “double” türünde bir deger oldugu için

oldugu için, 16. satırda yapılan metod bildiriminde metod isiminden hemen önce geri dönüs degerinin türünün

yazıldıgını görmekteyiz. Fakat önceki örneklerimizde geri dönüs degeri olmayan metodlarda bu kısma “void”

yazmıstık.

Dizilerin Metodlara Parametre Olarak Gönderilmesi

Daha önce dizilerin ne amaçla yaratıldıklarını ve nasıl kullanıldıklarını görmüstük. Dersimizin bu kısmında hem

metod kullanımını biraz daha pekistirmek, hem de diziler üzerinde pratik yapmak amacıyla dizilerin metodlara

aktarılmasını inceleyecegiz.

Asagıdaki örnekte çesitli isimlerden olusan bir diziyi “

 

alfabetikSirala” isimli metoda gönderiyoruz. Bu metod

kendisine parametre olarak karısık sırada isimlerden olusan bu diziyi alfabetik sırada yeni bir dizi içerisinde

olusturarak geriye de bu yeni diziyi gönderiyor.

import javax.swing.*;

import java.util.Arrays;

import java.lang.System;

class DiziSirala {

public static void main(String[] args) {

String liste[] = {"Evren Akar", "Ahmet Aykaç", "Fatih Demir", "Ender Uçkun"};

String gelenDizi[] = alfabetikSirala(liste);

diziGoruntule(liste, "Orjinal Dizi");

diziGoruntule(gelenDizi, "Sirali Dizi");

System.exit(0);

}

public static String[] alfabetikSirala(String [] dizi) {

String sirali_dizi[] = new String[dizi.length];

System.arraycopy(dizi, 0, sirali_dizi, 0, dizi.length);

Arrays.sort(sirali_dizi);

return sirali_dizi;

}

public static void diziGoruntule(String []dizi, String dizi_adi) {

String mesaj = dizi_adi+" Içerigi\n***************\n\n";

for(int i = 0; i < dizi.length; i++)

mesaj += "dizinin "+i+". elemani: "+dizi[i]+"\n";

JOptionPane.showMessageDialog(null, mesaj);

}

40

}

Diziler metodlara parametre olarak aktarılırken sadece isimlerinin aktarılması yeterlidir. Örnegimizde 5. satirda

yaratilan “

 

liste” isimli dizimiz, 6. satırda metod çagrılması sırasında, parantez içerisinde sadece ismi yazılarak

 

alfabetikSirala” isimli metoda aktarılmaktadır.

Diziyi parametre olarak alan metod bildiriminde ise, parametre kısmında gelecek olan dizinin türü, [ ] sembolü ve

bir parametre adı yazılması gerekir. Örnegimizde yarattıgımız “

 

alfabetikSirala” isimli metodun 12. satırdaki

bildiriminde de, gelecek olan dizi parametresi “

 

dizi” isimli degiskene aktarılacaktır. Ancak bu degiskenin de bir

 

String” dizisi degiskeni olarak tanımlandıgına dikkat ediniz.

“alfabetikSirala”

 

isimli metoda gelen bu dizi, parametre aktarımından dolayı artık metod içerisinde “dizi” ismiyle

kullanılacaktır.

 

System” sınıfının “arrayCopy” isimli metodu, 1. parametre ile aldıgı bir dizinin, 2. parametre ile aldıgı

indeksinden itibaren, 3. parametre ile aldıgı dizinin, 4. parametre ile aldıgı indeksine, 5. parametre ile aldıgı sayıda

elemanı kopyalar. Bu metod yardımıyla, 14. satırda oldugu gibi metod içerisinde “

 

dizi” ismiyle tutulan orjinal

dizimizin tüm elemanları, “

 

sirali_dizi” ismiyle yarattıgımız diziye kopyalanmaktadır.

 

Arrays” isimli sınıfın “sort” isimli metodu, kendisine parametre olarak verilen bir diziyi sıralamaktadır. Biz de

örnegimizde bu metodu kullanarak “

 

sirali_dizi” içerisinde bir kopyasını aldıgımız dizi isimli dizimizi sıralamaktayız.

Dizilerin Geri Dönüs Degeri Olarak Kullanılması

Bir diziyi geri dönüs degeri olarak gönderirken benzer sekilde “

 

return” anahtar sözcügü önünde dizinin isminin

yazılması yeterlidir. Ancak dikkat edilmesi gereken önemli nokta

 

geriye gelen diziyi tutacak degiskenin de bir dizi

degiskeni olması gerektigidir. Örnegimizde 16. saturda yazılan “

 

return” ifadesi ile yeni sıralı dizimizi 6 satırda

metodu çagırdıgımız yere geri dönüs degeri olarak göndermekteyiz. 6. satıra gelen bu yeni dizi “

 

gelenDizi” isimli

dizi degikenine aktarılmaktadır.

Örnekte 19. satırda yazmıs oldugumuz “

 

diziGörüntüle” isimli metod kendisine 1. parametre ile gönderilen bir

dizinin 2. parametre ile gönderilen baslıgı kullanarak içerigini görüntülemektedir. Bu metod yardımıyla orjinal ve

sıralanmıs dizilerimizin içeriklerini de görüntülemkteyiz.

Bu örnekler sayesinde metod ve dizi kullanımına iliskin teknikleri daha iyi anlayacagınızı umuyorum. Ders içerisinde

verilen örnekleri mutlaka satır satır yazmanızı öneririm. Böylece hiç farkında olmadan Java'da birçok seyin pratik

hale geldigini göreceksiniz.

Simdi dizilere iliskin son bir örnekle metod ve dizilerin birlikte kullanımını toparlayalım.

import javax.swing.*;

import java.util.Arrays;

import java.lang.System;

class HistogramSinifi {

public static void main(String[] args) {

int uzunluk = Integer.parseInt(JOptionPane.showInputDialog(null, "Dizi uzunlugu

ne olsun?"));

String []liste = diziYarat(uzunluk);

Histogram(liste);

System.exit(0);

41

}

public static String[] diziYarat(int boyut) {

String isimler[] = new String[boyut];

for(int i=0; i < isimler.length; i++)

isimler[i] = JOptionPane.showInputDialog(null, i+". ismi giriniz");

Arrays.sort(isimler);

return isimler;

}

public static void Histogram(String dizi[]) {

JTextArea cikisEkrani = new JTextArea(15, 15);

String cikis = "isim \t uzunluk \n -------------------\n";

for(int i = 0; i < dizi.length; i++) {

cikis += dizi[i] + "\t";

for(int k = 0; k < dizi[i].length(); k++)

cikis += "*";

cikis += "\n";

}

cikisEkrani.setText(cikis);

JOptionPane.showMessageDialog(null, cikisEkrani);

}

}

Örnegimizde 5. satırda “

 

JOptionPane” isimli sınıfın “showInputDialog” isimli metodu, geri dönüs degeri olarak

kullanıcının girecegi

 

String bir deger göndermektedir ve bu deger de “Integer” sınıfının “parseInt” isimli metodu

içerisine parametre olarak verilerek integer bir sayıya dönüstürülür. Dönüstürülen bu sayı da “

 

uzunluk” isimli

degiskene atanır. Daha sonra 7. satırda

 

“liste” ismiyle yaratılan dizimiz de, bu uzunluk degeri kadar olacaktır. Ama

dikkat ederseniz bu sefer dizi yaratma islemi bizim yazdıgımız “

 

diziYarat” isimli metod içerisinde yapılmaktadır.

13. satırda tanımlanan “

 

diziYarat” isimli metod kendisine parametre olarak verilen uzunlukta bir String dizisi

yaratır. Daha sonra 16. satırda yazılan for döngüsü ile bu dizinin elemanlarını kullanıcıdan alarak diziye yerlestirir.

Bu islemi 17. satırda oldugu gibi, for döngüsünün her i adımında, kullanıcıdan istedigi giris degerini dizinin i.

elemanına atayarak yapmaktadır. Daha sonra 19. satırda yaratılan ve içerisine isimler yerlestirilen dizimiz “

 

Arrays”

isimli sınıfın “

 

sort” isimli metodu ile sıralanmaktadır. En son olarak da 20. satırda, yaratılan bu dizi “return” ifadesi

ile metodun çagrıldıgı 7. satıra gönderilir. Bu gönderme neticesinde de yaratılan ve sıralan bu dizi, liste isimli dizi

degiskenine atanmıs olur.

8. saturda, “

 

Histogram” isimli metod çalıstırılmaktadır. Bu metod kendisine parametre olarak verilen bir dizinin

her elemanının kendisini ve bu elemanın karakter uzunlugu kadar * simgesini ekrana basar. Metod bu islemi

yapmadan önce ilk olarak

 

“JTextArea” denilen özel bir java nesnesi yaratmaktadır. Bu nesne 25. satırda

yaratılmaktadır. Java nesneleri ve nesnelerin yaratılması konusunu sonraki dersimizde ayrıntılı olarak görecegiz.

26. satırda “

 

cikis” isimli String degiskeni de en son ekranda belirecek mesajı tutmak amacıyla olusturulmaktadır.

Ancak bu degisken ilk yaratıldıgında içi bos bir sekilde olusturulmaktadır. 28. satırdaki for döngüsü ile dizinin her

elemanı tek tek ele alınacaktır. 29. satırda, i. adımdaki eleman ve bir tab bosluk karakteri “

 

cikis” degiskenine

yazılır. 30. satırdaki for döngüsü, i. adımda ele alınan dizi elemanının her karakteri için adım adım * isaretini yine

cikis isimli degiskene yazar. En son olarak da 33. satırda “

 

cikis” isimli degiskenin sonuna “\n” seklide alt satıra

geçme karakteri eklenerek 28. satırdaki döngünün bir sonraki adımına geçer ve aynı islemler diger dizi elemanları

için de tekrarlanır. Tüm dizi elemanları bu sekilde ele alındıktan sonra, 35. satırda oldugu gibi “

 

cikisEkrani” isimli

nesnenin içerisinde yer alacak yazı, yine bu nesneye ait öntanımlı “

 

setText” isimli metod yardımıyla “cikis” isimli

degiskenin içerisinde saklanan degere set edilir. (Java'da nesnelerin öntanımlı metodlarını sonraki derslerimizde

inceleyecegiz.) En son olarak da metod 36. satırda oldugu sekilde bu nesneyi showMessageDialog isimli metoda

vererek ekranda görünmesini saglar.

42

Dikkat ederseniz daha önceki örneklerimizde JOptionPane.showMessageDialog isimli metoda hep bir mesaj

yazıyorduk. Ama bu sefer metoda, “ ” içerisinde yazılmıs bir String mesajı yerine, bir nesne gönderdik ve tüm

mesajımızı da bu nesne içerisinde yazdık.

Uygulama:

 

 

Bir dizinin içerisindeki elemanları sıraya dizen static bir metod yaziniz ve main metodu icerisinde

yazdiginiz bu metoda diziyi gondererek siralayiniz.

UYGULAMA:

 

Kendi basınıza içerisinde isimler saklayan bir dizi yaratınız ve daha sonra bu dizide kullanıcıdan

aldıgınız bir ismi aratınız. Eger isim dizinin içerisinde bulunursa bu ismin indeks numarasını ekrana yazdırınız.

Bulunamazsa ismin bulunamadıgına dair bir mesaj yazdırınız.

Dizilerin Kopyalanmasına liskin NOT:

Bir dizi yaratıldıktan ve içerigi güncellendikten sonra bunu aynen baska bir diziye kopyalamak için System.arraycopy

metodu kullanılır. Bu metodun kullanımı:

System.arraycopy(kaynak_dizi, baslama_noktasi, hedef_dizi, hedef_baslama_noktasi, kopyalancak_eleman_sayisi);

seklindedir:

43

Java ile Programlama:

Bölüm 5:

Önceki dersimizde hatırlarsanız Java'da metodların nasıl kullanıldıgını ve yaratıldıgınu ayrıntılı olarak inceleyerek,

devamında da dizilerin metodlara parametre olarak gönderilmesine iliskin birtakım örnekler üzerinde çalısmıstık.

Önceki derslerimizi iyice tekrar ettiginizi ve verilmis örnekleri de teker teker yazarak denediginizi umuyorum. Bilinen

örnekleri bile sabırla yazmak inanın çok sey ögretecektir.

Bugünkü dersimizde artık nesne yönelimli programcılıgın en önemli kavramı olan sınıfları inceleyecegiz. Önümüzdeki

derslerin birçogu artık bu sınıfları kullanmak ve gelistirmek üzerine olacak. Bu yüzden burada basitlestirerek

anlatmaya çalıstıgım bu temel kavramları iyice anlamaya ve irdelemeye çalısmanızı öneririm.

Sınıf Kavramı:

Biliyoruz ki genel anlamda program yazabilmek için çesitli degiskenler yaratıp kullanıyoruz. Yaratılan her degiskenin

bir türü oldugunu ve yaratıldıktan sonra bu degiskenlerin de artık birer nesne oldugunu görmekteyiz.

Örnegin

"

 

int a;" dedigimizde a isimli degiskeni içerisinde tamsayılar tutacak biçimde,

"

 

double b; " dedigimizde b isimli degiskeni içerisinde virgüllü sayılar tutabilecek sekilde ya da

"

 

String c[]; " dedigimizde c isimli degiskeni içerisinde String türünde degerler tutan bir dizi seklinde yaratmıs

oluyoruz. Yani degiskenleri bilinen nesne türlerinden birtanesi cinsinden yaratıyoruz.

1ste bugün ögrenecegimiz sekilde, sınıfları yazarak önce

 

yeni bir nesne türü yaratıyor ve daha sonra da

yaratmıs oldugumuz bu "

 

nesne türü cinsinden" sınıf degiskenleri yaratarak bu sınıfları kullanabiliyoruz. Ya

da bir baskasının yaratmıs oldugu bir sınıf türünden yeni bir degisken yaratabiliyor ve yine bu degiskeni

kullanabiliyoruz.

Aslında bundan önceki derslerde, önceden yaratılmıs bazı sınıfları zaten kullanmıstık. Örnegin "

 

JOptionPane"

isimli sınıfa ait "s

 

howMessageDialog" ya da "showInputDialog" gibi metodları kullanırken aslında

JOptionPane

 

isimli sınıfı kullanmıs olduk.

Sınıf Nedir?

Simdi biraz daha genel olarak sınıfların ne oldugundan bahsetmekte fayda var. Sınıf denilen sey aslında birden fazla

metod ve degiskeni birarada tutan bir yapıdır. Ancak bu degisken ve metodların da aynı göreve iliskin olması

beklenir. Örnegin icq benzeri bir uygulamada en kaba sekilde görsel kısım ve ag baglantıları olmak üzere iki kısım

oldugunu kabul edelim. Bu uygulamanın pencere sekli, rengi, dügmelerin yeri v.b. isleri üstlenecek birçok metod ve

degiskeni olsa da hepsinin amacı aslında görselligi saglamaktır. Yine benzer sekilde arka planda baglantıları

ayarlayan, kontrol eden bir çok metod ve degisken de ag ayarları için kullanılır.

Bu durumda aynı projeye iliskin ama ayrı görevleri üstlenen tüm metod ve degiskenleri bu iki ana sınıf altında

toplamak hem organizasyonda hem de tasarımda kolaylık saglar. Bu iki kısım birbirinden bagımsız tasarlanarak bir

araya getiriliebilir. Bu da projeye esneklik saglar.

Sınıfların Yaratılması

Bundan önce yazdıgımız örneklerde aslında biz hep bir sınıf ve bu sınıfın içerisinde de birtakım metod ve

degiskenler yaratıyorduk. Simdi yine örnek bir sınıf yaratalım. Bu sınıf kendi içerisinde sadece bir degisken tutsun

ve bu degiskenin degerini elde edebilecek ya da degistirebilecek bazı metodları olsun:

class DegiskenTutan {

int x;

public void setX(int c) {

this.x = c;

44

}

public int getX() {

return this.x;

}

}

DegiskenTutan.java dosyasındaki örnekte, bahsettigimiz bu sınıfı yine sınıf ile aynı isimde olan

"

 

DegiskenTutan.java" dosyası içerisinde yarattık ve kaydettik. Biz aslında burada "DegiskenTutan" isimli yeni

bir nesne türü yaratmıs oluyoruz.

DegiskenTutan sınıfının 2. satırında yaratılan "

 

x" isimli bir global degiskeni bulunmaktadır. Bu degiskenin global

olmasının nedeni yaratıldıgı yerin herhangi bir metodun içinde degil de en dıs faliyet alanında olmasıdır. Bu nedenle

sınıf içerisinde tanımlı diger tüm metodlar bu degiskene erisebilir ve degiskeni kullanabilirler.

this Anahtar Sözcügü

Sınıf içerisinde yazılmıs olan "

 

getX" isimli metod, bu "x" degiskeninin içerisindeki degeri geri döndürmektedir.

Yalnız dikkat edilirse 9. satırda gerçeklesen bu geri döndürme islemi sırasında sadece degiskenin adı degil, onun

yerine "

 

this.x" seklinde bir kullanım görmekteyiz. "this" anahtar sözcügü özel bir anahtar sözcük olup noktadan

sonra gelen degisken isimlerinin sınıfa ait oldugunu ifade etmektedir. Yani 9. satırda yazılan

r

 

eturn this.x;

ile kastedilen sey, ilgili sınıfa ait olan "x" isimli degiskeninin geri döndürülecegidir. Yine sınıf içerisinde yazılmıs olan

"

 

setX" isimli metod da kendisine parametre olarak gelen ve c degiskeninde tutlan degeri "this.x" degikenine, yani

sınıfa ait olan "

 

x" degiskenine atamaktadır.

Gördüıgümüz gibi yazmıs oldugumuz bu yeni sınıf içerisinde baska degisken ya da metod bulunmamaktadır. Peki ya

madem artık bu sınıf yazıldı ve kullanıma hazır, sınıfı nasıl kullanabiliriz? Simdi bu sorunun cevabını verelim:

Yazılmıs Sınıfların Kullanılması

Bazı özel durumların dısında, en genel biçimiyle bir sınıf nesnesi ya da bildigimiz sekliyle bir sınıf türünden degisken,

su sekilde yaratılır:

SinifAdi degisken = new SinifAdi();

Mesela, az önce yazmıs oldugumuz "DegiskenTutan" isimli sınıf türünden bir degisken de:

DegiskenTutan a = new DegiskenTutan();

seklinde yaratılmaktadır. Bu yaratma islemini baska bir sınıf içerisinden yapabilirsiniz. Burada vurgulanması gereken

en önemli nokta, yaratılan her sınıf degiskeninin (a’nın) aslında gerçek sınıfın bir kopyası oldugudur (instance). Yani

biz yukarıdaki gibi a isimli ve DegiskenTutan türünde bir sınıf nesnesi ve yine aynı sekilde

DegiskenTutan b = new DegiskenTutan();

b isimli baska bir DegiskenTutan isimli sınıf nesnesi yarattıgımızda, bu iki nesne de artık kendilerine ait birer "setX"

ve "getX" metodları ile bir "x" degiskeni barındırmaktadır. A nesnesinin "x" degiskeni ile b nesnesinin "x" degiskeni

artık farklıdır. Ama ikisinin de bir "x" degiskeni vardır. Yine aynı sekilde "a" nesnesi ile "b" nesnesinin "setX" ve

"getX" metodları vardır ama her metod kendi nesnesine ait olan "x" degiskeni üzerinde islem yapabilir.

45

Simdi "DegiskenTutan.java" dosyası ile aynı klasör içerisinde yer alan "GenelSinif" isimli yeni bir sınıf daha yaratalım

ve bu yeni sınıf içerisinde de "DegiskenTutan" isimli sınıfı kullanalım:

import javax.swing.*;

public class GenelSinif {

public static void main(String arg[]) {

DegiskenTutan a = new DegiskenTutan();

DegiskenTutan b = new DegiskenTutan();

a.setX(10);

b.setX(20);

String message = "a daki x degeri: "+a.getX();

message += "\nb deki x degeri: "+b.getX();

JOptionPane.showMessageDialog(null, message);

System.exit(0);

}

}

Simdi yazmıs oldugumuz bu sınıfları kaydettikten sonra çalıstırabilmek için su islemleri yapmamız gerekmektedir.:

Öncelikle komut satırında bu sınıf dosyalarını yazmıs oldugunuz dizin içerisine cd komutu

yardımıyla giriniz. Örnegin bu dizin linux kullanıcıları için "/home/academytech/kodlar" ya da

windows kullanıcıları için "C:\kodlar" ise, dizin içerisine girmek için:

$cd /home/academytech/kodlar

ya da

C:\> cd kodlar

yazmanız gerekmektedir.

2 Simdi sırasıyla "DegiskenTutan.java" dosyasını ve "GenelSinif.java" dosyasını derleyelim:

javac DegiskenTutan.java

javac GenelSinif.java

46

3 Son olarak da GenelSinif.java dosyasını çalıstıralım:

java GenelSinif

Not:

 

Burada görüyoruz ki "DegiskenTutan.java" dosyası sadece derleniyor ancak GenelSinif.java gibi sonra da

çalıstırılmıyor. Bunun nedeni asıl çalısan programın "GenelSinif" olması "DegiskenTutan" sınıfının ise sadece

kullanılıyor olmasıdır. Çünkü "GenelSinif" sınıfı içerisinde "main" metodu vardır. Bununla ilgili ayrıntılı açıklamayı

yazının ilerleyen kısımlarında zaten bulabileceksiniz.

Örnegimizde 7. ve 8. satırlarda DegiskenTutan sınıfı türünden "a" ve "b" isimli 2 degisken ya da iki

"DegiskenTutan" sınıfı nesnesi yaratılmaktadır. Daha sonra 9. satırda a nesnesinin "setX" metodu "a" nesnesinin "x"

degiskeni degerini 10, "b" nesnesinin "setX" metodu da "b" nesnesinin "x" degiskeninin degerini 20 yapmaktadır.

Dikkat ederseniz "a" ve "b" nesneleri de "setX" ve "getX" metodlarına sahiptir ve bu metodları kullanmak için nesne

adından sonra "." isareti ve sonra da metod adını yazmak gerekir. "a" ve "b" nesnelerinin tıpkı "DegiskenTutan"

sınıfı gibi metodlara ve degiskenlere sahip olmalarının nedeni, bu nesnelerin de yaratılırken "DegiskenTutan" sınıfı

türünden yaratılmıs olmalarıdır.

12. ve 13. satırlarda hazırlanan "message" isimli String degiskeni içerisine ekranda görülecek yazı ve "getX"

metodları yardımıyla "a" ve "b" nesnelerinin "x" degiskenlerinin içerisindeki degerler hazırlanmaktadır. En son olarak

da "message" isimli degisken içerisinde hazırlanan bu son görüntü "JoptionPane" isimli sınıfın "showMessageDialog"

isimli metodu yardımıyla ekrana gönderilmektedir.

Bu örnekten çıkaracagımız sonuç sudur; Genel olarak yazılmıs sınıfların kullanılabilmesi için öncelikle bu sınıflar

türünden degiskenler yaratılarak bu sınıfların birer kopyası ya da nesnesi çıkarılmalı ve sınıfa ait degisken ve

metodlar bu nesneler aracılıgıyla kullanılmalıdır. Ayrıca gördügümüz gibi bir sınıfa ait metodlar kullanılırken sınıf

nesnesinden sonra "." isareti ve daha sonra da metodun adı yazılmaktadır.

Bu örnegimizde "a" ve "b" isimli sınıf nesneleri yaratıldıktan sonra, sahip oldukları "x" degiskenlerine "setX" metodu

ile degerler verilmektedir. Peki eger biz daha nesneyi yaratorken hemen o anda "x" degiskenine deger vermek

istersek ne olacak? Bunun için "baslangıç metodu" kavramını bilmemiz gerekir.

Sınıfların Baslangıç Metodları (Constructors):

Sınıfların baslangıç metodları bizim bildigimiz anlamda metodlardan biraz daha farklıdır. Bu metodların en önemli

özelligi, bir sınıf nesnesi yaratılırken otomatik olarak çagrılmalarıdır. Mesela "DegiskenTutan" sınıfı türünden bir

nesne yaratılırken aslında "new" anahtar sözcügünden sonra bir metod çagrıldıgını görmekteyiz:

DegiskenTutan a = new DegiskenTutan();

1ste bu "DegiskenTutan()" isimli metod, "DegiskenTutan" isimli sınıfın baslangıç metodudur. Peki o zaman baslangıç

metodlarının normal metodlardan farkı nedir?

1 Baslangıç metodları kesinlikle ve kesinlikle sınıf ismiyle aynı olmak zorundadır. Eger baslangıç metodunun ismini

verirken sınıf isminden farklı bir isim kullanırsanız bu metod artık baska bir metod olarak kabul edilir. Örnegin:

DegiskenTut -> Yanlıs. Sınıf ismi DegiskenTutan o halde baslangıç metodunun ismi bu olamaz

Degiskentutan -> Yanlıs. Sınıf isminde T harfi de büyük. 1sim, büyük küçük harf bazınbda da aynı olmak

zorundad?r.

2 Baslangıç metodları geri dönüs degerine sahip degildir. Yalnız burada geri dönüs degeri void demek

istemiyorum. Baslangıç metodlarının geri dönüs degeri gibi bir kavramları yoktur. void ile yok baska anlamlara

gelir.

3 Bir sınıfın birden fazla baslangıç metodu olabilir. Bütün baslangıç metodları da sınıf ismiyle aynı olmak

zorundadır ancak her birinin parametreleri birbirlerinden farklı olmak zorundadır.

47

Biz baslangıç metodlarını genelde bir sınıf türünden bir nesne yaratırken, bu nesnenin degiskenlerine birtakım ilk

degerler vermek amacıyla yazarız. Aslında tasarladıgımız bir sınıfa baslangıç metodu yazmak zorunda degiliz. Ancak

baslangıç metodu yazmamıssak, nesne yaratılırken Java

 

otomatik olarak bizim yerimize bos bir hayali baslangıç

metodu yazar ve onu çagırır. Eger yazmıssak bizim yazdıgımız baslangıç metodunu çagırmaktadır.

Simdi tüm bu anlattıklarımızı "DegiskenTutan" sınıfımıza baslangıç metodları ekleyerek irdeleyelim. Ama bu sefer

"DegiskenTutan" ve "GenelSinif" isimli sınıfları "DegiskenTutan2" ve "GenelSinif2" olarak degistirelim. Tabi aynı

degisikligi dosya isimlerinde de yapmayı unutmayalım:

/*** DegiskenTutan2.java ***/

class DegiskenTutan2 {

int x;

public DegiskenTutan2() {

this.x = 0;

}

public DegiskenTutan2(int c) {

this.x = c;

}

public void setX(int c) {

this.x = c;

}

public int getX() {

return this.x;

}

}

/*** GenelSinif2.java ***/

import javax.swing.*;

public class GenelSinif2 {

public static void main(String arg[]) {

DegiskenTutan2 a = new DegiskenTutan2();

DegiskenTutan2 b = new DegiskenTutan2(2);

String message = "a daki x degeri: "+a.getX();

message += "\nb deki x degeri: "+b.getX();

JOptionPane.showMessageDialog(null, message);

System.exit(0);

}

}

Bu örnekte görüyoruz ki; "GenelSinif2" dosyasının 7. satırında, "a" isimli "DegiskenTutan2" türünden sınıf degiskeni,

"DegiskenYutan2" sınıfının 5. satır?nda tanımlanan bos olan baslangıç metodu ile yaratılıyor ve bu metodun

içerisinde de "a" nesnesinin "x" degiskenine 0 degeri veriliyor. Ancak "GenelSinif2" çerisinde 8. satırda yaratılan "b"

isimli ve "DegiskenTutan2" türündeki nesne, "DegiskenTutan2" isimli sınıfın 9. satırda tanımlanmıs ve int parametre

alan baslangıç metoduyla yaratıldıgı için bu "b" nesnesine ait olan "x" degiskeni nesne yaratılırken verilen 2 degerini

alıyor. Bu örnekte, bir sınıf türünden nesne yaratılırken yapılmasını istedigimiz birtakım ilk islemleri baslangıç

metodları yardımıyla yaptırabildigimizi görüyoruz.

NOT:

 

Baslangıç metodları sadece nesne yaratılırken çagrılır. Baska bir zamanda bu metodların çagrılmasına izin

verilmez.

48

main Metodu

Su ana kadar dikkat ederseniz "main" metodu ile ilgili çok az ayrıntıdan bahsettim. Aslında bu metod da birtakım

özelliklere sahip özel bir metoddur. Simdi yukarıda yapmıs oldugumuz örneklere bir göz atmanızı istiyorum. Bu

örnekler de "GenelSinif" isimli sınıf içerisinde "main" metodu varken "DegiskenTutan" isimli sınıfın içerisinde böyle

bir metod yok. Ama her iki örnek de düzgün bir sekilde çalısabiliyor. Bunun nedenini söyle açıklayalım:

Bu ana kadar gördük ki bir sınıf nesnesi ilk önce yazılmakta ve daha sonra da kullanılmaktadır. Ancak kullanılmadan

önce tüm nesneler öncelikle "javac" komutu ile derlenmelidir. 1ste bir java dosyasının "javac" ile derlenmesi

isleminden sonra bir de "java" komutu ile çalıstırılabilmesi için, o java dosyası (ya da sınıfı) içerisinde "main"

metodu olması gerekir. Yani çalıstırılabilir sınıfların main metodunu sahip olmaları gerekir. Aksi takdirde

java <Sinif_adi>

komutundan sonra ekranda asagıdaki gibi "main" metodunun bulunamadıgına dair bir mesaj ile karsılarsınız:

"java.lang.NoSuchMethodError: main"

Ancak "DegiskenTutan" gibi sadece baska bir sınıf içerisinde kullanılmak üzere tasarlanmıs sınıflar dogrudan

çalıstırılmayacagı için, onların içerisinde main metodu olmasına gerek yoktur. Bu tür sınıfların yukarıdaki örnekte de

görüldügü gibi sadece derlenmesi, kullanılabilmeleri için yeterli olacaktır.

Özetle; yazdıgımız programlarda birbirinden farklı görevleri üstlenmis bir çok sınıfı barındıran java dosyaları ve

hepsini en son olarak tek çatı altında toplayacak ve asıl programın çalısmasını saglayacak genel bir sınıfımız

olacaktır. Ve tüm bu sınıflar içerisinde sadece ana programı çalıstıracak olan bu genel sınıf içerisinde "main" metodu

olmalıdır. Diger sınıfları kullanabilmeniz için, genel sınıf da dahil olmak üzere hepsini java ile derlemelisiniz. Ancak

programı çalıstırmak için sadece genel sınıfı java komutu ile çalıstırmanız yeterlidir.

Sonuç olarak; bir sınıf java ile çalıstırıldıgı zaman, otomatik olarak içerisindeki main metodu çagrılacaktır. Eger sınıf

içerisinde main metodu yoksa, böyle bir sınıf "javac" ile derlenebilir ancak "java" ile çalıstırılamaz!

main Metodu parametreleri:

"main" metodunun su ana kadar hiç deginmedigimiz bir özelligi de aldıgı parametrelerdir. Bu metod yazılırken

görmekteyiz ki

public static void main(String arg[])

seklinde bir String dizisini parametre olarak almaktadır. "1yi de bu parametre ne ise yarıyor?" diye merak ettiginizi

tahmin ediyorum. Artık bunu ögrenme zamanım?z geldi. Öncelikle asagıda verilen "MainParametreleri.java" isimli

sınıfı yazıp kaydediniz:

class MainParametreleri {

public static void main(String arg[]) {

System.out.println("1. parametre:"+arg[0]);

System.out.println("2. parametre: "+arg[1]);

System.exit(0);

}

}

Simdi asagıda gösterildigi gibi bu sınıfı önce javac komutu ile derleyip daha sonra java komutunun bu özel kullanımı

ile çalıstırınız:

javac MainParametreleri.java

java MainParametreleri bir iki

49

Bu sekilde sınıfı çalıstırdıgınızda ekranda söyle bir çıkıs göreceksiniz.

1. parametre:bir

2. parametre: iki

1ste burada, java komutu ile "MainParametreleri" sınfını çalıstırırken sırasıyla verdiginiz "bir" ve "iki" isimli bu iki

String degeri, main metodunun pototipinde tanımlanmıs olan "arg" isimli String dizisine atulmıstır. "main"

metodunun paramtresi olan bu "String arg[]" dizisi bu örnekte oldugu gibi bir sınıf çalıstırılırken kullanıcının vermek

istedigi parametreleri alır ve daha sonra program içerisinde kullanılabilmesi için saklar. Örnek programımızın 5. ve

6. satırlarında "arg[0]" ve "arg[1]" ile bu girilen parametreleri kullanabildigimzi görmekteyiz. Buradaki kullanma

seklimiz bu parametreleri sadece ekrana yazmak gibi anlamsız bir islem gibi görünse de daha sonra ise yarar

sekillerde kullanabilecegimizi düsünebiliriz.

1. parametre: bir

2. parametre: iki

Sınıfların public ve private Metod ve Degiskenleri

Su ana kadar belirli isleri yapabilmek amacıyla metod ve degiskenleri birarada tutan nesneleri yaratmayı ve

kullanmayı, yani sınıfların genel olarak kullanımını görmüs olduk. Bir sınıf içerisinde çesitli metod ve degiskenler

tutuyor ve daha sonra biz de bu sınıf türünden nesneler yaratarak bu metod degiskenleri kullanabiliyoruz.

Bazen bir sınıf içerisinde yazılan metod ya da degiskenleri sadece sınıfın içerisinde kullanmak isteyebiliriz. Yani

baska bir yerde bu sınıf türünden yaratılan bir degisken ile kullanmayacagımız ancak sınıfın kendi içinde kullanılması

gereken metod ve degiskenler olabilir. Bunu anlamak için "DegiskenTutan" sınıfına tekrar dönelim. Biz

"DegiskenTutan" sınıfı türünden bir "a" nesnesi yarattıgımızda "a" nesnesi kendisine ait olan "x" degiskenini:

a.x = 10;

seklinde degistirebilir. Ancak biz bu sekilde bir müdaheleye izin vermek istemiyor olabiliriz. Eger "a" nesnesinin "x"

degiskeni degistirilecekse, böyle bir islemin "setX" gibi bir metodla yapılmasını, degiskene "a.x" diyerek dogrudan

erisilememesini istiyor olabiliriz. 1ste bu durumlarda sınıf içerisine "x" degiskeninin basına bir "private" anahtar

sözcügü eklememiz gerekir. Yani "DegiskenTutan" sınıfında "x" degiskeninin bildirimi:

class DegiskenTutan {

private int x;

public Degiskentutan() {

...

seklinde olursa, artık "DegiskenTutan" türünden "a" gibi bir nesne yaratılsa bile, "a.x" gibi bir erisim yasaklanmıs

olur. Ancak sınıf içerisindeki bir metod "x" degiskenine yine de ulasabilir.

Eger genel olarak özetlemek gerekirse; sınıflar içerisinde bildirilen "private" türündeki degiskenlere dısarıdan

erisilemez, ancak sınıfın diger metodları ile erisilebilir.

Bu durum sınıfın private metodları için de geçerlidir. Eger sınıf yazılırken bir metodun basına "private" anahtar

sözcügü eklenirse, bu metod da artık dısarıdan erisilemez, sadece sınıf içerisindeki diger metodlar tarafından

kullanılabilir bir hale gelir. Mesela "DegiskenTutan" isimli sınıfa asagıdaki gibi bir "private" metod ekleyelim

 

:

class DegiskenTutan {

private int x;

...

private void resetX() {

this.x = 0;

}

...

50

public setX(int c) {

this.resetX();

this.x = c;

}

}

Bu sekilde "private" olarak bildirilmis "resetX" metodu artık bu sınıf türünden yaratılmıs nesneler ile dısarıdan

kullanılamaz. Yani asagıdaki gibi bir kullanım geçersizdir:

class BaskaSinif {

public static void main(String arg[]) {

DegiskenTutan a = new DegiskenTutan(2);

a.resetX();

/* YANLIS! resetX private bir metoddur

Bu sekilde dısarıdan kullanılamaz.*/

...

}

}

En son örnekte gördügünüz gibi "a.resetX()" gibi bir çagrım geçerli degildir. Çünkü "DegiskenTutan" sınıfının

"resetX" isimli metodu "private" bir metoddur. Bu nedenle, bu sınıf türünden yaratılmıs olan "a" nesnesi aracılıgıyla

bu metoda dısarıdan erisilemez. Ancak önceki örnekteki gibi "resetX" metodunu sınıfın diger bir metodu olan "setX"

metodu kullanabilmektedir. Degisken ya da metodların "private" ya da "public" olması, bu metod ya da

degiskenlerin sadece dısarıdan kullanımı etkileyen bir durumdur. Sınıf içerisindeki diger metodlar bu "private"

degisken ya da metodlara erisebilirler.

Tüm bunların bir sonucu olarak da , sınıflar yazılırken yaratılan "public" metod ve degiskenler, sınıf nesneleri

aracılıgıyla dısarıdan erisilebilirler.

Statik Metod ve Degiskenler

Su ana kadar ögrendiklerimizi ele aldıgımızda neden

 

JOptionPane sınıfının showMessage isimli metodunu

kullanmak için JOptionPane sınıfı türünden bir nesne yaratmıyoruz? diye sormamız gerekir.

Bazı metodlar yazıldıkları sınıflar içerisinde statik olarak yazılırlar. Bu türden statik olarak yazılmıs metodları

kullanmak için sınıf nesnesi yaratmak gerekmez. Bu metodları kullanmak için yazıldıkları sınıf isminden sonra "."

isareti koyarak dogrudan metodu çagırabilirsiniz.

Ancak tahmin edersiniz ki bir metod statik olarak yazılmıssa genel amaçlı bir metod olmalıdr. Mesela JOptionPane

isimli sınıfın showMessageDialog ya da showInputDialog isimli metodları genel amaçlı olup her zaman

kullanılabilmektedir. Ekrana bir mesaj penceresi çıkarmak ya da kullanıcıdan bir giris degeri almak için bir nesne

yaratmaya gerek yoktur. Siz de kendi tasarladıgınız sınıflar içerisinde bu sekilde genel amaçlı metodlar yazmak

isterseniz bunları statik olarak yaratabilirsiniz.

Bir metodun statik olarak yaratılabilmesi için, metodun prototipinin basına "static" anahtar sözcügü eklenir.

Asagıdaki iki örnegi yazıp kaydediniz:

import javax.swing.*;

class StatikTest {

String mesaj;

public StatikTest() {

mesaj = "";

}

public StatikTest(String m) {

this.mesaj = m;

}

public static void ozelMesaj(String m) {

JOptionPane.showMessageDialog(null, m);

51

}

public void kayitliMesaj() {

JOptionPane.showMessageDialog(null, this.mesaj);

}

}

class GenelSinif3 {

public static void main(String arg[]) {

StatikTest.ozelMesaj("Bu mesaji dogrudan gosterdim");

StatikTest a = new StatikTest("Bu mesaj icin nesne yarattim");

a.kayitliMesaj();

}

}

Bu örnegi çalıstırdıgınızda ekrana iki tane mesajın geldigini göreceksiniz. Bu mesajlardan ilki, "GenelSinif3" isimli

sınıfın 5. satırında, "StatikTest" sınıfının statik metodu dogrudan çagrılarak ekrana gelmistir. Gördügümüz gibi,

 

bir

sınıfın statik metodunu kullanmak için

 

ilk önce o sınıf türünden bir nesne yaratmaya gerek yoktur.

Çünkü statik metodlar sınıf ismi ve sonra ". " isareti yazıldıktan sonra dogrudan çagrılabilirler. Ancak ikinci mesaj

"StatikTest" sınıfının "kayitliMesaj" isimli ve statik olmayan metodu sayesinde ekrana geldiginden, bu metodu

kullanabilmek için ilk önce "StatikTest" sınıfı türünden bir nesne yaratılması ve metodun da bu nesne aracılıgıyla

çagrılması gerekir.

Uygulama Sorusu:

 

1çerisinde tarih tutan ve tarihlerle ilgili islemler yapabilen metodları barındıran bir sınıf

tasarlayınız. Yapılması gereken islemler:

a. iki tarihin birbiriyle kıyaslanması,

b. tarih üzerine belirli bir gün sayısı eklenebilmesi,

c. tutulan tarihin gösterilmesi,

d. tutulan tarihin degistirilmesi seklinde olmalıdır.

Bu islemlerin her biri için sınıf içerisinde bir metod tasarlamanız gerekmektedir. Böyle bir sınıfın günü, ayı ve yılı

tutan degiskenleri olmalıdır. Sınıfı tasarladıktan sonra, bu sınıfı kullanan ve bu sınıf türünden örnek nesneler

yaratarak bunları kullanan baska bir genel sınıf yazınız ve tasarımınızı bu nesneler üzerinde test ediniz.

Nihayet bu dersimizin de sonuna gelmis bulunuyoruz. Nesne yönelimli programlama tekniginin özünü olusturan

sınıfları ve sınıfların kullanımını ögrendigimiz bu dersimizi iyice sindirmenizi ve örnekleri de tekrar yazarak kendi

basınıza denemenizi ısrarla öneririm.

Uygulama Sorusu2:

 

Icerisinde array tutan (int turunden) bir sinif yaratiniz (IntArray). Bu sinif icerisinde tuttugu

bu array i dinamik olarak genisletebilmelidir. Ozetle bu sinifta asagidaki metdolar yer almalidir.

void add(int toAdd);

void add(int []toAddArray);

int findMax();

int findMin();

int remove(int index);

int display();

int reverseDisplay();

public IntArray(int a);

public IntArray(int []a);

public IntArray();

52

Java ile Programlama

Bölüm 6:

Sort yontemleri (bubble sort ve selection sort) anlatılacak.

ODEV

 

: String diziyi sort eden bir metod ornegi (Bir sonraki derste inceleyecegiz)

Uygulama Sorusu (Derste yapilacak):

Sınıfların dizilere parametre olarak gönderilmesine iliskin ornekler

- Person turunden bir sinif yarat (isim, yas)

- Bu sinif turunden elemanlari olan bir array yarat

- Bu arrayi bir metoda gonder ve ekranda goruntule

- Sonra compareTo metodunu Person sinifina ekle ve sort bilgisiyle bu sefer bu listeyi sirala

public class Person {

private String name;

private int age;

public Person() {

this.setName("No person");

this.setAge(0);

}

public Person(String name, int age) {

this.setName(name);

this.setAge(age);

}

public String toString() {

return "Person Name: " + this.getName() + "\nPerson Age: " +

this.getAge();

}

public static void sortPersonArray(Person p_array[]) {

/*for(int i = 0; i < p_array.length; i++)

for(int j = 0; j < p_array.length; j++)

if(p_array[i].compareTo(p_array[j]) > 0)

swap(p_array[i], p_array[j]);*/

for(int i = 0; i < p_array.length; i++)

for(int j = i+1; j < p_array.length; j++)

if(p_array[i].compareTo(p_array[j]) > 0)

swap(p_array[i], p_array[j]);

}

private static void swap(Person p1, Person p2) {

Person temp = new Person();

temp.setAge(p1.getAge());

temp.setName(p1.getName());

p1.setAge(p2.getAge());

p1.setName(p2.getName());

p2.setAge(temp.getAge());

p2.setName(temp.getName());

}

53

public int compareTo(Person p) {

return this.getName().compareTo(p.getName());

}

/**

* @return Returns the age.

*/

public int getAge() {

return age;

}

/**

* @param age The age to set.

*/

public void setAge(int age) {

while(age < 0)

age = Integer.parseInt(

JOptionPane.showInputDialog(null, "Yas bilgisi 0 ya da

daha kucuk olamaz!\nTekrar giriniz"));

this.age = age;

}

/**

* @return Returns the name.

*/

public String getName() {

return name;

}

/**

* @param name The name to set.

*/

public void setName(String name) {

this.name = name;

}

public static void main(String[] args) {

Person array[] = {new Person("ali", 12), new Person("ahmet", 24), new

Person("zeren", 13)};

Person.sortPersonArray(array);

for(int i = 0; i < array.length; i++)

System.out.println(array[i]);

}

}

Bu derse kadarki derslerimizde artık nesne yönelimli programlama tekniginin merkezinin olusturan sınıfların ne

anlama geldiklerini ve nasıl tasarlandıklarını ögrenmistik.

Bugün tasarımını ayrıntılı olarak ögrendigimiz sınıfların kullanımına iliskin bazı örnekler üzerinde duracagız. Ayrıca

Java'da öntanımlı olarak bulunan ve kendi özeli islerimiz için kullanabilecegimiz sınıfların bazılarını da görmüs

olacagız. Size tavsiyem burada

 

anlatılan ekleri mutlaka kendi basınıza da yazıp denemenizdir.

Sınıfların Kendi Kendilerini Kullanmaları:

Bundan önceki örneklerimizde bir sınıfın yazıldıktan sonra, baska bir sınıf içerisinde ya da örneklerde yaptıgımız gibi

main metodu içerisinde kullanılabildigini görmüstük. Bazı sınıflar otomatik olarak çalıstırılabilmek amacıyla da

54

yazılabilirler. Bir sınıfın otomatik olarak çalısabilmesi için içerisinde main metodu olması gerektigini zaten biliyoruz.

1ste bu sekilde main metodu içerisinde bir sınıf, kendisi türünden nesne yaratıp bunu kullanabilir.

1sin özü aslında sudur: Bir sınıf yazıldıktan sonra, bu sınıf türünden nesneleri istedigimiz her metod ya da her sınıf

içerisinde artık yaratıp kullanabiliriz. Bu genel kuralı bilirsek, zaten sınıf nesnelerinin ne zaman ve nerede

yaratılacagına dair bir problemimiz de kalmaz.

Asagıdaki örnegimizde, matematikte kullanılan karmasık sayılara iliskin deger ve metodları barındıran bir sınıf

yazacagız. Bu sınıf aynı zamanda “main” metodu içerecek ve kendisi türünden nesneler yaratarak bu nesneler

üzerinde islemler yapacak:

Simdi bu örnegimizi biraz inceleyelim. Sınıfımızın iki adet baslangıç metodu oldugunu görmekteyiz. Bu metodlardan

birtanesi, 6. satırda tanımlanmakta ve hiçbir parametre almadan yaratılan KarmasikSayi nesnesinin “gercel” ve

“imajinel” isimli degiskenlerini 0.0 degerine esitlemektedir. Diger baslangıç metodu ise 11. satırda tanımlanmaktadır

55

ve nesne yaratılırken kendisine verilen parametreleri kullanarak “gercel” ve “imajinel” degiskenlerinin degerlerini

atamaktadır.

NOT:

 

Sınıfın kendisine ait olan degisken ve metodlarını sınıf içerisinde kullanırken, bu degisken ve metodların

basına “this.” eklemis olduguma dikkat ediniz. Daha önce de söyledigim gibi this anahtar sözcügü sınıfın kendisini

temsil eder. Örnegin 12. satırda “this.gercel” ifadesi, “o anda içerisinde bulundugumuz sınıfa ait olan gercel isimli

degiskeni” temsil etmektedir.

16. satırda tanımlanan “topla” isimli metod parametre olarak baska bir “KarmasikSayi” nesnesi alarak, bu sayının

“gercel” ve “imajinel” degiskenleri ile sınıfın kendi “gercel” ve “imajinel” degerleri toplamını elde eder ve bu

degerlerle, “sonuc” adında yeni bir “KarmasikSayi” nesnesi yaratarak bu degiskeni 19. satırda geri döndürür. Buna

benzer sekilde 22. satırda yazılmıs olan “cikart” metodu da aynı islemi çıkartma için yapar. Ancak bu metod biraz

daha ilginç bir yöntemle deger döndürmektedir. Bu sefer sonucu tutacak ayrı bir degisken yaratmak yerine, 23.

satırda oldugu gibi “return” anahtar sözcügünün önünde yeni bir “KarmasikSayi” nesnesi yaratılarak hemen o anda

döndürülür. Bu yöntemde arada “sonuc” gibi baska bir degisken içerisinde “KarmasikSayi” nesnesi yaratma ihtiyacı

ortadan kalkmaktadır.

Yazdıgımız Sınıfların toString metodu:

Dikkat ederseniz 35. satırda “toString” adında ilginç bir metod yer almaktadır. Bu metod aslında main metodu

içerisinde hiç çagrılmamıstır. Ancak ilginçtir ki, 47. satırdaki “sayi1” isimli sınıf degiskeni ekrana yazılmak istendigi

zaman sanki bu metod çagrılmaktadır. Çünkü ekranda toString metodunun döndürdügü String ifadesi yazılmaktadır.

Aslında gerçekten de 47. satırda sayi1 degiskeninin ekrana basıldıgı noktada otomatik olarak bu metod çagrılır.

Yazılan tüm sınıflara aslında toString metodu da eklenebilir. Eger

“String toString()”

prototipini bozmadan sınıfınız içerisinde bir toString metodu yazarsanız, bu sınıfa iliskin bir sınıf degiskenini ekrana

basmak istediginizde bu metod otomatik olarak çagrılmaktadır. Ancak metodun içini istediginiz gibi yazabilirsiniz.

Eger yazdıgınız sınıf içerisinde bu metodu eklemez ve bu sınıf türünden bir degiskeni ekrana basmak isterseniz, o

zaman Java otomatik olarak bir toString metodunu kendisi yazacak ve buna iliskin bir String degeri de dödürecektir.

Ancak bu deger oldukça anlasılmaz bilgiler içermektedir. Özetle sınıfınızı nasıl ifade etmek istiyorsanız, buna iliskin

String toString() prototipli bir metod yazabilirsiniz.

Öntanımlı Java Sınıflarının Kullanımı:

Dersimizin bundan sonraki kısmında yeni bir konuya geçmeden önce, Java'da öntanımlı bazı sınıflara iliskin örnekler

yapmakta yarar görüyorum. Görecegimiz bu sınıflar, yazacagımız programlarda birçok yükü üzerimizden almakta

ve bize bazı yararlı hazır metodlar sunmaktadır. Bu nedenle isimizi görecek ve daha önceden yazılmıs bu hazır sınıf

ve metodları kullanarak zaman kaybı ve zahmetten kurtulabiliriz.

Bir konuda sizleri uyarmak isterim: Burada bu öntanımlı java sınıflarının tüm metodlarını detaylı bir sekilde

göstermek yerine, bu sınıflar hakkında bilgi sahibi olmanızı ve sadece birkaç metod kullanımıyla sınıfı sizlere

tanıtmayı hedefledim. Kendi uygulamalarınız için burada genel olarak ögrenmis oldugunuz bu sınıfların size uygun

metodlarını ve burada gösterilmeyen baska öntanımlı sınıfları java dökümantasyonu ve internette yapacagını

aramalar ile bulabilirsiniz. Java dökümantasyonunun online halini:

“http://java.sun.com/j2se/1.4.2/docs/api/index.html” adresinde bulabilirsiniz.

Özetle buradaki örnekleri sizlere sadece neyi nerede arayacagınızı bilmeniz açısından veriyorum. Simdi bu sınıfları

incelemeye baslayalım.

Math Sınıfı:

Bu sınıf çesitli matematiksel islemleri yapabilecegimiz metodları sunmaktadır. Bu metodlar içerisinde sin, cos, tan,

kuvvet alma, kök alma v.b. metodlar bulunmaktadır. Bu sınıfı kullanabilmeniz için uygulamalarınızın basında

herhangi bir kütüphaneyi “import” etmenize gerek yoktur. Asagıda Math sınıfınının bazı metodlarının kullanımına

iliskin bir örnek verilmektedir. Bu örnek, daha önce yapmıs oldugumuz karmasık sayı sınıfının biraz

 

daha

gelistirilmis hali ve Math sınıfının fonksiyonlarının kullanıldıgı bir örnektir. Ayrıca bu sınıfa “aciHesapla” adında yeni

bir metod daha eklenmis ve sınıfın içerisinde saklanan karmasık sayının açı degerleri bu metod yardımıyla

hesaplanmıstır.

56

Simdi örnegimizi daha detaylı inceleyelim. Herseyden önce genel bir noktayı vurgulamak istiyorum. Dikkat

ederseniz “KarmasikSayi2” sınıfının 23, 24, 27 satırlarında, “gercel” ve “imajinel” degerlerini “this.gercel” diyerek

dogrudan almak yerine bu degerleri 13 ve 16. satırlarda yazılmıs olan “gerceliVer” ve “imajineliVer” metodları

yardımıyla alıyoruz. Bunun nedeni sınıfın veri elemanlarını korumak ve böylece sınıf hiyerarsisini düzgün bir sekilde

kurmak içindir.

Bu teknik bizlere oldukça önemli ve saglam bir mekanizma sunar. Zaten dikkat ederseniz “gercel” ve “imajinel”

isimli veri elemanları da dısarıdan dogrudan erisimin engellenmesi amacı ile 7. satırda “private” olarak

tanımlanmıstır. Veri elemanlarına erisimin bu sekilde kontrollü olarak yapılması gerekir. Eger bu elemanlara

erisilmek gerekiyorsa, bu isi dogrudan degil de set ve get metodları gibi metodlar yardımıyla yapmak gerekir.

Kullanıcıya sadece bu metodlar sunulmalı, sınıfın veri elemanlarına erisim ise metodlar içerisinde ve gerektigi gibi

yapılmalıdır.

23. satırda kullanılan “Math.pow” isimli metod 1. parametre ile aldıgı sayının, 2. parametre ile aldıgı sayı kadar

kuvvetini hesaplar ve sonucu geri döndürür. Bu metodu “gercel” ve “imajinel” kısımların karelerini hesaplamak için

kullandık. Bu karelerin toplamının da karekökünü, tahmin ettiginiz gibi Math.sqrt metodu ile elde ettik. Yani özetle;

57

Math.pow degerleri ile elde edilen “gercel” ve “imajinel” kısımların karelerinin toplamını, Math.sqrt metoduna

paramtere olarak dogrudan göndererek sonucu da dogrudan geri döndürdük. Sizler de bol bol program yazdıkça

bu tip hızlı yazım tekniklerinizi gelistireceginizden emin olabilirsiniz. Ancak pratik olması amacıyla kısa kodlar

yazarken bile kodunuzun okunabilir olmasına dikkat ediniz.

Örnegimizin 27. satırında kullandıgımız “Math.atan2” isimli metod kendisine parametre olarak verilen “y” ve “x” gibi

iki sayının polar koordinatlarda sahip oldugu açı degerini hesaplayan bir metoddur. Yani aslında yaptıgı islem y/x

degerinin arktanjant degerini hesaplamaktır. Fakat geri dönen bu deger radyan cinsindendir. Bu nedenle, radyan

olarak elde edilen açı degeri 29. satırda yazılan “aciyiDereceVer” metodu ile derece olarak da elde edilebilir.

Hızlı bir sekilde listelemek gerekirse Math sınıfının bazı diger metodları sunlardır:

int Math.abs(int a) a sayısının mutlak degerini geri döndürür. Aynı metodun

float, double ve long türler için de versiyonları vardır.

double Math.acos(double a) a sayısnın ters kosinüs degerini döndürür. Benzer sekilde

asin ve atan metodları da vardır.

double Math.cos(double a) a sayısnın cosinüz degerini geri döndürür. Benzer sekilde

sin metodu da vardır.

double Math.exp(double a) a sayısnın e sayısını kuvveti olarak hesaplar ve bu degeri

döndürür.

int Math.max(int a, int b) a ve b sayılarından büyük olanın degerini geri döndürür.

Benzer sekilde bu metodun double, int, float ve long

versiyonları da vardır.

double Math.random() 0 ile 1 arasında rastgele pozitif bir sayı üretir ve bu degeri

döndürür.

DecimalFormat Sınıfı:

Java ile yazdıgımız programlarda sayısal degerler çogu zaman anlasılması zor ve gereksiz uzunlukta üretilir. Ancak

Java bizim için sayının ne kadar uzunlukta olması gerektigini otomatik olarak bilemez ve bu nedenle en dogru ve

orjinal sekilleriyle bu degerleri üretmektedir. Eger yukarıdaki örnegi yazıp çalıstırdıysanız, elde edilen sonuçların (açı

degerleri gibi) virgülden sonra oldukça fazla miktarda basmak içerdigini görmüssünüzdür.

DecimalFormat sınıfı, sayıları istedigimiz gibi ifade edebilmemize olanak saglar. Bu sınıfın kullanımına iliskin bir

örnek yazalım:

Örnegimize dikkat edersek, “DecimalFormat” sınıfını kullanmadan önce 4. satırda oldugu gibi

“java.text.DecimalFormat” kütüphanesini programa dahil etmeliyiz. 9. satırda yaratılan bir DecimalFormat nesnesi

yapmak istedigimiz ifade biçimini String bir deger olarak tutmaktadır. Bu nesne yaratıldıktan sonra, nesne

58

aracılıgıyla istenilen bir sayı “format” metodu kullanılarak 13. satırda oldugu gibi biçimlendirme yapılabilir. “format”

metodunun geri dönüs degeri String bir degerdir.

Sargı Sınıfları:

Java'da yaygın olarak kullanılan sınıflar arasında sargı sınıfları da vardır. Bu sınıflar aslında genel olarak aynı

prensiple kullanılır. Bı sınıfları kullanmaktaki amaç bilinen temel türleri (integer, float, double gibi) String türüne ya

da tersine, String türündeki bir ifadeyi temel türlere dönüstürmektir. Aslında bu tür sınıflara olan ihtiyacı örnek

üzerinde açıklarsak daha anlasılır olacaktır.

Mesela en son yaptıgımız “OndalikKisim” sınıfı örneginde, 10. satırda tanımlanan “a” degiskeni içerisindeki degerin

biçimlendirilmis hali String türünde elde edilmektedir. Ancak biz bu biçimlendirilmis hal ile baska matematiksel

islemler yapmak istedigimizde String türündeki bu sonuç isimize yaramayacaktır. Bu sonucun tekrar double türünde

elde edilmesi gerekir. Bunun için String türünde elde edilen bu deger “Double.parseDouble” metodu ile tekrar

double türüne dönüstürülebilir. Bu metodun örnek kullanımı:

...

double yeniBicim = Double.parseDouble(ikiHane.format(a));

..

seklinde olacaktır. Bu dönüsümleri yapan diger bazı sargı sınıfları ve metodları da sunlardır:

int Integer.parseInt(String str) str ile gelen String biçimindeki sayıyı integer

biçiminde geri döndürür.

String Integer.toString(int a) integer türündeki a sayısının String türünde

degerini geri döndürür.

double Double.parseDouble(String str) str ile gelen String biçimindeki sayıyı double

biçiminde geri döndürür.

String Double.toString(double a) double türündeki a sayısının String türünde

degerini geri döndürür.

float Float.parseFloat(String str) str ile gelen String biçimindeki sayıyı float biçiminde

geri döndürür.

String Float.toString(float a) float türündeki a sayısının String türünde degerini

geri döndürür.

String String.valueOf(int a) integer türündeki a sayısnın String degerini geri

döndürür. Aynı metodun double, float, ve long türünde

parametre alan versiyonları da vardır

ArrayList Sınıfı:

Daha önce ögrenmis oldugumuz diziler konusundan bildigimiz gibi bir dizi yaratıldıktan sonra artık otomatik olarak

boyutu degismiyordu. Siz diziyi belirli bir uzunlukta açtıktan sonra dizinin tüm alanları doluysa, yeni bir eleman

eklemek için birtakım algoritmik yöntemler uygulamanız gerekir. Ya da diziden bir eleman çıkardıgınız zaman, diger

elemanları birer basmak geri kaydırmak gibi birtakım isleri de yapmanız gerekir.

“ArrayList” sınıfı bu tür görevleri otomatik olarak yapan ve bize dinamik olarak kullanabilecegimiz bir dizi

mekanizması sunan bir sınıftır. Eger böyle bir diziye sahip olmak istiyorsanız asagıdaki sekilde bir “ArrayList”

nesnesi tanımlamanız gerekir:

ArrayList dinamikDizi = new ArrayList();

Daha sonra bu nesneyi artık kendi dizinismis gibi düsünerek “ArrayList” sınıfının sundugu metodlar yardımıyla

eleman ekleme, çıkartma ve bulma gibi islemler yapabilirsiniz. Mesela “dinamikDizi” nesnesine eleman eklemek için:

dinamikDizi.add(“merhaba”);

ya da

int a = 3;

dinamikDizi.add(a);

59

ArrayList sınıfının yukarıda gördügümüz gibi “add” isimli metodunun yanısıra diger metodlarından bazıları da

sunlardır:

void remove(int index) Dizinin verilen indeks numarasındaki elemanını çıkartır ve

diziyi buna göre düzenler. Örnek kullanım:

int a = dinamikDizi.remove(2); //2.eleman siliniyor

int size() Dizinin içerisindeki elelman sayısını verir. Örnek kullanım:

int a = dinamikDizi.size();

Object get(int index) Dizinin index nolu elemanını geri döndürür. Örnek kullanım:

String str = dinamikDizi.get(0);

int indexOf(Object o) o ile temsil edilen nesnenin dizi içerisindeki indeks nuaarasını

geri döndürür. Eger eleman dizide yoksa -1 geri döndürür.

Asagıdaki “KayitListesi.java” uygulamamızda hem böyle bir dinamik dizi kullanımını, hem de bugüne kadar

ögrendiklerimizle gerçege oldukça yakın bir java uygulamasının yazımını görmekteyiz. Bu uygulama çalıstıgında,

ekrana resimdeki gibi bir menü sunulmakta ve kullanıcının yaptıgı seçimlerle kayıt ekleme, silme, kayıtları listeleme

gibi islemler yapıldıktan sonra tekrar aynı menü ekrana gelmektedir. Kullanıcıya istedigi zaman programdan

çıkabilecegi bir seçenek de sunulmaktadır.

60

61

KayitListesi.java Uygulamasındaki Nesne Yönelimli Programcılık zleri

Uygulamamız içerisinde , her seçime iliskin bir metod uygun isi üstlenmektedir. Ayrıca tüm alt görevleriyle ve

degiskenleriyle birlikte bu uygulama tek bir sınıf altında ve tek bir amaç için olusturulmustur. Programlarınızda bu

sekilde is bölümü yapma islemi nesne yönelimli programcılıgın baslıca presiplerinden birisidir.

Yazmıs oldugumuz bu uygulama tek bir sınıf nesnesi olarak tasarlanmıs ve 106. satırdaki main metodu içerisinde de

bir degisken aracılıgıyla çalıstırılmıstır. Ayrıca dikkat ederseniz uygulamamızın bazı metodları “private” olarak

tasarlanmıstır. Bunun nedeni; bu metodların iç mekanizma isleyisi için kullanılıyor olmasıdır. Yani 109. satırda

oldugu gibi kullanıcı, bu sınıfın “uygulamaBaslat” metodunu çagırabilmeli ancak diger metodlarını çagıramamalıdır.

Bu metodların hangi sırada ve ne zaman çagrılacagı program içerisinde sınıfın kendisi tarafından ve uygun bir

hiyerarsi ile belirlenmektedir. Bu nedenle, bir degisken üzerinden erisilmemesi istenen metodlar private olarak

tasarlanmıstır. Böylece bu metodlara, sadece sınıfın diger metodlarının erisebilmesine izin verilmektedir. Kullanıcının

hizmetine ise sadece “public” metodlar sunulmaktadır.

StringBuffer Sınıfı:

Daha önceki derslerimizde ögrendigimiz üzere String sınıfı bazı yararlı metodlara sahiptir. Hatta bu metodlardan

“equals” ve “matches” isimli olanlarını da, “KayitListesi.java” uygulamamızda 19.satırda ve “toUpperCase” isimli

olanı da 37. satırda kullanmaktayız.

Bu metodlar sayesinde çesitli kolaylıkları olan String türünde degiskenlerin içerikleri sabit uzunluktadır. Bu nedenle

içerigi de dinamik olarak degistirilebilen bir sınıf türüne ihtiyaç duyulmaktadır. Bu amaçla StringBuffer isimli sınıf

kullanılabilir.

StringBuffer sınıfı kullanılmadan önce bu sınıf türünden bir nesne yaratılmalıdır:

StringBuffer strbuffer = new StringBuffer();

Bu sekilde, içerisinde hiç karakter tutmayan ve 16 karakter kapasiteli bir StringBuffer nesnesi yaratılabilir. Bu sınıfın

baska baslangıç metodları da vardır. Mesela 20 karakter kapasiteli bir nesne yaratmak için

 

:

StringBuffer strBuf = new StringBuffer(20);

Ya da hazır bir String degiskenini StringBuffer halinde yaratmak için:

StringBuffer str = new StringBuffer(“Merhaba”);

yazmak gerekir. Bu sınıf içerisinde tutulan String degerinin String olarak kullanılabilmesi için, sınıfa ait olan toString

metodu kullanılabilir. Mesela az önce “Merhaba” String degeri ile yaratmıs oldugumuz “str” isimli StringBuffer

nesnesinin String degeri:

String a = str.toString();

seklinde elde edilebilir.

Bu sınıfın sahip oldugu bazı metodlar sunlardır:

StringBuffer append(String) StringBuffer nesnesi içerisinde tutulan String sonuna

parametre ile verilen String degerini ekler ve bu yeni hali

StringBuffer nesnesi olarak geri döndürür. Bu metodun int,

float, double, char [] parametreli versiyonları da vardır.

int capacity() Nesnenin sahip oldugu karakter kapasitesini verir.

void ensureCapacity(int minCapacity) Nesnenin kapasitesini minCapacity parametresi ile verilen

deger haline getirir.

char charAt(int index) Nesnenin tuttugu String degeri içerisinde verilen indekste yar

alan karakteri geri döndürür.

StringBuffer reverse() Nesnenin içerisinde tutulan String degerininin ters çevrilmis

halini geri döndürür.

62

Ancak yine de hatırlatmak isterim ki StringBuffer sınıfının daha birçok metodu vardır. Diger metodları her zaman

söyledigim gibi Java dökümantasyonu içerisinde bulabilirsiniz.

NumberFormat ve DecimalFormat Sınıfı: Çıkısın Biçimlendirilmesi

Asagıdaki gibi bir numerik hesap yaptıktan sonra

x = 10000.0/3;

System.out.println(x) metodu yardımıyla bu sonucu ekranda görüntüleyebiliriz.

Ancak ekrana gelecek olan bu görüntü 3333.333333335 seklinde olacaktır. Oysa biz çıkısın daha anlamlı olmasını

isteyebiliriz. Bunun için DecimalFormat sınıfından yararlanıyoruz.

import

 

 

java.text.DecimalFormat;

public class

 

 

Main {

public static void

 

 

main(String[] args) {

DecimalFormat formatter =

 

new DecimalFormat("0.0000 YTL");

double

 

 

x = 100.0/3.0;

System.

 

out.println(x);

System.

 

out.println(formatter.format(x));

}

}

Ayrıca sistemde tanımlı olan yerel sayı, para birimi (currency) gibi degerleri kullanmak için de NumberFormat

sınıfından yararlanabiliyoruz

 

.

import

 

 

java.text.NumberFormat;

import

 

 

java.util.*;

public class

 

 

Main {

public static void

 

 

main(String[] args) {

NumberFormat formatter = NumberFormat.getCurrencyInstance();

formatter.setMaximumFractionDigits(4);

formatter.setMaximumIntegerDigits(6);

formatter.setMinimumIntegerDigits(6);

double

 

 

y = 1000.0/3.0;

String s = formatter.format(y);

System.

 

out.print(s);

}

}

GregorianCalendar Sınıfı

Java’da tarihlerle ilgili islemler yapmak için kullanılabilecek 2 tane sınfı vardır.

Tarihte herhangi bir noktayi ifade etmek için “Date” sınıfı kullanılabilir.

import

 

 

java.util.Date;

public class

 

 

Main {

public static void

 

 

main(String[] args) {

63

Date d1 =

 

new Date();

d1.setYear(1999-1900);

d1.setDate(12);

d1.setMonth(0);

Date d2 =

 

new Date();

d2.setTime(System.currentTimeMillis());

 

//1,1,1970 den bugune kadar gecen

milisaniye

if

 

 

(d1.before(d2))

System.

 

out.println(d1 + " tarihi, " + d2 + " tarihinden daha once

geliyor"

 

 

);

System.

 

out.print(d1 + "\n" + d2);

}

}

GregorianCalendar sınıfı, Date sınfından daha fazla metoda sahiptir.

GregorianCalendar ile kullanabileceginiz baslangıç metodları:

new GregorianCalendar()

new GregorianCalendar(1999, 11, 31);

new GregorianCalendar(1999, Calendar.DECEMBER, 31, 23, 59, 59)

GregorianCalnedar kullanarak zamanı elde etme ve istedigimiz gibi degistirmeye

iliskin temel metodlar sunlardır:

GregorianCalendar simdi = new GregorianCalendar();

int month = simdi.get(Calendar.MONTH);

simdi.setTime(Calendar.MONTH, 3);

simdi.add(Calendar.MONTH, 3);

import

 

 

java.util.Calendar;

import

 

 

java.util.GregorianCalendar;

public class

 

 

Main {

public static void

 

 

main(String[] args) {

GregorianCalendar simdi =

 

new GregorianCalendar();

int

 

 

ay = simdi.get(Calendar.MONTH);

int

 

 

gun = simdi.get(Calendar.DAY_OF_WEEK);

int

 

 

yil = simdi.get(Calendar.YEAR);

int

 

 

tarih = simdi.get(Calendar.DATE);

int

 

 

saat = simdi.get(Calendar.HOUR);

int

 

 

dakika = simdi.get(Calendar.MINUTE);

int

 

 

saniye = simdi.get(Calendar.SECOND);

System.

 

out.println("Tarih: " + tarih + " " + hangiAy(ay) + " " + hangiGun(gun)

+

 

" " + yil);

System.

 

out.println("Saat: " + saat + ":" + dakika + ":" + saniye);

}

public static

 

 

String hangiAy(int n) {

64

switch

 

 

(n) {

case

 

 

0:

return

 

 

"Ocak";

case

 

 

1:

return

 

 

"Subat";

case

 

 

2:

return

 

 

"Mart";

case

 

 

3:

return

 

 

"Nisan";

case

 

 

4:

return

 

 

"Mayis";

case

 

 

5:

return

 

 

"Haziran";

case

 

 

6:

return

 

 

"Temmuz";

case

 

 

7:

return

 

 

"Agustos";

case

 

 

8:

return

 

 

"Eylul";

case

 

 

9:

return

 

 

"Ekim";

case

 

 

10:

return

 

 

"Kasım";

case

 

 

11:

return

 

 

"Aralık";

}

return

 

 

"Jupiter ";

}

public static

 

 

String hangiGun(int n) {

switch

 

 

(n) {

case

 

 

1:

return

 

 

"Pazar";

case

 

 

2:

return

 

 

"Pazartesi";

case

 

 

3:

return

 

 

"Sali";

case

 

 

4:

return

 

 

"Carsamba";

case

 

 

5:

return

 

 

"Persembe";

case

 

 

6:

return

 

 

"Cuma";

case

 

 

7:

return

 

 

"Cumartesi";

}

return

 

 

"Pazoncesi ";

}

}

ODEV:

Dinamik buyuyen int array dizisini double, String ve int turleri icin genellestirip gerekli tum metodlari da barindiran

bir DinamicArray nesnesi yaratiniz.

Önümüzdeki derste Sınıfların Türetilmesi konusunu detaylı bir sekilde inceleyecegiz.

65

Java ile Programlama

Bölüm 9 - 10

Stringler

Daha önce de sıkça kullanıdıgımız String türünde degiskenler asılnda ilkel degiskenlerden biraz daha farklıdır.

Burada ilkel kelimesinden kasıt her dilde tanımlı olan ve java’da da yer alan en temel degiskenlerdir. Java’da

String’ler bu temel olma durumunun biraz daha üstünde nesnelerdir. Zaten String nesnelerinin kendilerine ait bazı

metodların olması da bu durumu açıkça göstermektedir. Teknik olarak Stringler karakter dizileridir.

Bir String nesnesi ile kullanılabilecek özel metodları söyle listelyebiliriz:

a)

 

int length(): Nesnenin içerisindeki karakter uzunlugunu verir.

b) char charAt(int index):

 

Nesne içerisinde istenen indexteki karakteri verir.

c) String substring(int start, int end):

 

start ve end indeksleri arasındaki küçük string parçasını verir.

d) String toUpperCase():

 

String nesnesinin tüm karakterlerini büyük harfe çevirir.

e) String toLowerCase():

 

String nesnesinin tüm karakterlerini küçük harfe çevirir.

f) String trim():

 

String nesnesi içersindeki boslukları ortadan kaldırır ve yeni bvir string üretir.

g) int indexOf(String str):

 

String nesnesi içerisinde “str” string parçasını arar ve buldugu ilk indexi

gönderir.

h) boolean equals(String str):

 

String nesnesini parametre olarak verilen str ile karsılastırır. Esitlik

durumunda true, diger durumda false degerinin üretir.

i) boolean equalsIgnoreCase(String str):

 

equals ile aynı isi yapar ama büyük küçük harf durumuna

dikkat etmez.

j) String valueOf(int a):

 

Verilen ilkel tipi String’e çevirir. Parametresi diger türleri de alabilir.

Çok Boyutlu Diziler

Çok boyutlu diziler aslında her elemanı baska bir dizi olan dizilere çok boyutlu diziler denilir.

ODEV

1) Bir çift boyutlu dizinin tüm elemanlarinin toplamini bulan bir metod yaziniz:

a. 1nt findTotal(int arr[][]);

2) Verilen bir çift boyutlu diziyi dortgn haline getiren bir metod yaziniz. Verilen

 

dizinin her elemani ayni

uzunlukta olmayabilir.

a. 1nt [][] makeSquare(int arr[][]);

66

Odev:

Magic Square bulma

Bir cift boyutlu dizi eger her satirinin toplami, her sutunun toplami ve her iki ana diagonalin toplami esitse ve dizi

kare ise (satir ve sutun sayisi esit) bu dizi magic’tir.

Bu islemi yapan ve prototipi

public static boolean isMagic(int array[][])

bir metod yaziniz.

1pucu: Programi parcalara bolunuz. Mesela sadece tek boyutlu bir dizinin toplamini bulan ya da bir cift boyutlu

dizinin sadece i. Sutunun toplamini bulan ya da bir cift boyutlu diznizn sadece 1. ya da sadece 2. ana diagonalinin

toplamini bulan metdolari ayri ayri tasarlayiniz ve daha sonra bunlari ana programda kullaniniz.

Sınıfların Türetilmesi

Sınıfların türetilmesi kavramını söyle bir örnekle açıklamaya çalısalım: Diyelim ki çok büyük bir programlama

projesinin bir kısmında görev aldınız. Öyle ki sizin yapmanız gereken kısım bir ekran üzerine yerlestirilecek olan

seçenek dügmelerinin tasarımı olsun. Ancak bu islemi yapabilmeniz için elinizde herseyden önce bir ekran

görüntüsünün olması lazım. O halde öncelikle bir ekran görüntüsü olusturan program parçası, ya da artık yeni

ögrendigimiz kavramlara dayanarak, temel ekran islemlerini barındıran sınıf olması gerekmektedir. Ancak sizin asıl

isiniz olmadıgından, ekran islemlerine iliskin bir sınıf yazmanız ve daha sonra da kendi dügmelerinizi de bu sınıf

içerisine eklemeniz gereksiz bir is olacaktır. Ayrıca bu ekran islemleri gibi temel nitelige sahip ve sizin dısınızda diger

kisilerin de baska islemler için ihtiyaç duyabilecegi bir sınıf kendi basına ayrı bir sekilde tasarlanmalıdır. Eger bu

sınıfın temel özelliklerini koruyarak, üzerine herkesin ihtiyaç duyacagı yeni özelliklerle birlikte yeni bir sınıf haline

getirilecegi bir mekanizma olursa, önceden harcanan emek de yeni islemler için temel teskil edecek nitelikte olup,

gereksiz is gücü kaybı engellenmis olacaktır.

1ste Java'da bu mekanizmaya sınıfların türetilmesi denilir. Sekilde türetme iiliskisine iliskin bir örnek yer almaktadır.

67

Buna göre sekildeki “TemelSinif”tan türetilen “Sinif 1” ve “Sinif 2” isimli sınıfların islevleri “Temel Sınıf”ın islevlerini

de içermektedir. Buna göre “Sinif 1”; kendi içerisinde yer alan “x”, “y” ve “z” degiskenleri ile “X” metodunun yanı

sıra, “TemeSinif” dan türedigi için “a”,”b” degiskenleri ile “A”, “B” metodlarına da sahip olmaktadır. Benzer sekilde

“Sinif 2”, kendisinde yer alan “k” degiskeni ile “K”, “L” ve metodları ve türetme iliskisi yüzünden “a”, “b”

degiskenleri ile “A” ve “B” metodlarına da sahip olmaktadır.

Sekilde bu türetme iliskisinin “Sinif 1” ve “Sinif 2” den “TemelSinif”a dogru giden oklarla gösterilmesi bir yanlıslık

degil, kasten yapılmaktadır. Nesne yönelimli programlamada türetme iliskisi genellikle bu sekilde, yani, türetilmis

sınıftan türetilen sınıfa dogru gösterilmektedir.

Örnek Uygulama 1

O halde kavramsal olarak inceledigimiz türetme islemini bir de uygulamalı olarak görelim. Kisi.java, Ogrenci.java ve

KisiDeneme.java dosyalarından olusan klasik örnekte bir kisi kaydını temsil eden bir sınıftan, bir ögrenci kaydını

temsil eden farklı bir sınıf türetilmektedir.

class Kisi {

String isim;

String adres;

char cinsiyet;

public Kisi(String gelenIsim, char gelenCinsiyet, String gelenAdres) {

this.isimSetEt(gelenIsim);

this.adresSetEt(gelenAdres);

this.cinsiyetSetEt(gelenCinsiyet);

}

public void isimSetEt(String yeniIsim) {

this.isim = yeniIsim.toUpperCase();

}

68

public void adresSetEt(String yeniAdres) {

this.adres = yeniAdres.toUpperCase();

}

public void cinsiyetSetEt(char gCinsiyet) {

if(gCinsiyet != 'e' && gCinsiyet != 'k') {

System.out.println("Cinsiyet bilgisi \"e\" ya da \"k\"

olmali.");

System.out.println("Yanlis bir deger girdiniz...");

System.out.println("Program sonlaniyor");

System.exit(0);

}

else

this.cinsiyet = gCinsiyet;

}

public String ismiGetir() {

return this.isim;

}

public String adresiGetir() {

return this.adres;

}

public char cinsiyetiGetir() {

return this.cinsiyet;

}

public String toString() {

String str="";

str += "Kisi Bilgileri\n";

str += "Isim: "+this.ismiGetir()+"\n";

str += "Cinsiyet :"+this.cinsiyetiGetir()+"\n";

str += "Adres: "+this.adresiGetir()+"\n";

return str;

}

}

Örnekte, türetme islemine maruz kalan sınıfın “Ogrenci” isimli sınıf oldugunu görmekteyiz. Bu nedenle “Ogrenci”

isimli sınıf yaratılırken sınıf bildiriminin devamına “extends” anahtar sözcügü ve daha sonra da bu sınıfın türetildigi

temel sınıf olan “Kisi” sınıfının adı yazılmaktadır

 

.

class Ogrenci extends Kisi {

String bolum;

int donem

 

;

public Ogrenci(String ad, char cns, String adr, String blm, int dnm) {

super(ad, cns, adr);

this.bolumSetEt(blm);

this.donemiSetEt(dnm);

}

public String bolumuGetir() {

return this.bolum;

}

69

public void bolumSetEt(String yBolum) {

this.bolum = yBolum.toUpperCase();

}

public int donemiGetir() {

return this.donem;

}

public void donemiSetEt(int yDonem) {

this.donem = yDonem;

}

public String toString() {

String str = super.toString();

str += "Bolum: "+this.bolumuGetir()+"\n";

str += "Donem: "+this.donemiGetir()+"\n";

return str;

}

}

Böylece Ogrenci sınıfı artık aynı zamanda bir “Kisi” sınıfı haline gelmis ve kendi degisken ve metodlarının yanı sıra,

“Kisi” sınıfının degisken ve metodlarına da sahip olmustur. Bu nedenle “Ogrenci” sınıfını yazarken bir daha isim,

cinsiyet ve adres degiskenleri ve bu degiskenler ile ilgilenen gerekli metodları yazmaya gerek yoktur.

class KisiDeneme {

public static void main(String arg[]) {

Ogrenci o1 = new Ogrenci("Dogac Berkun", 'e', "Kurtulus Cd. No 24",

"Bilgisayar Bilimleri", 2);

System.out.println(o1);

o1.donemiSetEt(3);

System.out.println(o1);

}

}

KisiDeneme.java dosyasındaki “main” metodu içerisinde en son olusturdugumuz “Ogrenci” sınıfını kullanarak bir

nesne yaratmaktayız. Daha sonra da önceden ögrendigimiz “toString” metodu islevinden yararlanarak (bkz. Bölüm

6) olusturdugumuz bu “Ogrenci” türünden nesneyi ekrana basmaktayız.

Sınıflarda super Metodu:

En son yazdıgımız “Ogrenci” sınıfının baslangıç metodu içerisinde “super” isimli

 

ilginç bir metod kullanılmaktadır.

Oysa “Ogrenci” isimli sınıfın böyle bir metodu yoktur. O halde hiç yazılmamıs olan bu metod nedir?

Baska bir sınıftan türetilmis olan sınıflarda, “super” ile temsil edilen metod, türetmenin yapıldıgı sınıfın baslangıç

metodunu temsil etmektedir. O halde bizim örnegimizde “Ogrenci.java” dosyasının 7. satırındaki

super(ad, cns, adr);

kullanımı ile “Ogrenci” sınıfının türedigi “Kisi” sınıfının uygun parametreli baslangıç metodunun çagrıldıgını

söyleyebiliriz. Böylece “KisiDeneme.java” dosyasında kullanıcı “Ogrenci” nesnesini yaratırken, aslında arka planda,

bu “Ogrenci” nesnesinin içerisinde yer alan “Kisi” nesnesine ait kısımlar, “Kisi” nesnesinin baslangıç metodu ile

olusturulmakta ve daha sonra da “Ogrenci” nesnesinin kendisine ait olan kısımlar olusturulmaktadır. Fakat bu

islemlerin hepsi neticede “Ogrenci” nesnesinin baslangıç metodu içerisinde yapılmaktadır. “Ogrenci” nesnesi “Kisi”

nesnesinden türedigi için, bünyesinde “Kisi” nesnesine ait kısımları da barındırmakta ve dolayısı ile “super” metodu

yardımıyla gerektiginde “Kisi” nesnesinin baslangıç metodlarına ya da “Ogrenci.java” dosyasının 29. satırında

oldugu gibi “Kisi” nesnesini baska metod ve degiskenlerine erisme hakkına sahip olmaktadır.

70

Örnek Uygulama 2

Simdi örnegimizi biraz daha genellestirelim ve bu sefer içerisinde “Ögrenci2” sınıfı türünden nesneleri tutan ve bu

nesneler ile ilgili çesitli islemler yapan bir “Kayitlar” isimli bir sınıf tasarlayalım.

class Kisi2 {

String isim;

char cinsiyet;

public Kisi2(String gelenIsim, char gelenCinsiyet) {

this.isimSetEt(gelenIsim);

this.cinsiyetSetEt(gelenCinsiyet);

}

public void isimSetEt(String yeniIsim) {

this.isim = yeniIsim.toUpperCase();

}

public void cinsiyetSetEt(char gCinsiyet) {

if(gCinsiyet != 'e' && gCinsiyet != 'k') {

System.out.println("Cinsiyet bilgisi \"e\" ya da \"k\" olmali.");

System.out.println("Yanlis bir deger girdiniz...");

System.out.println("Program sonlaniyor");

System.exit(0);

}

else

this.cinsiyet = gCinsiyet;

}

public String ismiGetir() {

return this.isim;

}

public char cinsiyetiGetir() {

return this.cinsiyet;

}

public String toString() {

String str="";

str += "Kisi Bilgileri\n";

str += "Isim: "+this.ismiGetir()+"\n";

str += "Cinsiyet :"+this.cinsiyetiGetir()+"\n";

return str;

}

}

class Ogrenci2 extends Kisi2 {

String bolum;

int donem;

int ogrenci_no;

String ortalama;

71

public Ogrenci2(String ad, char cns, String blm, int dnm, int ogrNo, double ort)

{

super(ad, cns);

this.bolumSetEt(blm);

this.donemiSetEt(dnm);

this.numaraSetEt(ogrNo);

this.ortalamaSetEt(ort);

}

public String bolumuGetir() {

return this.bolum;

}

public void bolumSetEt(String yBolum) {

this.bolum = yBolum.toUpperCase();

}

public int donemiGetir() {

return this.donem;

}

public void donemiSetEt(int yDonem) {

this.donem = yDonem;

}

public int numarayiGetir() {

return this.ogrenci_no;

}

public void numaraSetEt(int ogrNo) {

this.ogrenci_no = ogrNo;

}

public String ortalamayiGetir() {

return this.ortalama;

}

public void ortalamaSetEt(double yeniOrt) {

if(yeniOrt < 1.0)

this.ortalama = "F";

else if(yeniOrt >= 1.0 && yeniOrt < 1.5)

this.ortalama = "D";

else if(yeniOrt >= 1.5 && yeniOrt<2.0)

this.ortalama = "C";

else if(yeniOrt >= 2.0 && yeniOrt<3.6)

this.ortalama = "B";

else if(yeniOrt >= 3.6 && yeniOrt <= 4.0)

this.ortalama = "A";

}

public String toString() {

String str = super.toString();

str += "Bolum: "+this.bolumuGetir()+"\n";

str += "Donem: "+this.donemiGetir()+"\n";

str += "Ogrenci No: "+this.numarayiGetir()+"\n";

str += "Ortalamasi: "+this.ortalamayiGetir()+"\n";

return str;

}

}

72

class Kayitlar {

Ogrenci2 dizi[];

public Kayitlar() {

}

public Kayitlar(Ogrenci2 yeniEleman) {

this.dizi = new Ogrenci2[1];

this.dizi[0] = yeniEleman;

}

public void ekle(Ogrenci2 eklenecekOgr) {

if(this.dizi == null) {

dizi = new Ogrenci2[1];

this.dizi[0] = eklenecekOgr;

}

else {

Ogrenci2 tmp[] = new Ogrenci2[dizi.length+1];

for(int i=0; i < dizi.length; i++)

tmp[i] = dizi[i];

tmp[tmp.length-1] = eklenecekOgr;

this.dizi = tmp;

}

}

public void cikart(int id) {

Ogrenci2 tmp[] = new Ogrenci2[dizi.length-1];

int indeks=-1;

for(int i=0; i < dizi.length; i++)

if(dizi[i].numarayiGetir() == id)

indeks = i;

for(int i=0; i < indeks; i++)

tmp[i] = dizi[i];

for(int i = indeks; i < dizi.length-1; i++)

tmp[i] = dizi[i+1];

dizi = tmp;

}

public void listele() {

System.out.println("Kayitlar listeleniyor:");

System.out.println("--------------------");

for(int i=0; i < dizi.length; i++)

73

System.out.println(""+dizi[i]);

}

public Ogrenci2 enBuyukOrtalamaliOgrenci() {

Ogrenci2 max=dizi[0];

for(int i=0; i < dizi.length; i++) {

if(dizi[i].ortalamayiGetir().compareTo(max.ortalamayiGetir()) == -1)

max = dizi[i];

}

return max;

}

}

class KayitlarDeneme {

public static void main(String arg[]) {

Kayitlar x = new Kayitlar();

x.ekle(new Ogrenci2("Evren Banger", 'e',"Bilgisayar", 2, 100, 2.54));

x.ekle(new Ogrenci2("Aykut Toygar", 'e',"Bilgisayar", 2, 101, 2.4));

x.ekle(new Ogrenci2("Hande Kumek", 'k', "Bilgisayar", 3, 102, 3.5));

x.ekle(new Ogrenci2("Ilker Kara", 'e', "Bilgisayar", 2, 103, 1.55));

x.ekle(new Ogrenci2("Cemile Caglar", 'k',"Isletme", 4, 201, 3.7));

x.ekle(new Ogrenci2("Erdem Aykac", 'e', "Isletme", 4, 202, 3.58));

x.listele();

Ogrenci2 sonuc = x.enBuyukOrtalamaliOgrenci();

System.out.println("En buyuk ortalamali ogrenci: \n"+sonuc);

}

}

Bu sınıf daha önceki derslerimizde yazmıs oldugumuz “KayitListesi” sınıfını andırmakla beraber, bu sefer sınıfın veri

elemanı bu kayıtları tutacak “Ogrenci2” türünden bir dizi olacaktır. Bu arada , “Ogrenci2” sınıfı da bir önceki örnekte

kullandıgımız “Ogrenci” sınıfına çok benzer olup sadece bazı metodları degistirilerek yeniden yazılmıstır. Özetle bu

örnek “Kisi2.java”, “Ogrenci2.java” ve “Kayitlar.java” dosyalarından olusmakta ve en son olarak

“KayitlarDeneme.java” dosyasında çalıstırılmaktadır.

Simdi de gelelim bu uygulamanın detaylı bir incelemesine: “KayitlarDeneme.java” dosyasındaki main metodu

içerisinde “Kayitlar” sınıfı türünden bir nesne yaratılmıs ve bu nesneninin “ekle” isimli metodu yardımıyla birtakım

“Ogrenci2” sınıfı türünden nesneler hemen o anda parametre olarak yaratılarak listeye eklenmistir. Bu “Ogrenci2”

türünden nesneleri önce degisken olarak yaratıp daha sonra “ekle” metdouna parametre olarak gönderebilirdik.

Örnegin:

...

Ogrenci2 o2 = new Ogrenci2("Evren Banger", 'e',"Bilgisayar", 2, 100, 2.54)

x.ekle(o2);

...

Ancak bizim kullanıdıgımız yöntem hem daha pratik hem de gereksiz degiskenlerden arınmıs bir program yazmamızı

saglamaktadır.

“Kayitlar.java” sınıfının içerisindeki

public Kayitlar(Ogrenci2 yeniEleman)

74

prototipli baslangıç metodu daha önce hiç kayıt eklenmemis durum için tek elemanlı yeni bir “Ogrenci2” dizisi

yaratır ve “yeniEleman” isimli “Ogrenci2” türünden parametreyi de bu diziye ekler. Yine “Kayitlar” sınıfının

metodlarından birisi olan ekle isimli metod da durumu iki türlü ele alır. Eger daha önce hiç kayıt eklenmemisse önce

tek elemanlı bir “Ogrenci2” dizisi açılarak bu kayıt diziye eklenir (satır 16-18). Ama zaten daha önceden eklenmis

kayıtlar varsa o zaman ilk olarak eski diziden 1 eleman fazla uzunlukta “tmp” adında yeni bir geçici dizi yaratılır

(satır 22), daha sonra eski dizinin tüm elemanları bu diziye de kopylanır (satır 24-25) ve en son olarak da bu tmp

dizisinin fazla olan sondaki bos eleman yerinde de metoda parametre olarak gönderilen “eklenecekOgr” isimli

“Ogrenci2” nesnesi yerlestirilir (satır 27). Tüm bu islemlerin sonunda da artık kayıtların son halini tutan “tmp” dizisi,

sınıfın kendi dizisi olan “dizi” isimli “Ogrenci2” dizisine atanır (satır 28).

Buna benzer olarak; sınıfın cıkart isimli metodu da çıkarılacak olan elemanının dizideki indeks numarasını

saptadıktan sonra (satır 37-39) bu elemana kadar olan ve bu elemandan sonraki tüm elemanları “tmp” dizisine

kopyalar (satır 41-42 ve 44-45) ve “tmp” dizisini yine sınıfın asıl dizisi haline getirir (satır 47).

“Kayitlar” sınıfının “public Ogrenci2 enBuyukOrtalamaliOgrenci()” isimli metodu ise “Ogrenci2” nesnelerinin

ortalamarına bakarak en yüksek ortlamalı “Ogrenci2” nesnesini geri dönüs degeri olarak gönderir. Geriye dönen bu

deger “KayitlarDeneme.java” dosyasında bir “Ogrenci2” degiskeninde tutularak (satır 16) ekrana basılır (satır 17).

Burada tekrar hatırlatmak isterim ki; “sonuc” adındaki “Ogrenci2” sınıf degiskeni 17. satırda oldugu gibi ekrana

basılmak istendiginde, aslında sonuc degiskeni aracılıgıyla ve “Ogrenci2” sınıfına ait olan “toString” isimli metod

otomatik olarak çagrılmaktadır ve bu metodun hazırlayıp gönderdigi String türünden ifade ekrana basılmaktadır.

Tabi ki bu ifadeyi hazırlayan da sınıfı yazan kisidir.

Umuyorum ki detaylı olarak hazılayıp anlatmaya çalıstıgım bu örnek ile birlikte, sınıfların tasarlanması, baska sınıf ve

metodlar içerisinde kullanılması ve türetilmesine iliskin kavramları daha rahat kavramıs olursunuz.

Uygulama Sorusu

Yukarıda verilen “Kayitlar” sınıfı örnegini biraz daha gelistirerek bu sınıfa ögrencileri not ortalamalarına göre, isim

sırlarına göre listeleyen ve sadece belirli bölümlerdeki ya da belirli dönemlerdeki ögrencileri görüntüleyen metodlar

ekleyiniz ve bu yeni sınıfın adını da “Kayitlar2” olarak degistiriniz. 1pucu olarak; yazmanız gereken bu metodların

prototiplerini asagıdaki sekilde verebiliriz:

public void notOrtalamasinaGoreListele()

public void isimSirasinaGoreListele()

public void bolumdekiOgrenciler(String bolumAdi)

public void donemdekiOgrenciler(int donem)

Sunu da belitmeliyim ki, “Kayitlar” sınıfına ekleyeceginiz bu metodların yanı sıra, eger gerekecegini düsünüyorsanız

mevcut metodların isleyislerini ya da bu sınıfın içerisinde kullanılan “Ogrenci2” sınıfının da yine bazı metodlarının

isleyisini degistirebilirsiniz.

Polymorphism ve Final Metodlar genel açıklama

Ornek:

class TemelSinif {

public void method() {

System.out.println("Temel sinifin metodu");

}

public final void method2() {

System.out.println("Temel sinifin final metodu");

}

}

75

class TuremisSinif1 extends TemelSinif {

/*Temel sinifin metodunu override etmis*/

public void method() {

System.out.println("TuremisSsinif_1 sinifin metodu");

}

/*Temel sinifin metodunu override etmis*/

public void method2() {

System.out.println("TuremisSsinif_1 sinifin final metodu");

}

}

class TuremisSinif2 extends TemelSinif {

}

class Main {

public static void main(String arg[]) {

TuremisSinif1 t1 = new TuremisSinif1();

TuremisSinif2 t2 = new TuremisSinif2();

TemelSinif tt = new TemelSinif();

t1.method();

t2.method();

tt = t1;

tt.method();

tt = (TemelSinif)t1;

tt.method();

}

}

Instanceof Ornek

public static void main(String[] args) {

Object ar[] = {new Student("A", 12, 1232, 2), new Sayi(13)};

for(int i = 0; i < ar.length; i++) {

if(ar[i] instanceof Student)

((Student)ar[i]).m_student();

else if(ar[i] instanceof Sayi)

((Sayi)ar[i]).m_sayi();

}

}

76

Sınıfların protected veri elemanları:

Daha önceden biliyoruz ki sınıflarda private olan bir degisken ya da metod sadece kendi sınıfının diger metodları

tarafından erisilebilir haldedir. Bununla beraber public sınıf elemanları, hem bu sınıfın diger metodları, hem de bu

sınıf türünden yaratılmıs olan nesneler tarafından, yani dısarıdan erisilebilir haldedir.

Eger bir sınıfın veri elemanı sadece bu sınıfın kendi metodları ya da bu sınıftan türetilmis sınıfların metodları ile

erisilebilir ancak dısarıdan erisilemez olsun isteniyorsa, böyle veri elemanlarının protected veri elemanı olarak

bildirilmesi gerekir. Bu durumda protected veri elemanlarının erisim bakımından public ve private veri elemanları

arasında bir seviyede oldugunu söyleyebiliriz.

Protected Metodlar

Bir sınfıfın bazı metodları protected olarak tasarlanabilir. Böyle metodlar da sadece sınıfı türeten alt sınıflar

içerisinde kullanılabilir ancak dısarıdan kullanılamazlar. Böylece sadece türetme yapan sınıflara güveniliyorsa ve

dısarıya kapatılmak isteniyora bir metod protected olarak tasarlanabillir. Bunun bir örnegini ileriki konularda

görecegimiz Object sınıfının protected metdu olan “clone” metodunu incelreken görecegiz.

Object Sınıfı

Su ana kadar sınıfların türetilmesine iliskin birçok sey ögrendik. O halde artık Java da temel bir sınıf olan Object

sınıfını da inceleyebiliriz. Java’da her sey bir nesnedir. Aslında bu tanım hem kavramsal hem de teknik anlamda

dogrudur.

Kavramsal olarak Java’da herseyin bir nesne oldugunu zaten bu noktaya kadar tartıstık. Teknik olarak da Java’da

herseyin bir nesne olması, Java’daki tüm tanımlı sınıfların aslında “Object” adı verilen özel bir sınıftan türemesi

anlamına gelmektedir.

Öyle ki sizin yazdıgınız bir sınıf da aslında öntanımlı olarak Object isimli sınıftan türemistir.

77

Object Sınıfının Metodlarının Yeniden Yazılması

Ayrıca daha önce ögrenmis oldugumuz “function overriding” kendi yarattıgımız sınıflarda Object sınıfının bazı

metodlarını kendi istegimize göre sınıfımız içerisinde degistirerek yazabiliriz. Aslında toString isimli metodun böyle

bir metod oldugunu bu noktada belirtmek gerekir

 

.

Object sınıfının toString Metodu

toString metodu Object sınıfında yazılmıs olan bir metoddur. Ancak daha önce de söyledigimiz gibi Java’da yazılan

her sınıf, hatta bizim kendi yazdıgımız sınıflar da dahil, birer Object sınıfı kabul edildiginden (yani otomatik olarak

bu sınıftan türediginden), Object sınıfına ait olan bu metodları kendi basımıza yazabiliriz.

Object sınıfının finalize Metodu

finalize() isimli metod da Object sınıfına ait bir metoddur. Bu metodu da kendi sınıfımıza göre yazabiliriz. Ancak

daha önce bu metodun ne iser yaradıgını bilmekte fayda var.

Önceden ögrendigimiz gibi bir sınıf yaratıldıgı zaman otomatik olarak uygun olan baslangıç metodu (constructor)

çagrılmaktadır. Ayrıca sistemde kullanılmayan nesnlerin de garbage collector yapısı ile otomatik olarak ortadan

aldırıldıgını da söylemistik.

1ste sınıflarda benzer sekilde bir sınıf ortadan kaldırılırken, yani islevi sonlandırılırken de otomatik olarak çalgrılan bir

metod vardır. Bu metod finalize() isimli bir metoddur. O halde nasıl baslangıç metodu içerisine sınıfımızın birtakım

ilk islemlerini yazıyorsak, finalize metodu içerisine de bir sınıf sonlanırken yapılması gereken son islemleri

tanımlayabiliriz. Bu son islemlere örnek olarak:

a) Daha önce açılmıs bir dosyanın kapatılması

b) Daha önce yapılmıs bir veri tabanının sonlandırılması

c) Daha önce açılmıs bir session’ın sonlandırılması

d)

 

Daha önceden kullanılan birtakım geçici degiskenlerin sonlandırılması

verilebilir.

Ancak sunu da belirtmek gerekir ki Java’da finzlize metodu Garbage Collector devreye girdigi zaman çagrıldıgı için

bu metodu tam olarak ne zaman çagrılacagı bilinemez. Bu nedenle bazen öngörülemeyen sonuçlar ortaya çıkabilir.

O halde sonuç olarak kullanıcı aslında kendi istedigi zaman çagırabilecegi birtakım son islemleri yapacak bir metodu

yine kendisi baska bir isimle yazabilir. Böylece son islemler dogru sırada ve kullanıcının istegine baglı olarak

yapılacaktır. Bu da finalize metoduna olan gerekliligi ortadan kaldırmaktadır.

Bunun dısında Object sınıfında baska metodlar da vardır. Ancak bu metodlar ilerde ögrenecegimiz bazı kavramları

gerektirdiginden simdilik Object sınıfına bu kadar deginecegiz.

Object Sınıfına Her Nesne Atanabilir

Java’da herseyin bir Object oldugunu tekrar hatırlayalım. Aslında Object isimli sınıf türünden bir degiskenin bu

nedenle her türden nesneyi tutabilecegini de söyleyebiliriz

 

.

public class

 

 

ObjectOrnek {

public static void

 

 

main(String[] args) {

Object dizi[] =

 

new Object[3];

dizi[0] =

 

"string nesnesi";

dizi[1] =

 

new Integer(13);

dizi[2] =

 

new Deneme();

}

78

}

class

 

 

Deneme {

}

Yukarıdaki örnekte Object türünden bir dizi yarattık. Bir dizi içerisinde tüm elemanların aynı türden olması gerektigi

halde birbirinden farklı türleri nasıl oluyor da bir dizide saklayabiliyoruz? 1ste bunun nedeni az önce söyledgim gibi

aslında her türün aynı zaman bir Object olmasından kaynaklanmaktadır.

class ObjectDeneme {

public static void main(String arg[]) {

Object ar[] = {new Deneme(), "String ekledik", new Integer(12), new BaskaBirSinif()};

BaskaBirSinif temp = (BaskaBirSinif)ar[3];

System.out.println(temp.methodX());

/*Olmaz!*/

//ar[3].methodX();

}

}

class Deneme {

public static void methodY() {

System.out.println("Deneme sinifi");

}

}

class BaskaBirSinif {

public static String methodX() {

return "12";

}

}

Soyut sınıflar

Soyut sınıf kavramı aslında tamamen türetme ile iliskilidir. Bu nedenle soyut sınıfların anlamlı kullanılması aslında bir

türetme isleminin yapılmasını gerektirir. Türetme islemini hatırlayacagımız gibi bir sınıf baska bir sınıfının degisken

ve metodlarını alabilmektedir. Böylece önceden yazılmıs birtakım metod ve degiskenlerin yeraldıgı bir sınıf varsa ve

biz de bu metod ve degiskenlere ihtiyaç duyuyor ve aynı zamanda yeni metod ya da degiskenler de eklemek

istiyorsak, mevcut sınıftan bir türetme yaparak sadece yeni eklemek istedigimiz metod ve degiskenleri yazmamız

yeterli olacaktır.

Bir sınıf içerisinde daha önce görmüs oldugumuz metod tanımlamalarından farklı

 

olarak “soyut metod” denilen bir

metod sekli daha vardır. Bir metod soyut olarak yazılacaksa metod prototipinde public, private ya da protected

79

anahtar sözcügünden sonra “abstract” anahtar sözcügü yazılmadır. Ayrıca sınıf içerisinde bu sekilde prototipi

yazılan soyut metodun içerisine de hiçbirsey yazılmaz. Örnegin:

public abstract String ismiVer();

Yukarıdaki örnekte bir soyut metod bildirimi yapılmıs ve içerisi yazılmadan noktalı virgül ile bildirim tamalanmıstır.

1kinci kural olarak da içerisinde soyut metod barındıran bir sınıftan türetilen yeni bir sınıf, bu soyut metodun

içerisini kendi içinde yazmak zorundadır. Aksi takdirde türetme islemi hatalı sayılır. Sonuç olarak:

Soyut bir metodun temel sınıf içerisinde sadece prototipi yazılır.

Bu temel sınıftan türeyen bir sınıf sadece prototipi yazımıs olan bu soyut metodu kendi içerisinde tamamen

yazmak zorundadır.

1çerisinde soyut metod barındıran sınıflara soyut sınıf denilir ve böyle bir sınıfın bildiriminin basına Class

anahtar sözcügünden önce “abstract” yazılmak zorundadır.

Peki ama soyut metodların bu kullanımı ne ise yarar?

Sınıf bildirimi içerisinde yazılmıs olan soyut metodların nasıl çalısacagı, ancak bu sınıftan türetilen sınıflar içerisinde

yazılmaktadır. Temel sınıf içerisinde bu metodların nasıl isleyeceklerinden ziyade geri dönüs degerlerinin ve

parametrelerinin ne oldukları yazılır. O halde içerisinde soyut metodlar barındıran bir sınıftan türetme yapıldıgında,

ondan türeyen her sınıf içerisinde bu metodun yeniden yazılması gerekecek ve dolayısıyla bu sınıftan türeyen tüm

sınıfların böyle bir metod barındıracagı garanti edilmis olacaktır.

Böylece birçok kisinin görev aldıgı büyük bir projede yazılması kesinlikle gerekli olan ancak sadece isleyisi

degisebilen metodları temel bir sınıf içerisinde soyut olarak tanımlarsak ve yazılacak tüm yeni sınıfların da bu temel

sınıftan türetilerek yazılmasını sart kosarsak, herhangi bir kontrole gerek kalmaksızın yazılması zorunlu olan bu

metodların birbirinden bagımsız kisilerin tasarlayacagı tüm sınıflarda kesinlikle yer alacagından emin olabiliriz. Bu

durum asagıdaki sekilde de özetlenmistir

 

:

Böylece kavramsal olarak soyut metod ve soyut sınıfın ne oldugunu yeterince

 

inceledigimizi düsünüyorum. Simdi

yukarıda okuduklarımız pekistiren bir örnek yapalım. Bu örnekte soyut metod kullanımını içeridigi gibi aslında

türetme isleminin de güzel bir kullanımını göstermektedir.

Örnegimizde en temel olarak “Sekil” adında bir sınıf yeralmaktadır. Bu sınıf tüm geometrik sekillerin temelini teskil

ettiginden içerisinde yer alacak olan alanHesapla, cevreHesapla, kenarSayisiVer gibi metodların yazılması

anlamsızdır. Ancak bir geometrik sekil bu metodlara sahip olmalıdır. O halde biz “Sekil” sınıfınının bu metodlarını

soyut olarak tasarlayıp gerekli olan geometrik sekile iliskin bir sınıfı da bu sınftan türetirsek, soyut olan bu metodları

80

ilgili seklin özelliklerine göre yeniden yazabiliriz. Bu düsünceyle de örnegimizde “Sekil” sınıfından türeyen “Kare”,

“Ucgen” ve “Daire” sınıflarını da yazmaktayız:

81

Java ile Programlama

Arayüzler

Arayüzler aslında teknik olarak bir sınfın ne yapması gerektigini anlatmaktadır. Yani aynen soyut sınıflarda oldugu

gibi, temel bir sınıfın operasyonlarını tanımlamak amacıyla tüm metodlarının soyut olması soncunda arayüzler

meydana gelir.

Bu bakıs açısıyla ir arayüzün aslında tam anlamıyla bir sınıf olmaktan ziyade “yapılması gerkenler listesi” olarak

tanımlanması da mümkündür.

Nesneler arasındaki büyüklük küçüklük kriterinin önemi

Bunu su temel örnekler açıklayabiliriz. Daha önceki derslerimizde de ögrendigimiz gibi belirli nesneler üzerinde bir

sıraya dizme islemi yapılabilmesi için bu nesnlerim birbirleri arasında bir büyüklük-küçüklük iliskisinin tanımlı olması

gerekir. 1lkel veri tipleri için bu iliski zaten “>” ya da “<” operatörü ile kolaylıkla anlasılabilmektedir. Ancak bizim

yarattıgımız nesneler üzerinde (mesela Student ya da Dortgen sınıfları gibi) dogal bir büyüklük küçüklük kriteri

yoktur. Çünkü java açısından bu nesnelerin mantıksal olarak ne ise yaradıkları bilinemez. O halde biz büyklük

kriterini de içercek compareTo ismli bazı metodlar yazarız. Bu metodlar yardımıyla da bu kriteri kullanıur ve böylece

nesneleri sıralayabiliriz.

Comparable Arayüzü

1ste bu islem için java programlama dili içerisinde “Comparable” adında bir arayüz tanımlanmıstır.

public interface Comparable {

int compareTo(Object other);

}

Bu arayüz bize kendisinde türetilen bir sınıfın içerisinde bu compareTo metodunun zorunlu olarak yazılması

gerektigini anlatır. Ayrıca bir nesne eger bu arayüzden türetilirse, yine java içerisinde zaten öntanımlı olarak

kullanılan “Arrays” isimli sınıfın sort metodu yardımıyla bu sınıf türünden nesneler de otomatik olarak

sıralanabilecektir.

NOT:

 

Arrays isimli sınıf genel olarak içerisinde birçok statik metod barındıran ve dizi islemleri yapmayı kolaylastıran

bir sınıftır.

Comparable’dan türetme neden gerekli?

Peki ama biz zaten kendimiz istedigimiz bir sınıf içerisine compareTo metodu ekleyebileceksek o halde neden

sınfımızı Comparable nesnesinden türetelim ki??

Bunun nedeni “Arrays.sort” metodu içerisinde bir yerlerde a[i].compareTo(a[j]) gibi bir kod yazmaktadır. O halde

bu metoda gonderilen bir nesne dizisinin içerindeki her nesnenin comparTo metodu oldugu garanti edilmelidir.

Bunun da tek yolu sizin gonderdiginiz ve sıralanmasını istediginiz bu nesnelerin Comparable arayüzünden türetilmis

olmalarıdır.

Arayüzlerin Özellikleri

1) Arayüzler ile instance yaratılamaz

Teknik olarak aryüzleri içerisinde hiçbir metod yazılmadıgından bir aryüz nesnesini dogrudan yaratmak hataya

neden olur. Yani asagıdaki gibi bir kod geçersizdir:

Comparable x = new Comparable();

2) Arayüzler içerisndeki degiskenler sabit olmalıdır

Arayüzlerde yaratılan metodların içerinde yerlestirilen degiskenler her zman public static final kabul edilirler.

82

3) Birden fazla arayüzden türetme

Nir ınıf normalde en fazla bir sınıf türetebilir. Ancak birde fazla sınıftan türetme yapmamın tek yolu kullanılan teme

sınıflardan sadece birtanesinin sınıf, digerlerinin ise arayüz olması gerekir. Örnegin Comparable gibi bir de Movable

isimli bir arayüzün varlıgını kabul edersek, Student isimli bir sınıf Person isimli bir sınıftan türetme ve Comparable ile

Movable isimli arayzlerden de implement tyaparak aslında birden fazla sınıftan türetme yapabilir:

class Student extends Person implements Comparable, Moveable

 

{

public int compareTo(Object obj2) {

}

public void move(double x, double y) {

}

}

Nesne Klonlama

Java da yaratılan bir sınıf nesnesinin bir baska sınıf degiskenine kopyalanildigini ve hatta temel sınf türünden bir

degiskene türemis sınıfların da atnabildigini ve buna iliskin detayları önceki derslerimizde görmüstük.

Ancak bir sınıf nesnesi bir baska sınıf degiskenine kopyalandıgında aslında iki degiskenin de hafızada aynı nesneye

isaret ettiklerine ve bu nedenle de birinci degisken üzerinde degisiklik yapıldıgında aslında ikiniciyi de

degistirdigimizi belirtmek gerekir. Asagıdaki örnegi inceleyiniz:

= operatörü ile aslında nesneyi degil, adresini kopyalarız.

class Person {

String name;

public Person(String name) {

this.name = name;

}

public String toString() {

return this.name;

}

public void setName(String new_name) {

this.name = new_name;

}

public static void main(String[] args) {

Person p1 = new Person("Hakan Gozutok");

Person p2 = p1;

System.out.println("Birinci nesne icersindeki isim: " + p1);

System.out.println("Birinci nesne icersindeki isim: " + p2);

p2.setName("Caglar Aytek");

//p1 içersindeki isim degistirilmedigi halde Caglar Aytek

//olacaktir

System.out.println("Birinci nesne icersindeki isim: " + p1);

System.out.println("Birinci nesne icersindeki isim: " + p2);

}

}

83

Bu sekilde meydana gelen degisimden kurtulmak ve gerçek anlamda nesnenin tam bir kopyasını almak için

nesnenin klonlanması gerekir.

Yarattıgımız her nesne aslında bir Object tir. Bunu daha önce ögrenmistik. 1ste Object sınıfı içerisinde yer alan

“clone()” isimli bir metod bir nesnenin tam bir kopyasının baska bir nesne seklinde klonlanmasını saglar. Ancak bu

islem sanılıdıgı kadar basit deggildir. Bunu asagıdaki örnek ile açıklayalım:

Bir sınıfın örneklerini, dogrudan “clone” metodu ile sadece kendi içerinde kopyalayabiliriz

class Person {

String name;

public Person(String name) {

this.name = name;

}

public String toString() {

return this.name;

}

public void setName(String new_name) {

this.name = new_name;

}

public static void main(String[] args) {

Person p1 = new Person("Hakan Gozutok");

Person p2 = p1;

System.out.println("Birinci nesne icersindeki isim: " + p1);

System.out.println("ckinci nesne icersindeki isim: " + p2);

p2.setName("Caglar Aytek");

//p1 içersindeki isim degistirilmedigi halde Caglar Aytek

//olacaktir

System.out.println("Birinci nesne icersindeki isim: " + p1);

System.out.println("ckinci nesne icersindeki isim: " + p2);

Person p3 = new Person("");

try {

p3 = (Person)p1.clone();

} catch (Exception e) {};

p3.setName("Ahmet Aykac");

System.out.println("Birinci nesne icersindeki isim: " + p1);

System.out.println("Ucuncu nesne icersindeki isim: " + p3);

}

}

Nesneleri, kendileri dısında baska metodlar içerisinde dogrudan klonlamak mümkün degildir.

Yukarıda anlattıgımız klonlama isleminde aslında clone metodu ile nesneyi kopyalrken kendi sınıfı içerisinde bu

islemi yaptık. Oysa tamamen sınıfın dısında daha önceden yaratılmıs bir sınıf türünden örnegi kolnlamaya

kalktıgımızı düsünelim. Bu sefer islem yapılamayacaktır. Çünkü klonlanmak istenen bu sınıfın Cloneable

arayüzünden implement edilmesi sarttır. Ayrıca bu islemde bir checked exception meydana gelir (Checked

Exception ileriki koularda ele alınacaktır. Simdilik sadece ele alınması zorunlu olan exceptionlar olarak

tanımlayabilriiz.)

84

Bir nesnenin heryerde klonlanabilir olmasını saglamak

Böyle durumlarda 1lgili nesne Cloneable arayüzünden implement edilir ve clone metodu polymorphism yöntemiyle

yeniden yazılabilir. Bu yeniden yazımda clone metodunun prototipi

public Object clone();

seklinde yazılır.

Ancak sunu da belirtmek gerkir ki aslında Cloneable arayüzü içerisinde hiçbir metod tanımlı degildir.

Cloneable içerisinde hiçbir metıd yoksa neden bu sınıftan implementasyon yapıyoruz?

clone metodu aslında Cloneable sınıfı içerisinde tasnımlı bir metd degildir. Bu metod Object sınıfı içerisinde

tanımlıdır ve protected anahtar sözcügü ile tanımlanmıstır. Ancak yine de kullanıcıya bilgi vermek amacıyla

Cloneable dan implement yapılmaktadır.

Etiketleme Arayüzleri

NOT: Burada gördügümüz gibi java’da bazı arayüzler bu skilde “etiketleme” amacııyla kullanılır. Bu arayüzlerde hiç

metod bulunmaz ve sadece gerektigi durumlarda “instanceof” operatörüyle kullanabilmek için implement edilirler.

NOT:

 

 

Aslında clone metodu Object sınıfı içerisinde protected olarak tanımlanmıstır. Bütün sınıflar Object sınıfının bir

alt sınıfı ise ve bir alt sınıf türedigi sınıfın protected metodlarına erisebiliyorsa, o halde neden herhangi bir nesne

baska nesnenin clone metoduna dogrudan erisemez? Protected metod konusundan da hatırlayacagımız gibi bir sınıf

kendisinin atası olan sınıfın protected metoduna türetme sırasında, kendi içerisinde erisebilir. Ancak bu sınıfın

atasında yer alan protected metoda baska bir sınıf içerisinde erisilemez. Bu nedenle bir sınıfın baska bir sınıf

içerisinde clone islmeine tabi tutulması için bu sınıfın clone metodunu public olakrak yeniden bildirmesi gerekir

 

 

.

Simdi özet olarak bir nesnenin herhangi bir yerde clone islemine tabi tutulabilmesi

için:

class A implemenrs Cloneable {

public Object clone() {

try {

return super.clone();

}

}

...

seklinde clone metodunu yeniden yazması gerekir. Böylece bu nesnenin clone metodunu çagırmak isteyen kis

aslında public olan clone metodunu çagrabilir. Ancak nesne içerisinde bu public clone meodu, kendi ata sınıfının

protected olan clone metodunu çagırmaktadır. Ata sınıf içerisindeki bu clone metodu da nesnenin veri elemanlarını

alan alan kopyalar ve bir nesne olarak geri döndürür.

çerisinde baska sınıfları veri elemanı olarak kullanan sınıfların klonlanması

Böyle durumlarda yazılan public clone metodu bu veri elemanlarını da klonlayacak sekilde dikkatlice yazılmalıdır.

Diyelim ki A bir sınıf olsun içinde B adında baska bir sınıfı veri elemanı olarak kullansın:

85

class B {

double y;

}

class A implements Cloneable{

int a;

String str;

B b;

...

public Object clone() {

try {

/*A nesnesi klonlarak geçisi bir nesnede

tutluyor. Ama b degerinin adresi kopylanadı.

Çünkü b aslında B türünden ve alan alan kopylamada b nin kendisi

degil adresi kopylanadı.*/

A cloned_a = (A)super.clone();

/*nesnenin kendi kopyasını tutan geçici

degiskenin b alanının da klonu alınıyor. Artık geçici kopya da

adres kopyalam islemi düzeltildi.*/

cloned_a.b = (B) b.clone();

/*Geçici nesne geri gönderiliyor*/

return cloned_a;

}

}

}

Ödev: (2 haftalik)

Çok kapsamlı bir Student nesnesi yaratınız. Bir Student nesnesinin veri elemanları:

a- String student_name

b- Vector courses (Ogrencinin aldigi dersler, dinamik bir array olmali, her elemani Course olmali)

c- Adress address (Ogrencinin adresi)

d- Date b_date (Ogrencinin dogum tarihi)

e- int term; (Ogrencinin donem bilgisi)

Bununla birlikte gerekli metodlari ile birlikte bu nesneyi tasarlayiniz.

Bu nesnenin tasarlanabilmesi icin tabi ki Date, Course ve Address nesnelerinin de gerekli metodlariyla birlikte

tasarlanmasi gerekmektedir.

Date sinifi, icerisinde bir tarih ve zaman bilgisi tutan bir siniftir. Bu sinifin veri elemanlari day, month, year, hour,

minute, second olmalidir. Ve tabi ki bu degiskenleri isleyebilecek uygun metodlari barindirmalidir. Bu sinifin

metodlarindan bazilari asagida verilmistir:

public void addDay( int toAdd) - tariha toAdd kadar gun ekler.

public void addMonth(int toAdd) -tarihe toAdd kadar ay ekler

public void addYear(int toAdd) -tarihe toAdd kadar yil ekler

public int diff(Date d) - iki tarih arasindaki gun farkini veren bir metod

public void addCourse(Course new_course) - yeni bir course alip vector nesnesine ekleyecek

/*secime bagli*/

public int getAge() - Ogrencinin yasini retrun edecek. (Sistem zamanini almaniz gerekir)

86

Bunun disnda da gerekli olan diger metodlar eklenecektir.

Address sinifi sadece address bilgisini tutmak ve kullanabilmek icin yaratilacaktir. Bu sinifin tum degisken ve

metdolari tasarimciya birakilmistir.

Course sinifi sadece 1 dersin bilgilerini tutmak icin kullanilacaktir. Bu sinifin tum degisken ve metdolari tasarimciya

birakilmistir.

Tum metodlarin icerigi tasarimciya birakilmistir. Ancak yaratilan nesnelere iliskin dokumantasyon hazirlanacaktir

.Bu dokumantasyonda bir metodun sadece adi, aldigi parametre ve geri donus degeri anlatilacaktir. Metodun

icerideki isleyisi anlatilmayacaktir.

Bir Student nesnesi Comparable arayuzu ve Person turunde bir arayuzden’den turemelidir. Person interface’i

asagida verilmistir.

public interface Person {

public String getName();

public String getAddress();

public String getFamilyName();

public String listCourses();

public Date getBirthday();

}

Hata Yakalama (Exception Handling)

Java’da error adı verilen hatalar meydana geldiginde program akısı dogrudan sonlandırılmaktadır. Ancak bazen,

aslında derleme sırasında hata oldugu belli olmayan ancak çalısma zamanı sırasında yapılan hatalı islemler

neticesinde ortaya çıkan hatalar olabilir.

Çalısma zamanı sırasında meydana gelen hatalar

Mesela program içerisinde “x/a” gibi bir ifade oldugunu varsayalım. Bu durumda program derlenirken bu ifade

hatalı olarak algılanmaz. Ancak program çalısırken a degiskenine 0 degeri atanırsa bu ifade matematiksel olarak

sonsuz anlamına gelir ve bu da baska bir hata üretilmesine neden olur.

1ste bu tur hatalara error degil “exception” adı verilir.

Exception ele alınabilir ama error alınamaz

Exception ile error kavramları saece tanım olarak degil, nitelik olarak da farklıdır. Çünkü java da excepton’lar

runtime sırasında yakalanabilir. Ancak error oldugu zaman bu durum kesinlikle programın çalısmasını sonlandırır.

Exception ların ele alınması

Exception, programda bazı özel bloklar içerisinde ele alınır. Programın çalısması sırasında bir exception olursa

hemen o anda bir “Exception” nesnesi yaratılır. Bu nesne, aslında Exception nesnesinden türemis bir baska

exception da olabilir. Ama neticede en temel anlamda bir “Exception” nesnesi yaratılır.

Çalısma zamanı sırasında üretilen exception’lar ele alınabilir

Daha sonra eger programcı tercih etmisse bu exception nesnesi özel bir blok tarafından yakalanır ve yine aynı

bloklar içerisinde programcının istedigi kodları çalıstırır.

87

try {

openFile();

readFile();

closeFile();

}

catch(Exception e) {

doSomething();

}

Yukarıda da görüldügü gibi aslında exception ların yakalanma prensibi, exception olma ihtimali olan satırların bir try

blogu içerisinde yazılması ve meydana gelen exception’ı yakalayacak bir catch blgunun da hemen bu try bloklarının

sonuna yerlestirilmesi seklindedir.

Exception’lar Es Geçilemez

Exceptionlar uretildigi anda programcı tarafından ele alınmazsa program exception ile birlikte sonlanır. Bu nedenle

bir exception ele alınmadan program akısına devam edilemez.

Kontrol edilen ve Kontrol Edilmeyen Exception lar

Aslında Exception lar kontrol edilen ve kontrol edilmeyen olmak uzere 2’ye ayrılır.

Çalısma zamanı sırasında meydana gelen bazı exceptionların kontrol edilmesi pogramcının istegine baglıdır. Bu tip

exception lar “RunTimeException” nesnesinden türemislerdir. Programcı bu exceptionları ele almazsa program bir

hata mesajı ile sonlanır. Ya da programcının ele aldıgı sekilde akısına devam ederi. (dizi indeksinin geçilmesi, sıfıra

bölme hatası )

Kontrol edilen exceptionların ele alınması prgoramcının istegine baglı degildir. Bu exceptionların ele alınması

zorunludur. Mesela bir sodyanın açılması okunması ya da kapanması islemleri kontrol edien exceptionlardır. Bu tür

exceptionlar programcının hatasından kaynaklanmayan exception lardır (Bozuk bir dosya ya da URL)

NOT:

 

Aslında bütün exception’lar Throwable nesnesinden türemistir.

Exception ların Yakalanması

Asagıdaki örnekte kulanıcıdan bir sayı girmesi istenecektir

 

.

import javax.swing.*;

public class HataYakalama {

public static void main(String[] args) {

String str = JOptionPane.showInputDialog(null, "Bir sayı

giriniz");

try {

int n = Integer.parseInt(str);

System.out.println("Girilen sayi: " + n);

}

catch(NumberFormatException e) {

e.printStackTrace();

System.exit(0);

}

}

}

88

Eger kullanıcı bir sayı yerine yanlısklıkla bir metin girerse, o zaman bu metinin Integer.parseInt metodu yardımıyla

sayıya donusturulmesi bir runtime exception uretilmesine neden olur. Ve program akısı hemen RunTimeExeption

ureterek catch bloguna atlar. Boylece hata yakalanmıs olur. Eger hata yaklalanmaz ise JVM u hatayı kendisi yakalar

ve ekrana asagıdaki gibi bir exception mesajı gondererk program akısını sonlandırır:

java.lang.NumberFormatException: For input string: "gdg"

at java.lang.NumberFormatException.forInputString(Unknown Source)

at java.lang.Integer.parseInt(Unknown Source)

at java.lang.Integer.parseInt(Unknown Source)

at HataYakalama.main(HataYakalama.java:9)

import javax.swing.*;

public class HataYakalama {

public static void main(String[] args) {

int n;

String str = JOptionPane.showInputDialog(null, "Bir sayı giriniz");

try {

n = Integer.parseInt(str);

}

catch(NumberFormatException e) {

JOptionPane.showMessageDialog(null, "Exception yakalandı");

n = Integer.parseInt(JOptionPane.showInputDialog(null, "Giris

yanlis tekrar deneyiniz:"));

}

System.out.println("Girilen sayi: " + n);

}

}

KISACA REKURSIF METODLAR

Uygulama:

Kullanıcıdan dogru giris alana kadar çalısan bir sayı isteme mekanizması yazınız

 

 

.

Cevap:

import javax.swing.*;

public class HataYakalama {

public static int sayiAl(String onEk) {

JOptionPane.showMessageDialog(null, "DEBUG: metoddayiz");

int n = -1;

String str = JOptionPane.showInputDialog(null, onEk + " Bir sayı

giriniz");

try {

JOptionPane.showMessageDialog(null, "DEBUG: try blogundayiz");

n = Integer.parseInt(str);

}

catch(NumberFormatException e) {

89

JOptionPane.showMessageDialog(null, "Exception yakalandı");

onEk = "Giris yanlis tekrar tekar deneyiniz.\n";

return sayiAl(onEk);

}

return n;

}

public static void main(String[] args) {

System.out.println("Girilen sayi: " + sayiAl(""));

System.exit(0);

}

}

Exception Ureten Metdolar

Su ana kadar ogrendiklerimizden görüyoruz ki Java’da bazı satırlar exception olusmasına neden olabilir. O halde

bazı metodlar da exception uretilmesine neden olabilirler.

Bir metod eger exception uretiyorsa bu metodu kullandıgımız satırında try blogu içerisinde yazılması gerekir. O

halde Java’da bazı hazır metodları incelerken bunların exception uretip uretmediklerine de bakılmalıdır.

FileInputStream

read

Integer.parseInt metodlarının dokumantasyondan incelenmesi.

Eger biz de yazdıgımız metodların exception uetmelerini istiyorsak metod prototipinin sonuna throws anahtar

sözcügü ve devamında da üretilecek exception’ın tipini yazarız.

public String getValue(int index) throws IndexOutOfBoundsException {

f(index == null || index >= values.length) {

throw new IndexOutOfBoundsException();

}

}

Checked ya da Unchecked Exception Nasıl Yaratılır

Eger exception gonderen method “Exception” ya da ondan tureyen bir exception’ı throw ediyorsa bu exceptionlar

checked sayilir. O halde bu metodu kullanan kisi metodu try bloklari icerisinde yazman zorudadir.

Ancak gonderilen exception “RunTimeException” ya da ondan turemis bir exception ise metodumuz unchecked

exception uretiyor demektir. O halde bu metodu try bloklari icerisinde yazmak zorunda degiliz.

finally Blok Yapısı

finally blok yapısı catch bloklarının sonuna eklenir Bir exception yakalansa da yakalanmasa da program akısı finally

blokları içerisine yönlenecektir. Asagıdaki örnegi incelyiniz:

try {

code a;

}

90

catch(IOException e) {

code b;

}

finally {

code c;

}

1. Burada code a; hiçbir exception üretmeyebilir. Bu durumda “code a” çalıstıktan sonra “code c” çalısacaktır.

Program akısı daha sonra finally blogu altındaki kodları çalıstırmaya devam eder.

2. Bu durumda “code a” IOException üretir ve bu nedenle “code b” çlaısır. Daha sonra yine “code c”

çalısacaktır. Eger catch blogu herhangi bir exception üretmez ise program akısı yine try bloklarının bittigi

yerden devam edecektir.

3. try blokları içerisinde catch içerisinde yakalanmayan bir exception üretilirse o zaman “code a” ve “code c”

çalıstıktan sonra exception kullanıcıya gönderilir.

Asagıdaki örnegi degisik senaryolar için deneyiniz:

package derstekiornekler;

public class ExceptionTest {

public static void main(String[] args) {

try {

System.out.println("Satir 1");

throw new Exception();

}

catch(Exception e) {

System.out.println("Catch blogu icindeyiz");

}

finally {

System.out.println("Finally blogu icindeyiz.");

}

System.out.println("Catch blogu disindayiz");

}

}

NOT:

 

finally bloklarını açılan streamleri, exception olsa bile kapatabilmek amacıyla kullanabiliriz.

91

Java ile Programlama

Bölüm 8:

Java'da Dosya slemlerine Giris

Programcılıgın vazgeçilmez islerinden birisi de disk üzerindeki dosyalarla çalısmaktır. Buraya kadar konuları

ögrenmek amacıyla kullanmıs oldugumuz örneklerde aslında veriler sadece o anda çalısan program içerisinde ele

alınabiliyordu.

Profosyonel anlamda yazılan programların çogu kullanıcının ihtiyaç duyacagı verileri dosyalar üzerinde saklamakta

ve gerektiginde bu dosyalardan verileri okuyarak ya da yeni verileri dosyalara yazarak isleyislerini sürdürmektedir.

Bu nedenle programcılıkta amaç ne olursa olsun dosyalar üzerinde islem yapma ihtiyacı mutlaka karsınıza

çıkacaktır.

File Sınıfı

Java'da dosya islemlerine iliskin ilk olarak “File” isimli sınıfın kullanımını inceleyerek baslayalım. Bu sınıf disk

üzerinde yer alan bir dosyayı program içerisinde de bir nesne haline getirerek programcının dosya üzerinde islem

yapabilmesini saglamaktadır. Sınıfın baslangıç fonksiyonu temel olarak bir dosyanın yol (path) bilgisini alarak File

nesnesini yaratır. Örnegin:

...

File dosya1 = new File(“Dosya.txt”);

File dosya2 = new File(“c:\ornekler\dosya.txt”);

File dosya3 = new File(“/home/Academytech/Dosyam.txt”)

...

Tabi yukarıda verilen bu örneklerde, “File” sınıfının baslangıç fonksiyonuna parametre olarak verilen bu yolların

diskte de düzgün bir sekilde mevcut olması gerekmektedir. Yani bulundugumuz dizinde Dosya.txt ya da

“c:\ornekler\” dizini altında bir “dosya.txt” ya da “/home/Academytech/” dizini içerisinde bir “Dosyam.tx”t dosyası

bulunmalıdır. Aksi takdirde “dosya1”, “dosya2” ya da “dosya3” ismi ile temsil edilen “File” nesneleri düzgün bir

sekilde yaratılamayacaktır.

Not:

 

Java'da dosya islemlerinin yapılabilmesi için io.* kütüphanelerinin programın en üst satırında “import” anahtar

sözcügü ile programa dahil edilmesi gerekmektedir.

Asagıdaki örnekte temel olarak “File” sınıfı ile dosya islemlerinin ele alınmasına iliskin bir program yazılmaktadır.

Örnegimizde temel bir File nesnesi yaratarak aslında diskte yer alan bir dosya bilgilerinin nasıl ele alındıgını

görmekteyiz. Bu örnekte benim girmis oldugum “/tmp/dosya.txt” yolu aslında kendi sistemimdeki bir dosyanın

92

yerini temsil ettiginden siz kendi örneginizi yazarken kendi diskinizdeki yolu yazmaya dikkat ediniz. Program

çalıstırıldıgında “InputDialog” nesnesi ile asagıdaki resimde gösterildigi gibi sizden bir dosya yolu istenecektir:

Girdiginiz bu yol bilgisi programımızın 8. satırında yazıldıgı sekilde “dosyaYolu” degiskenine aktarılmakta ve daha

sonra da 11. satırda oldugu gibi bu degisken yardımı ile nesne yaratılmaktadır. Bu nesne yardımıyla kullanılabilecek

birkaç metodu 14, 15 ve 16. satırlarda görmekteyiz.

System.out.println metodu

Bu metodu daha önceki derslerimizden gayet iyi biliyoruz. Aslında bu metodun System paketi içerisindeki out

sınıfının println metodu olarak düslünebilirsiniz. Ancak gerçekte durum bu degildir. Buradaki durumun anlasılması,

java’da dosyalar konusunu kavramak için önemli bir baslangıç olacaktır. O halde ilk önce bu durumu inceleyelim.

out System sınıfı içerisinde statik bir nesnedir (instance)

Aslında “out”, System sınıfı içerisinde yer alan static bir instance’dır. Bu yüzden programcı bu instance’a dogrudan

erisebilir. Ayrıca bu nesne bir “PrintStream” nesnesidir.

Stream Kavramı:

Programcılık açısından dosya islemlerini anlamanın en iyi yolu Stream kavramını bilmekle baslar. Stream denilen

nesne aslında bir seyin okunması ya da yazılması için bir soyutlamadır (abstraction). Bu soyutlama gereklidir, çünkü

okunacak ya da yazılacak bilginin tipi her zaman degisebilir. Yani okunan ya da yazılan bilgi bir uygulamada

manyetik karttan yapılabilecegi gibi baska bir uygulamada da diskten yapılabilir.

Burada Stream aslında kelime anlamı olarak akıs anlamına gelir ve programcılık anlamında “bilgi akısını” ifade eder.

Bu yaklasıma göre okuacak bilgi stream den okunur ve yazılacak bilgi de stream e yazılır. Böylece bilginin tipi ne

olursa olsun okunma ve yazılma asamasında stream üzerinde ortak bir bilgi akısı saglanacaktır. Bu ifadeyi

kullandıgımız örneklerle daha iyi pekistirecegimizi düsünüyorum.

Stream kullanımı ile bilgi ne olursa olsun okuma ya da yazma sekli hep aynıdır:

stream aç

daha fazla bilgi oldukça (ya da yazdıkça)

bilgi oku (ya da yaz)

stream kapat

O

 

halde out nesnesine geri dönelim. out nesnesi, bu sekilde adı OutputStream denilen bir arayüzden türetilmis bir

sınıf olan PrintStream sınıfı türündendir. Aslında bizim ekrana bilgi gönderme seklimiz her isletim sisteminde

farklıdır. Ancak JVM içerisinde platforma göre implement edilmis olan bu PrintStream nesnesi bize bu soyutlamayı

saglar ve böylece içerisinde yer alan println metodunu platform bagımsız olarak kullanabiliriz.

flush Kavramı

Aslında yazılması ya da okunması istenen bilgiler yukarıda nalatılan stream’ler içerisine ve oradan da yazılması ya

da okunması istenen yere gönderilir. Ancak bir stream’in kendi içini ne zaman bosaltacagı (yani istenen bilgiyi

gerekli yere ne zaman ulastıracagı) belli degildir. Bu isleme “flush” denilir. Programcı isterse bunu kendisi de

yapabilir.

93

InputStream Nesnesi

Yine System sınıfı içerisinde yer alan ve out nesnesine benzeyen bir nesne daha vardır. Bu nesnenin adı “in” ve türü

de InputStream sınıfı türündendir. Bu nesne de konsoldan bir bayte lık bilgi okuma yetenegine sahiptir. Ancak

okuma yetenegi bu kadarla sınırlıdır. Bu nesneyi “debug” islemleri için kullanabiliriz

 

.

public class

 

 

InputStreamOrnek {

public static void

 

 

main(String[] args) {

for

 

 

(int i = 0; i < 10; i++) {

System.

 

out.println("i: " + i);

try

 

 

{

System.

 

in.read();

}

catch

 

 

(Exception e) {

}

}

}

}

Standart Giris ve Çıkıs

Java'da yukarıda bahsettigimiz bu stream kavramı ile standart giris ve standart çıkısa yazma ve okuma yapmak

mümkün olacaktır. Aslında standart giris-çıkısı komut satırı ortamı olarak düsünebilirsiniz.

Fazla detaya inmeden söylemek gerekirse standart çıkısa yazma yapma islemi aslında daha önceden bildigimiz

Sytem.out.print(“yazi”) metodu ile yapılmaktadır. Arka planda aslında “System” isimli sınıfın içerisinde tanımlı

“PrintStream” türünden yaratılmıs ve adı “out” olan static bir degiskeni kullanmaktayız.

BufferedReader <-- InputStreamReader <-- InputStream

Aynı sekilde standart giristen program içerisine okuma yapmak da mümkündür. Bu islem için yetenekleri sınırlı olan

System.in nesnesine InputStream nesnesi ve BufferedReader nesnesi yardımıyla yetenek kazandıracak ve en son

BufferedReader nesnesinin readLine metodu ile okuma yapacagız:

Örnegimizde 7. satırda BufferedReader nesnesi yaratılmıstır. Bu nesnenin baslangıç fonksiyonuna parametre olarak

bir “InputStream” nesnesi hemen orada yaratılmakta ve gönderilmektedir. “InputStream” nesnesi okuma yapmak

amacıyla kullanılır. Bu nesnenin de baslangıç fonksiyonuna, okumanın yapılacagı yer olan standart giris parametre

olarak verildiginden bu stream standart girise yönlendirilmis, yani standart giristen okuma yapacak sekilde

hazırlanmıstır.

94

Program çalıstırılırken asagıdaki resimde görüldügü gibi komut satırı ortamında bizden birseyler girmemizi isteyecek

ve bu bilgileri daha sonra ekrana yazacaktır. Bilginin standart giristen alınmasını saglayan komut da 14. satırda

görülmektedir. Aslında bu komut soyutlanmıs “BufferedReader” nesnesinin “readLine” metodur ve bu nesne

yukarıda da anlatmıs oldugum gibi standart girise yönlendirlmistir

 

.

Text Dosyalarının Okunması ve Yazılması:

(FileReader ve FileWriter sınıfları)

Yukarıda bahsettigimiz stream kavramı sayesinde standart giristen yapılan okuma aynı sekilde bir text dosyasına

yönlendirilirse, o zaman dosyadan okuma yapmak da mümkün olacaktır. Aynı sekilde standart çıkısa gönderilen bir

bilgi text dosyasına yönlendirilmis bir stream e gönderilirse o zaman da text dosyasına yazma islemi yapmıs oluruz.

1ste burada da stream soyutlamasının kolaylıgını görmekteyiz. Asagıdaki örnekte, bahsettigimiz bu dosyadan okuma

islemini

 

görmekteyiz.

import

 

 

java.io.*;

public class

 

 

DosyaIslemleri {

public static void

 

 

main(String[] args) {

String str;

String fileName =

 

"deneme.txt";

try

 

 

{

BufferedWriter out =

 

new BufferedWriter(

new

 

 

FileWriter(fileName));

out.write(

 

"Deneme Satir 1 ");

out.write(

 

"Deneme Satir 2\n");

out.write(

 

"Deneme Satir 3");

out.close();

BufferedReader in =

 

new BufferedReader(

ne

 

w FileReader(fileName));

while

 

 

((str = in.readLine()) != null) {

System.

 

out.println(str);

}

in.close();

95

}

 

catch(IOException e) {}

}

}

NOT:

 

Aslında BufferedReader ve BufferedWriter sınıfları olmadan da dogrudan FileWriter ve FileReader sınıfları

yardımıyla dosyaya text yazmak ya da dosyadan text okumak mümkündür. Yani bu soyutlama zaten yapılmıstır.

Ancak Buffered sınıfları yardımıyla bu okuma ve yazma islemi daha büyük verier için daha verimli bir sekilde

yapılmaktadır.

Veri Dosyalarını Okunması ve Yazılması:

(DataOutputStream, DataInputStream)

Veri dosyaları önceki örnekte kullanmıs oldugumuz text dosyalarından biraz daha farklıdır. Bildigimiz gibi program

yazarken degiskenlerin yaratılması sırasında onların türlerini de belirtmek zorundayız. Daha sonra da bu

degiskenlere verilen degerleri de aynı türden vermek zorundayız.

1ste veri dosyalarında saklanan bilgiler de bu sekilde tür bilgisi ile birlikte sanki hafızada(ram’de) saklanıyormus gibi

saklanmaktadır. Yani text dosyalarında oldugu gibi verilerin tamamı string seklinde saklanmaz. Bu nedenle de veri

dosyalarını bir text editörü ile açıp okumaya kalktıgınızda bilgilerin anlasılır olmadıgını görürüz. Asagıdaki örnekte bir

veri dosyasına birtakım bilgiler yazılmakta ve daha sonra da aynı dosyadan bu bilgiler okunmaktadır.

Aslında buradaki mantık yine yukarıdaki anlattıklarımıza benzer. Yukarıda bir dosyaya text yazmadan önce bir

FileWriter stream açarak dosyaya giden bir yol açmıs olduk. Ancak bu yola verileri dha verimli yüklemek için yolun

ucuna bir BuffereWriter tüneli ekleyerek onun üzerinden dosyaya gönderdik. Ancak bu sekilde ancak text verileri

dosyaya yazabiliyoruz.

Dosyaya verileri tür bilgisi ile gönderebilmek için önce dosyaya ulasan bir FileOutputStream tüneli açıyoruz. Daha

sonra bu tünelin ucuna BufferedOutputStream ve onun da ucuna DataOutputStream ekleyerek verileri tür

bilgileriyle birlikte dosyaya gönderebiliyoruz.

Yukarıdaki örnegimizde bu sefer veri yazma islemi yapmaktayız. Bu nedenle stream nesnemizi 9. satırda oldugu gibi

veri yazabilecek ve 16. satırda oldugu gibi veri okuyabilecek sekilde hazırlamaktayız. 12. ve 13. satırlarda sırayla

96

yazılan double ve int veriler okunurken de yazıldıkları sıra ile okunurlar. Veri yazma islemini program içerisindeki bir

degiskenin hafızada degil de dosyada saklanması gibi düsüebiliriz. Çünkü bazen verileri bu sekilde tür bilgileriyle

saklamak ve daha sonra da ele almak gerekmektedir. Bu islemi bir text dosyasıyla yapmaya kalkarsak verilerin

sadece görüntülerini saklamıs oluruz. Bu durumda verilerin daha sonra tekrar okunması sırasında tür bilgileri

kaybolacagından örnegimizdeki 19. 20. satırdakilere benzer atamalar mümkün olmayacaktır

 

.

throws Kullanımının getirdigi kolaylık

Ayrıca dikkat edersek bu örnegimizde “try” ve “catch” bloklarını kullanmak yerine üretilecek “Exception” bilgisini

daha farklı ele aldık. Eger bir metodun içerisinde “Exception” üretilme ihtimali varsa örnegimizde oldugu gibi

metodun prototipine “throws” anahtar sözcügünden sonra üretilecek Exception yazılırsa, metod içerisinde bu

Exception'ı üretebilecek satırları “try” bloklarında ele almaya gerek kalmaz. Buna iliskin detaylı bilgileri bir önceki

dersimizde bulabilirsiniz.

Özetleyecek Olursak

Text Veri ---> BufferedWriter ---> FileWriter ---> DOSYA

Program <--- BufferedReader <--- FileReader <--- (TextVeri) DOSYA

Ham Veri--->DataOutputStream-->BufferedOutputStream--->FileOutputStream--->DOSYA

Ham Veri<---DataInputStream<--BufferedInputStream<---FileInputStream<---

(HamVeri)DOSYA

Hep Sırayla Okuduk, Sırayla Yazdık Ama..

Dersimizin buraya kadar olan kısmında stream yaratarak dosyalara yazma ve okuma islemlerini gördük. Ancak bu

yazma-okuma islemlerini hep sırayla yaptık. Yani bir veriyi okumadan, ondan daha sonra gelen veriyi okumak

mümkün degildi. Yine aynı sekilde ilk veriyi yazmadan ikinci veriyi yazmak yukarıda gösterdigimiz stream ler ile

olanaksızdı. Böyle bir islem yapmak için daha farklı bir stream kullanmamız gerekmektedir. Dosyalara bu sekilde

erisim istegine teknik olarak “rastgele erisim” denilir. Simdi bunu inceleyelim.

Dosyalara Rastgele Erisim slemi

Bir dosyaya rastgele erisim yapılabilmesi için öncelikle “RandomAccessFile” sınıfı türünden bir degisken yaratmak

gerekir. Bu degisken yaratılırken 1. parametre olarak erisimin yapılacagı dosya ve ikinci parametre olarak da erisim

hangi modda yapılacagı bilgisi verilmelidir.

Örnegin “CikisDosyasi.dat” dosyamıza okunabilir ve yazılabilir modda erismek istiyorsak nesneyi su sekilde

yaratmamız gerekir:

RandomAccessFile myFile = new RandomAccessFile(“CikisDosyasi.dat”, "rw");

Dosyaya rasgele erisim için kullanılabilecek en genel modlar su sekilde özetlenebilir:

r:

 

Dosya sadece okuma için açılır. Herhangi bir yazma islemi

yapılırsa IOException üretilir.

rw:

 

Dosya yazma-okuma için açılır. Eger dosya hali hazırda mevcut degilse yeni bir tane yaratılır.

Asagıdaki örnekte bir dosya içerisine veriler yazıldıktan sonra rastgele erisilerek okunmaktadır. Burada okuma islemi

sırayla yapılmamaktadır.

97

Örnegimizde 8. satırda okuma-yazma modunda açılan dosyamıza bazı double degerler ekliyoruz. Bu ekleme islemini

bir döngü ile yapıyoruz. Kullanıcı 13. satırdaki sorgu geregi “-1” girmedigi sürece girilen bilgiler önce double türüne

dönüstürülüyor ve daha sonra da dosyaya yazılıyor. Bu dönüstürmenin nedeninin, girilen bilgini hep string

olmasından dolayı oldugunu önceden hatırlayınız.

Daha sonra 21. satırda kullanılan “seek()” metodu sayesinde dosya içerisinde rastgele bir pozisyona gidiyoruz. Bu

pozisyon, seek metoduna asıl pozisyon * 8 olarak gönderiliyor. 1lk pozisyon “0” oldugu için kullanıcının istedigi

pozisyondan 1 çıkartarak seek() metoduna gönderiyoruz. Böylece kullanıcı gerçekten istedigi sayıyı elde edebiliyor.

NOT:

 

seek() metodunun içerisine yazılan 8 * cursor ifadesindeki 8, double veriler icin. Her veri icin bu dger

degisir. Mesela int veriler icin bu deger 4, byte veriler icin ise 1 dir. Bu bilgiler dokumantasyonda yer alan write

metodlarinda mevcuttur.

Object Serialization Hakkında

import

 

 

java.awt.*;

import

 

 

java.io.*;

public class

 

 

ObjectReaderWriter {

String

 

filePath;

public static void

 

 

main( String args[] ) {

ObjectReaderWriter orw =

 

new ObjectReaderWriter();

}

ObjectReaderWriter() {

try

 

 

{

98

// Allow the user to specify an output file.

FileDialog fd =

 

new FileDialog( new Frame(), "Nesnelerin yazilacagi dosya..",

FileDialog.

 

SAVE );

fd.show();

filePath

 

 

= new String( fd.getDirectory() + fd.getFile() );

// Next, create an object that can write to that file.

ObjectOutputStream outStream =

new

 

 

ObjectOutputStream( new FileOutputStream( filePath ));

// Create instances of each data class to be serialized.

MySerialObject serialObject1 =

 

new MySerialObject(12, "Academytech");

MySerialObject serialObject2 =

 

new MySerialObject(24, "Caglar");

//save each object

outStream.writeObject( serialObject1 );

outStream.writeObject( serialObject2 );

outStream.flush();

outStream.close();

// Allow the user to specify an input file.

fd =

 

new FileDialog( new Frame(), "Nesnelerin cekilecegi dosya",FileDialog.LOAD

);

fd.show();

filePath

 

 

= new String( fd.getDirectory() + fd.getFile() );

ObjectInputStream inStream =

 

new ObjectInputStream( new FileInputStream(

filePath

 

 

));

// Retrieve the Serializable object.

MySerialObject serialObject = ( MySerialObject )inStream.readObject();

//MySerialObject serialObject2 = ( MySerialObject )inStream.readObject();

// Display what we retrieved:

System.

 

out.println( serialObject );

inStream.close();

}

catch

 

 

(Exception e) {}

}

}

File Sınıfının ncelenmesi:

Java'da dosya islemlerini ele alabilecegimiz “File” isimli bir sınıf nesnesi daha vardır. Bu nesne yardımıyla aslında

yine bir soyutlama yapılmkata ve böylece disk üzerindeki dosya ya da dizinler platform bagımsız olarak

kullanıbilmektedir.

Önceki örneklerimizde dosyaları hep birer String ile ifade etmistik. Burada bir dosyanın “File” nesnesi haline

getirildikten sonra da bazı metdolar yardımıyla nasıl kullanılabilecegine dair bir örnek yapacagız. Örnegimizi

incelemeden önce bir File nesnesine ait bazı metodları inceleyelim:

boolean canRead():

 

Nesnenin ifade ettigi dosyanın okunabilirligini kontrol eder.

boolean canWrite():

 

Nesnenin ifade ettgi dosyanın yazılabilirligini kontrol eder.

boolean createNewFile():

 

Nesneye verilen path içerisinde bos bir dosya yaratır. Ancak bu dosyanın mevcut dizin

içerisinde önceden yaratılmamıs olması gerekir.

boolean delete():

 

Nesnenin isaret ettgi path içerisindeki dosyayı siler.

boolean exists():

 

Verilen path içerisinde yer alan dosya ya da dizinin var olup olmadıgına bakar.

String getAbsolutePath():

 

Nesnenin ifade ettigi dosya ya da dizinin tam yol bilgisini string olarak verir.

99

String [] list():

 

Nesnenin isaret ettigi dizin içerisindeki dosya ya da dizinlerin bir listesini verir. Bu liste de String

türünden bir dizi olarak olusturulur.

boolean mkdir():

 

Verilen path içerisinde yeni bir dizin yaratır.

boolean renameTo(File hedef):

 

Nesnenin isaret ettigi dizin ya da dosyayının ismini parametre ile verilen yeni

isme dönüstürür.

Tabi ki aslında “File” nesnesi yukarıda özetlenenden daha fazla hazır metoda sahiptir. Ancak burada genel bilgi

vermek amacıyla bu kadarından bahsetmeyi yeterli görüyorum. Daha önce de söyledigim gibi herhangi bir java

sınıfının içerdigi degisken ya da metodları bulabileceginiz dökümantasyon sayfasına (1.4.2 için)

http://java.sun.com/j2se/1.4.2/docs/api/index.html

 

 

adresinden erisebilirsiniz.

Simdi File sınıfını kullanarak yazacagımız bir örnekle konuyu daha iyi pekistirelim:

Odev:

1çerisinde

Name:Surname:Address:ID

Academy:tech:26:Address:1302

seklinde bilgiler olan bir dosyadan bu bilgileri cekerek Person nesnesi haline getiren ve bu personlari bir dizide

saklayan bir uygulama yaziniz. Daha sonra bu diziyi sort ederek (Person nesnesinin compareTo metodu olmali)

ekrana basiniz. Ve en son olarak bu bilgileri nesneler halinde Object Serialization yontemi yardimiyla baksa bir

dosyada saklayiniz.

Arastirma konusu:

 

Dosyadan Turkce karakter okuma (ISO8859-9 formati, dosyalarin iso8859-9 formatinda

acilmasi)

100

Örnegimizde kullanıcıdan 10. satırda alınan bir dizin bilgisi “File” nesnesi halinde yaratılmaktadır. Böylece program

içerisinde File sınıfının sunacagı hazır metodlardan yararlanılabilir. Zaten 11. satırda bu metodlardan birisi olan list

metodu yardımıyla verilen dizin içerisindeki dosyalar String dizisi halinde elde edilir.

Bu noktaya kadar dosya islemlerini içeren baslıkların çogunu basit ve anlasılır örneklerle incelemis olduk. Bunu

ötesinde daha büyük uygulamalarda bu küçük parçalar kullanılarak konu daha iyi pekistirilecektir.

Dersimizin bundan sonraki kısmında Java programlama dilinin en güçlü yanlarından birisi olan grafik arayüz

gelistirmeyi ögrenecegiz.

101

Java ile Programlama

Bölüm 10:

Java ile Grafik Arayüz Gelistirme:

Grafik arayüz denilen sey aslında arka planda çalısan programların daha anlasılır olabilmesi amacıyla, ön tarafta

kullanıcıya sunulan ortamdır. Aslında bu tür ortamlarla zaten günlük bilgisayar kullanımında sıklıkla karsılasırsınız.

Örnegin internette gezinebilmek amacıyla kullandıgımız Netscape ya da Mozilla gibi web tarayıcılar birer grafik

araryüzdür. Gerçekte bilgisayarımız web siteleriyle, arka tarafta çesitli protokoller ve özel komutlar yardımıyla

iletisim kurar ve sayfaları alır ya da gönderir. Ancak ön planda çesitli text alanları, dügmeler ve menüler yardımıyla

bu islemleri daha anlasılır sekilde yapabiliriz.

Artık masaüstü kullanılan isletim sistemlerinin tamamı grafik arayüzleri ile donatılmıstır. Bir programın giris çıkıs

bilgilerine iliskin teknik detayların kullanıcıdan soyutlanması ve ona daha anlasılır bir etkilesim ortamının sunulması

gerekir. Bu nedenle, yazılan programlar en son asamada bir grafik arayüzü ile desteklenir ve böylece daha kullanıslı

hale gelir.

Java'da grafik arayüz gelistirmek önceden yazılmıs birtakım sınıfların kullanılması ile saglanır. Bu sınıflar en genel

anlamda javax.swing ve java.awt paketleri içerisinde toplanmıstır.

Öncelikli olarak bilinmesi gereken birtakım temel kavramlar incelendikten sonra sayısız grafik arayüz nesnesine

iliskin örnekler görecegiz. Bu örneklerin tamamında temel kavramları kullanacagız.

JFrame Kavramı:

Gelistirecegimiz tüm grafik arayüz uygulamaları (GUI) aslında JFrame sınıfından türetilmis uygulamalar olacaktır.

JFrame sınıfı aslında isletim sisteminden en temel pencere fonksiyonlarını alacak sekilde olusturulmustur.

Kullandıgınız isletim sistemine göre bu fonksiyonlar ve bunların ekrana getirilmesi islemleri farklılık göstereceginden

siz sadece JFrame sınıfını türeterek kendinizi bu farklılıktan soyutlarsınız. Zaten ilk derslerimizde de bahsettigimiz bu

teknik nesne yönelimli program gelistirmenin avantajlarından birisi olarak karsımıza çıkmaktadır. Asagıdaki örnekte

çok basit bir JFrame nesnesi ile grafik uygulamalarına baslayabiliriz.

import javax.swing.*;

import java.awt.*;

public class Cerceve extends JFrame {

public Cerceve() {

super("Benim ilk uygulamam");

this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);

this.setSize(300, 400);

this.setResizable(false);

this.show();

}

public void paint(Graphics g) {

g.setColor(new Color(200, 20, 208));

g.drawString("Merhaba ", 150, 200);

g.drawLine(0, 0, 300, 300);

g.setColor(Color.BLACK);

g.drawRect(149, 188, 50, 20);

g.setColor(Color.CYAN);

g.drawOval(30, 30, 100, 150);

g.fillOval(30, 30, 80, 120);

}

102

public static void main(String[] args) {

new Cerceve();

}

}

Yukarıdaki örnekte oldukça basit bir GUI uygulaması görmekteyiz. Daha önce de söyledigimiz gibi bu uygulama

önceden hazır olan JFrame sınıfının türetilmesi ile elde edilmektedir. Simdi bu uygulamayı detaylı olarak ele alalım

ve örnek üzerinde temel kavramlara deginelim.

Türetilen sınıfımızın baslangıç fonksiyonu içerisinde kullandıgımız “super” metodu önceden hatırlayacagımız gibi

temel sınıfın baslangıç metodunu çagırmaktadır. Bu metod kendisine gönderilen bir string ifadeyi ekranda çalısan

frame in baslıgı haline getirmektedir.

JFrame Metodları:

JFrame nesnesinden türeyen bir sınıf JFrame'e ait olan hazır metodları kullanabilir. Yine uygulamamızın baslangıç

metodunda kullandıgımız “setSize”, “setResizable” ve “show” metodları bu tür metodlardandır. “setSize” metodu

ekrana gelecek olan arayüzün satır ve sütün uzunlugunu olusturur. Bu bilgiler piksel olarak metoda verilmektedir.

“setResizable” metodu ekrana gelen arayüzün fare yardımıyla genisletilip genisletilemeyecegini belirlemek için

kullanılır. Parametre olarak verilen “false” degeri arayüzün sınırlarını sabit hale getirmektedir. En son satırda

kullanılan “show” metodu arayüzümüzün çalıstıktan sonra ekranda görünür olmasını saglar.

32 satırda uygulamamız türünden bir nesne yarattıgımızda baslangıç fonksiyonu otomatik olarak çagrılacak ve

gerekli boyut, listener ve diger ayarlar yapıldıktan sonra show metodu sayesinde çerçevemiz ekranda görünür halde

olacaktır.

24. satırda tanıtılmıs olan paint metodu çerçevemiz olusturulurken otomatik olarak çagrılan bir metoddur. Bu metod

her zaman bir “Graphics” nesnesini parametre olarak alır. Graphics nesnesine ait olan metodlar sayesinde

uygulamamız üzerine birtakım çizimler ve yazılar yerlestirebiliriz. 26. satırdaki metod sayesinde çizilecek ya da

yazılacak bilgilerin hangi renkte olacagı belirlenir. Bu renk belirleme islemi aslında setColor isimli metoda gönderilen

bir “Color” nesnesi ile belirlenir. Hemen o anda yarattıgımız Color nesnesinin baslangıç metodunda da 3 tane tam

sayı girlmektedir. Bu sayılar sırasıyla kırmızı yesil ve mavi bilesenlerini temsil eder. Her bilesen 0-255 arasında bir

deger alır ve istedgimiz renk bu 3 bilesenin karısımından elde edilir. 27. satırdaki “drawString” metodu ile

uygulamamız üzerine istenilen bir yazıyı yazabiliriz. drawString metoduna verilen diger 2 parametre ise bu yazının

hangi piksellerden baslayarak yazılacagını belirler.

Swing ve AWT

Java’da GUI nesnelerinin gelistirebilmek için kullanılan paketler swing ve awt paketleridir. Aslında swing paketi

awt’den daha sonra gelistirilmis ve nesneler swing paketi içerisinde hem artmıs hem de daha küçülmüstür Yani awt

paketinin gelistirilmis hali swing paketididir. Ancak yine de event handling mekanizmasi için awt paketi hala

kullanılmaktadır.

GUI Uygulamalarına Detaylı Bir Bakıs

Önceki dersimizde hazırlamıs oldugumuz “JavaGui” örneginde, GUI üzerinde yapılan bir takım hareketlerin listener

nesneleri tarafından yakalandıgından bahsetmistik. Hatta GUI uygulamamızda pencerenin “çarpı” dügmesine

bastıgımızda uygulamanın gerçek anlamda sonlanması, bu hareketin yakalanması ve bizim istedigimiz sekilde ele

alınması sonucunda mümkün olmustu.

Listener Kavramı

GUI uygulamalarında “listener” kavramı çok önemli bir yer tutar. Bu önemi GUI uygulamalarının yazılıs nedenine

bakarak rahatlıkla anlayabiliriz. Öyle ki; bir GUI uygulaması yazılmıs bir programın kullanıcı tarafından daha rahat

103

kullanılabilmesi amacı ile yazılmaktadır. O halde kullanıcının hizmetine sunulan bir GUI uygulaması kullanıcının

isteklerini de algıyabilmelidir.

GUI uygulamaları, genel olarak bir takım hazır nesnelerin (Dügme, ScrollBar, Text Alanları v.b.) uygulama üzerine

yerlestirilmesi seklinde hazırlanır. 1ste bu uygulmaların ikinci kısmını da bu nesneler üzerinde yapılan hareketlerin

algılanması olusturur.

Asagıdaki örnegimizde basit bir GUI çerçevesi üzerinde bir Jbutton nesnesi eklenmekte ve bu nesnenin harektleri

takip edilecek sekilde uygulama tasarlanmaktadır:

import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

import javax.swing.event.*;

public class SwingOrnek1 extends JFrame {

Container c;

JButton dugme;

Dinleyici dinleyici;

public SwingOrnek1() {

super("GUI Nesneleri");

c = this.getContentPane();

dinleyici = new Dinleyici();

dugme = new JButton("Mesaji Goster");

dugme.addActionListener(dinleyici);

c.add(dugme);

this.addWindowListener(new WindowAdapter() {

public void WindowClosing(WindowEvent e) {

System.exit(0);

}

});

this.setSize(300, 300);

this.show();

}

}

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.*;

public class Dinleyici implements ActionListener {

public void actionPerformed(ActionEvent e) {

if(e.getActionCommand() == "Mesaji Goster") {

JOptionPane.showMessageDialog(null, "Dugmeye Basildi.");

}

}

}

public class Monitor {

public static void main(String[] args) {

new SwingOrnek1();

}

104

}

Örnegimiz 3 dosyadan olusmaktadır. Bu dosyalardan “Monitor.java” dosyası aslında kendi basına bir islevi olmayan

ve genel olarak tüm uygulamayı çalıstırmaya yönelik bir sınıf olarak yazılmıstır.

“Dinleyici.java” sınıfı aslında orjinal adıyla “listener” olarak isimlendirilen ve ActionListener arayüzünü implement

eden bir sınıftır. Bu sınıf kendisine atanan nesneleri sürekli dinleyen ve ilgili nesneye yapılan her hareketi takip eden

bir sınıftır. Bu sınıf içerisinde yer alan “actionPerformed” isimli metod, bu sınıfın dinledigi herhangi bir nesneye

müdahele oldugu zaman otomatik olarak çagrılmaktadır.

Aslında daha teknik olarak ifade etmek gerekirse, herhangi bir nesneye yapılan müdahele sonucunda Java’da

“ActionEvent” yaratılmaktadır. Yaratılan bu “ActionEvent” ise ilgili nesneyi dinleyen listener sınıfının

“actionPerformed” metoduna parametre olarak gönderilmektedir. O halde bizim örnegimizde “SwingOrnek1.java”

dosyasının 20. satırında dinlenmek üzere eklenen “JButton” nesnesine dokunuldugunda bir action yaratılmakta ve

bu nesneyi dinelyen “dinleyici” isimli sınıfa gönderilmektedir. Bu metoda gelen eventin hangi nesneye ait oldugu

“ActionEvent” nesnesinin “getActionCommand” metoduyla anlasılmaktadır. Bu metodun geri dönüs degeri

ActionEvent halinde gelen nesnenin üzerinde yazan etikettir. O halde sunu da belirtmek gerekir ki listener tipindeki

bir sınıf aynı anda birden fazla nesneyi dinleyebilir. Ya da bir baska deyisle, birbirinden farklı birden fazla nesne,

aynı listener sınıfının dinlenme listesine eklenebilir. Bizim örnegimizdeki “dugme” isimli JButton nesnesi,

SwingOrnek1.java dosyasında 20. satırda dinleyici sınıfının dinlenecek nesnelerinden birisi olarak eklenmektedir.

Dinleyici degiskeni de yine aynı dosyadaki 10. satırda “Dinleyici” sınıfı türünden yaratılmıstır. Dinleyici sınıfı da

“ActionListener” arayüzünden türetildigine göre, bu sınıfın dinleme yetenegi vardır.

Action Nesneleri Hakkında

Genelde belirli bir menu nesnesi tarafından tetiklenen bazı komutlar bazı baska nesneler tarfından da tetiklenebilir.

Mesela bir menu nesnesinde tanmlı olan bir komut bir toolbar nesnesi içerisinde de tetiklenebilir.

Kullanıcı belirli bir nesne için belirli bir fonksiyon atayabilir. Bu nesne bir menu nesnesi, bir dugme ya da bir toolbar

nesnesi olabilir.

Mesela adı blueAction olan bir nesne ColorAction nesnesinde türemis bir nesne olsun. ColorAction nesnesi de

ActionListener’ı implement eden bir nesne olsun. O halde yaratılan bir dügmenin dinleyicisi olarak blueAction

nesnesi kullanılabilir ve bu nesne de sadece arka plan rengini maviye dönüstürecek sekilde yazılmıs olabilir.

O halde artık bu nesne birden fazla nesne tarafında listener olarak kullanılabilir.

105

Swing paketleri içerisinde Action denilen bir arayüz sayesinde yukarıda bahsettigimiz bu mekanizma çok verimli bir

sekilde ele alınabilir. Bu arayüz birçok listener arayüzünde tetiklenen metoduları içerir:

interface Action {

void actionPerformed(ActionEvent e);

void setEnabled(boolean b);

boolean isEnabled();

void putValue(String key, Object value);

Object getValue(Sting key);

void addPropertyChangeListener(PropertyChangeListener listener);

void removePropertyChangeListener(PropertyChangeListener listener);

}

putValue ve getValue metodları action nesnesi içerisinde anahtar deger ikililerinin tutmaya olanak verir. Bunun için

Action sınıfı içerisinde tanımlı bazı sabitlerden yararlanırız.

NAME, SMALL_ICON, SHORT_DESCRIPTION, LONG_DESCRIPTION, MNEMONIC_KEY, ACCELERATOR_KEY,

ACTION_COMMAND_KEY gibi...

Eger action bir menu ya da toolbar nesnesine eklendigi zaman NAME ve SMALL_ICON otomatik olarak nesne bu

degerler için ayarlanır. SHORT_DESCRIPTION degeri de nesne de tooltip olarak set edilir.

Action, bir arayüz oldugu için daha kolay bir kullanımı saglayan AbstractAction sınıfı kullnılabilir. Bu sınıf içerisinde

tüm metodlar gerektigi sekilde implement edilmistir. Ancak sadece actionPerformed metodu soyut olarak

bırakılmıstır.

Mesela yeni bir action tanımlamlayalım

 

:

public class ColorAction extends AbstractAction {

public ColorAction(String name, Icon icon, Color c) {

putValue(Action.NAME, name);

putValue(Action.SMALL_ICON, icon);

putValue(“color”, c);

putValue(Action.SHORT_DESCRIPTION, “Set panel color to ” +

name.toLowerCase);

}

public void actionPerformed(ActionEvent e) {

Color c = (Color)getValue(“color”);

setBackground(c);

}

}

Bundan sonra bu action istenilen nesneler için kullanılabilir:

Action blueAction = new ColorAction(“Blue”, new ImageIcon(“blue.gif”), Color.BLUE);

JButton blueButton = new JButton(blueAction);

Container Kavramı

Su ana kadar aslında bir GUI nesnesinin nasıl dinlendigini ögrendik. Peki ama bir GUI nesnesi nasıl çerçeve içerisine

eklenebilir? Bu islem örnegimizin 16. satırında gerçeklesmektedir. GUI nesnelerinin bazıları diger nesneleri üzerinde

tasıma yetenegine sahiptir. Bu yetenege sahip olan nesnelerden birtanesinin JFrame oldugunu görmekteyiz. Öyle ki

bizim örnegimiz temelde bir JFrame nesnesidir. Bu sayede üzerine bir JButton nesnesi ekleyebiliyoruz. Ancak

JFrame nesnesine bu eklemeyi yapmadan önce 8. satırda oldugu gibi “Container” sınıfı türünden bir degisken

yaratmaktayız. Bu degisken nesneleri tutabilen bir yapı haline gelmektedir. 16. satırdaki “getContentPane” isimli

metod yazmıs oldugumuz JFrame nesnesinin panelini bu tasıyıcıya atadıgından, container nesnesine eklenen her

106

nesne dolayısı ile JFrame nesnesi üzerine eklenmis olacaktır. Bu da bizim uygulamamızın (SwingOrnek1 sınıfı)

kendisidir.

Container ve JFrame arasındaki iliskiyi asagıdaki sekilde irdeleyebiliriz.

NOT: Bizim uygulamamız JFrame nesnesidir. Çünkü uygulamamızı JFrame nesnesinden türetmekteyiz. Önceki

dersleri hatırlayınız.

Layout Kavramı

Genel olarak bakıldıgında uygulamamızda bir sorun görmekteyiz. Öyle ki “dugme” adıyla eklemis oldugumuz

JButton nesnesi bütün çerçeveyi kaplamaktadır. Bu görüntü alısılmıs bir dügme görüntüsünden farklıdır. Bunun

sebebi bu tür nesneleri tasımak üzere yarattıgımız Container nesnesinin “layout” modelini belirtmemis olmamızdır.

Layout denilen kavram tasıyıcı görevi üstlenen bir nesnenin kendisine eklenen diger nesneleri hangi düzende

yerlestireceginin belirleyen bir kavramdır.

Layout modellerinden ilki olarak FlowLayout modelini inceleyebiliriz. Bu tasıyıcı nesneye (yani container nesnesine)

eklenen her nesne (JButton ve daha sonra ögrenecegimiz diger Swing nesneleri gibi) arka arkaya ve satır satır

eklenmektedir. Çerçeve üzerinde bir satır bittikten sonra eklemeye alt satırdan devam edilir.

Asagıdaki örnekte FlowLayout modeli kullanılarak nesneler eklenmektedir. Ayrıca bu örnekte listener sınıfı için yeni

ve ayrı bir sınıf yaratmak yerine çerçevenin kendisi aynı zamanda Listener olarak kullanılmaktadır. Bu nedenle

addActionListener metoduna eklenecek sınıf olarak “this” yani sınıfın kendisi verilmektedir

 

.

import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

import javax.swing.event.*;

public class LayoutDeneme1 extends JFrame implements ActionListener {

107

Container c;

JButton dugmeler[] = new JButton[10];

public LayoutDeneme1() {

c = 0this.getContentPane();

c.setLayout(new FlowLayout(FlowLayout.LEFT));

for(int i = 0; i < dugmeler.length; i++) {

dugmeler[i] = new JButton("dugme_"+i);

dugmeler[i].setSize(10,15);

dugmeler[i].addActionListener(this);

c.add(dugmeler[i]);

}

this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);

this.setSize(300, 300);

this.show();

}

public void actionPerformed(ActionEvent e) {

for(int i = 0; i < dugmeler.length; i++)

if(e.getSource() == dugmeler[i]) {

JOptionPane.showMessageDialog(this, i + " Nolu Dugmeye Basildi");

}

}

public static void main(String arg[]) {

new LayoutDeneme1();

}

}

“LayoutDeneme1” sınıfı, bildiriminden de anlasıldıgı gibi hem bir JFrame nesnesi, hem bir listener hem de kendi

basına çalısabilen bir uygulama olarak tasarlanmıstır. Uygulama üzerine yerlestirilecek JButton nesneleri bir JButton

dizisi içerisinde saklanmaktadır. Bu dizi 9. satırda yaratılmaktadır. 17 satırda ise for döngüsünün her adımında

dizinin ilgili elemanı JButton nesnesi olarak yaratılmakta ve yaratılırken de otomatik bir isim verilmektedir.

18. satırda JButton nesnesine ait olan “setSize” isimli bir metod sayesinde her JButton nesnesi sabit bir büyüklükte

yaratılmakta ve böylece daha dogal bir görüntü saglanmaktadır. Aynı döngü içerisinde ilgili nesne yaratılır

108

yaratılmaz ActionListener görevini üstlenen sınıfa, yani bu örnekte sınıfın kendisine eklenmektedir. Sınıfın kendisi

ActionListener oldugu için de sınıf içerisine ActionListener arayüzüne sahip olan “actionPerformed” metodunun

mutlaka yazılması gerekir

(Arayüzlerde belirtilen metod prototiplerinin, bu arayüzleri implement eden sınıflarda yazılmak zorunda oldugunu

hatırlayınız).

Bu islem 32. satırda yapılmaktadır.

20. satırda yaratılan her JButton nesnesi Container olarak yaratılan c nesnesine eklenmektedir. Ancak 14. satırda

görüldügü gibi c nesnesinin layout yapısı “FlowLayout” oldugundan eklenen her JButton nesnesi sırayla ve arka

arkaya eklenmekltedir. Bu sonuç, program çalıstırıldıgında yukarıda sekilde oldugu gibi açıkça görülmektedir. Ayrıca

FlowLayout bildirimi yapılırken kullanılan LEFT sabit degiskeni ekleme sırasının her satır için soldan saga dogru

olacagını belirler. Bunun dısında RIGHT ya da CENTER da kullanılabilir.

Bu örnekte birden fazla aynı türe iliskin nesnelerin bir dizi içerisinde otomatik olarak nasıl yaratıldıgını 16. satırda

görmekteyiz. Genel olarak bu sıra su sekilde listelenebilir:

Dizinin her adımı için:

a) Nesneyi yarat

b) Nesneyi özellestir (Boyut, renk vb.)

c) Nesneyi listener sınıfına kaydet

d) Nesneyi conatiner nesnesine ekle.

32. satırda da bu sekilde dizide saklanan nesnelerin nasıl kullanıldıgını görmekteyiz. Döngünün her adımında ilgili

nesnenin otomatik olarak verilmis adı yardımıyla mesaj penceresi hazırlanmaktadır. Ancak bu sefer üzerinde islem

yapılan nesne, nesnenin üzerindeki isme bakılarak degil, gerçekten kendisine bakılarak tespit edilmektedir. Bunu

saglayan metod ActionEvent sınıfının “getSource” isimli metodudur. Demek ki bir ActionEvent yaratıldıgında bu

nesnenin hangi nesne oldugunu ya “getActionCommand“ yardımıyla nesne üzerindeki isime bakarak, ya da

“getSource” metodu yardımıyla nesnenin kendisine bakarak anlayabiliriz.

Bir baska layout modeli de BorderLayout’dur. Bu modele göre tasıyıcı nesne üzerinde kuzey, güney, dogu ve batı

olarak 5 tane alan vardır ve nesneler bu alanlardan birisine yerlestirilir. Aslında contenPane içerisindeki öntanımlı

layout modeli de zaten budur. Eger yukarıdaki örnekte layout modeli BorderLayout olarak degistirilirse nesneler

buna göre istenen bölgeye yerlestirilebilir. Gerekli degisiklerle birlikte az önceki örnegin yeni hali asagıdadır:

import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

import javax.swing.event.*;

public class LayoutDeneme2 extends JFrame implements ActionListener {

Container c;

JButton dugmeler[] = {new JButton("dugme_0"), new JButton

 

("dugme_1"),

new JButton("dugme_2"), new JButton("dugme_3"),

new JButton("dugme_4")};

public LayoutDeneme2() {

c = getContentPane();

c.add(dugmeler[0], BorderLayout.WEST);

c.add(dugmeler[1], BorderLayout.EAST);

c.add(dugmeler[2], BorderLayout.SOUTH);

c.add(dugmeler[3], BorderLayout.NORTH);

c.add(dugmeler[4], BorderLayout.CENTER);

for(int i = 0; i < dugmeler.length; i++)

dugmeler[i].addActionListener(this);

109

this.addWindowListener(new WindowAdapter() {

public void WindowClosing(WindowEvent e) {

System.exit(0);

}

});

this.setSize(300, 300);

this.show();

}

public void actionPerformed(ActionEvent e) {

for(int i = 0; i < dugmeler.length; i++)

if(e.getSource() == dugmeler[i]) {

JOptionPane.showMessageDialog(this, i + " Nolu Dugmeye Basildi");

}

}

public static void main(String arg[]) {

new LayoutDeneme2();

}

}

Bu örnekte görüldügü gibi ekleme isleminde kullandıgımız add metoduna bir de eklemenin hangi bölüme yapılacagı

bilgisi de verilmelidir. Buraya kadar sadece en temel kavramları vermek amacıyla Container, Layout ve Swing

nesnelerini en az özellikleriyle inceledik.

Su anda amacımız genel yapıyı ve hiyerarsiyi kavramak oldugundan bu nesnelerin kendi içindeki detaylara simdi

girmiyoruz. Böylece en azından örneklerimizi anlayacak kadar temel bilgileri edinmis oluyoruz. 1lerleyen konularda

bu temel kavramların herbirini kendi içinde daha detaylı inceleyecegiz.

JPanel Nesnesi

Artık genel anlamda bir JFrame nesnesi yaratmayı, bu nesneye baska nesneler eklemeyi ve eklenen bu nesneleri de

takip etmeyi ögrendik. Nesnelerin JFrame üzerine eklenmesi için bir Container kullandık. Ancak bazen nesneleri

direk JFrame üzerine eklemek kullanıslı olmayabilir. Bu nedenle önce bazı nesneleri kendi içinde gruplayıp tek bir

nesne haline getirip bu ana nesneyi JFrame container üzerine eklemek daha anlasılır ve daha düzenli olabilir.

JPanel kendi basına üzerinde nesne tutabilen bir yapıdır. Yani JFrame’de oldugu gibi, bir JPanel nesnesi üzerine

baska bir nesne eklemek için contentPane olusturmaya gerek yoktur. Dogrudan JPanel üzerine nesneler eklenir ve

bu nesnelerin listener islemleri tamamlanır. Daha sonra bu JPanel nesnesi artık içerisinde baska nesneleri tutan tek

bir nesne gibi kullanılabilir. Aslında bu islemleri yaparken de gerçek anlamda nesne yönelimli programcılık

yaptıgımızı özellikle belirtmek isterim.

Asagıdaki örnekte bir text alanı içerisindeki yazı üzerinde renk ve boyut düzenlemeleri yapan bir uygulama

gelistirilmektedir. Ancak bu düzenleme opsiyonları ayrı gruplar halinde paneller üzerinde tasarlanıp daha sonra

çerçeve üzerine eklenmektedir. Uygulama çalıstıktan sonra asagıdaki gibi bir GUI ekrana gelmektedir:

RESIM:

RESIM ADI: JpanelOrnek1Cikis.png

ALT BASLIK: JPanelOrnek1 Uygulamasının Çalısması

import javax.swing.*;

import javax.swing.event.*;

import java.awt.*;

import java.awt.event.*;

public class JPanelOrnek1 extends JFrame implements ActionListener {

JPanel colorPanel, sizePanel, editPanel, southPanel;

JTextArea text;

110

JButton yellowButton, redButton, blueButton;

JRadioButton editable, noneditable;

ButtonGroup group;

Container c;

public JPanelOrnek1() {

c = this.getContentPane();

c.setLayout(new BorderLayout());

southPanel = new JPanel();

southPanel.setLayout(new BorderLayout());

colorPanel = new JPanel(new FlowLayout());

yellowButton = new JButton("Sari");

yellowButton.addActionListener(this);

colorPanel.add(yellowButton);

redButton = new JButton("Kirmizi");

redButton.addActionListener(this);

colorPanel.add(redButton);

blueButton = new JButton("Mavi");

blueButton.addActionListener(this);

colorPanel.add(blueButton);

yellowButton.setBackground(Color.BLACK);

yellowButton.setForeground(Color.WHITE);

redButton.setBackground(Color.BLACK);

redButton.setForeground(Color.WHITE);

blueButton.setBackground(Color.BLACK);

blueButton.setForeground(Color.WHITE);

southPanel.add(colorPanel, BorderLayout.SOUTH);

editPanel = new JPanel(new FlowLayout());

group = new ButtonGroup();

editable = new JRadioButton("Duzenlenebilir", false);

group.add(editable);

editable.addActionListener(this);

editPanel.add(editable);

noneditable = new JRadioButton("Duzenlenemez", true);

group.add(noneditable);

noneditable.addActionListener(this);

editPanel.add(noneditable);

southPanel.add(editPanel, BorderLayout.NORTH);

text = new JTextArea();

text.setText("Deneme Yazisi");

text.setEditable(true);

c.add(text, BorderLayout.CENTER);

c.add(southPanel, BorderLayout.SOUTH);

this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);

this.setSize(300, 300);

this.show();

}

public void actionPerformed(ActionEvent e) {

if(e.getSource() == yellowButton) {

text.setBackground(Color.YELLOW);

111

yellowButton.setBackground(Color.YELLOW);

redButton.setBackground(Color.BLACK);

blueButton.setBackground(Color.BLACK);

}

else if(e.getSource() == redButton) {

text.setBackground(Color.RED);

yellowButton.setBackground(Color.BLACK);

redButton.setBackground(Color.RED);

blueButton.setBackground(Color.BLACK);

}

else if(e.getSource() == blueButton) {

text.setBackground(Color.BLUE);

yellowButton.setBackground(Color.BLACK);

redButton.setBackground(Color.BLACK);

blueButton.setBackground(Color.BLUE);

}

if(e.getSource() == editable)

text.setEditable(true);

else if(e.getSource() == noneditable)

text.setEditable(false);

repaint();

}

public static void main(String[] args) {

new JPanelOrnek1();

}

}

Simdi bu örnegimizi biraz daha derinlemesine inceleyelim. Öncekilerde oldugu gibi bu sınıf da, yine bir JFrame

uygulaması ve aynı zamanda ActionListener olarak yaratılmaktadır.

Ancak bu sefer birtakım nesneler dogrudan JFrame’in Container nesnesi üzerine yerlestirilmek yerine, önce bazı

paneller üzerine yerlestirilmis ve daha sonra bu paneller JFrame üzerine eklenerek uygulama tamamlanmıstır.

Örnegimizde tüm nesneleri kendi üzerinde tasıyan JFrame nesnesinin Container’ı 18. satırda yaratılmaktadır. Daha

sonra sadece renk opsiyonlarının ayarlanacagı dügmeleri barındıracak olan “colorPanel” isimli bir JPanel nesnesi

yaratılmıs ve 24. satır ile 33. satırlar arasında bu panelin tutacagı nesneler de tek tek yaratılarak panel üzerine

eklenmistir.

Benzer sekilde ekrana gelen text alanına yazmayı saglayan ya da yazma opsiyonunu kaldıran seçenekleri barındıran

“editPanel” isimli bir baska JPanel nesnesi ve onun tutacagı nesneler de 37. ve 46. satırlar arasında yaratılmaktadır.

En son olarak üzerinde editPanel ve colorPanel panellerini tutacak olan bir baska JPanel nesnesi “southPanel” adıyla

22. satırda yaratılmıs ve JFrame’in c isimli Container nesnesinin SOUTH bölgesine 54. satırda yerlestirilmistir.

c isimli Container’ın CENTER bölgesine ise JTextArea isimli nesne 53. satırda oldugu gibi dogrudan yerlestirlmistir.

Bunun dısında aslında uygulama genel olarak diger nesnelerin yaratılması ve bazı özelliklerinin set edilmesi seklinde

tamamlanmaktadır. Burada karsımıza JTextArea ve JRadioButton isimli iki yeni GUI nesnesi gelmektedir.

Aslında adından da anlasılabilecegi gibi JTextArea isimli nesne bize içerisine yazı yazabilecegimiz bir text alanı

sunmaktadır. Yine birçok hazır metodu sayesinde bu nesnenin bazı özelliklerini degistirmek mümkündür.

JRadioButton nesneleri de benzer sekilde seçim dügmeleri yaratmamızı saglar. Ancak bu nesneler yaratıldıktan

sonra bir de 12. satırda yaratılan “ButtonGroup” adında bir nesne içerisine eklenmektedir. Bu ekleme, bir

RadioButton seçili iken digerinin otomatik olarak seçilmemesini saglamaktadır. Eger birden fazla radio button

nesnesini ButtonGroup içerisine eklemezseniz, aynı anda birden fazla seçim yapabilirsiniz.

112

Böylece genel anlamda bir GUI uygulmasında ilk olarak hiyerarsiyi belirlemek gerektigini ve daha sonra da bu

hiyerarsiye uyarak gerekli olan GUI nesnelerini birtakım özellikleriyle yaratarak paneller üzerine eklemek gerektigini

görmekteyiz.

Seçim yapmak üzere üzerine basılan ya da seçim yapılan bu nesnelerin her biri bir ActionEvent üretmektedir.

Listener’a eklenen tüm nesneler için bu ActionEvent’ler de dogrudan actionPerformed metoduna göderilmektedir.

Buna göre gönderilen her ActionEvent için JTextArea nesnesinin bir özelligi degistirilmektedir. Böylece kullanıcı asıl

olarak kullandıgı text alanını seçimlere göre degistirebilme olanagına sahip olur. Bu degisimler 66. satırdaki

actionPerformed metodunda ele alınmıstır.

GUI derslerimizin bundan sonra devam edecek olan kısımlarında öncelikle yukarıda bahsedilen temel kavramların

kendi içinde detaylarına deginecek ve daha sonra da birçok GUI nesnesini tek tek ele alarak inceleyecegiz. Daha

sonra kapsamlı bir GUI uygulaması gelistirerek GUI derslerimizi geride bırakacagız.

Bu derste anlatılan temel bilgileri kendiniz de deneyerek test etmeli ve kavramları iyice irdelemelisiniz.

ARASTIRMA ÖDEV

Uygulama olarak; yukarıda verilen son örnegimize bir de yazı fontunun rengini degistiren opsiyonların yeraldıgı bir

panelin nasıl eklenecegini arastırabilirsiniz. Bunun için ipucu olarak JTextArea nesnesinin bir metodunu (setFont)

kullanabilirsiniz. Ama ondan önce bu metodu tetikleyecek birtakım seçim dügmeleri yaratmalı ve bu dügmeleri bir

panel üzerine yerlestirerek uygulamaya dahil etmelisiniz. Bu da iyi bir tekrar ve yeni arastırma gerektirmektedir.

Simdiden kolay gelsin

 

 



113

Java ile Programlama

Java2D

Bundan önceki dersimizde arayüz tasarımına bir giris yapmıstık. Bazı nesneleri de kullanarak genel olarak arayüz

tasarımının nasıl ele alınacagını incelemistik. Bu genel kavramları incelerken

-

 

event handling

-

 

container

-

 

component

gibi kavramları da ögrenmistik. Bu dersimizde bu kavramları kendi içinde daha detaylı incelmeye baslayacagız.

Grafik arayüz programlarında sadece nesneler ile degil bu nesneler üzerinde de yazı ve sekil gibi animasyonların da

kullanıldıgını görmüstük. Hatırlarsak geçen dersimizde Graphics nesnesini yardımıyla bir component içerisinde yer

alan paint metodu yeniden yazılarak, ilgili componentin üzerinde istedigimiz gibi 2 boyutlu yazı ya da resimler

olmasını saglayabiliyorduk. Simdi bu iki boyutlu animasyonlar ile daha detaylı ilgilenecegiz.

Java 2 ile birlikte gelen Graphics2D kütüphanesi ve paintComponent Metodu

Java 2 ile birlikte daha da gelismis olan Graphics2d isimli kütüphane bu 2 boyutlu animasyonları daha detaylı ele

almamızı saglayan metodlara sahiptir. Eger “paintComponent” isimli metod kullanlırsa bu metoda otomatik olarak

Graphics2D kütüphanesi parametre olarak tanacaktır. Bizim yapmamız gereken tek sey gelen bu Graphics2D

nesnesi için bir tür dönüsümü yapmaktır.

Örnek:

public void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D) g;

g2.birseyler..

....

}

Graphics2D de sekiller daha nesne yönelimlidir

Graphics’D kütüphanesi içerisinde Rectangle2D, Line2D, Ellipse2D gibi sekiller daha nesne yünelimli olarak ele

alınmaktadır. Örnegin yeni bir dörtgen çizmek için:

Rectangle2D rect = new Rectangle2D(...);

g2.draw(rect);

demek yeterlidir. Oysa Graphics kütüphanesinde bu çizimlerde her sekil için ayrı bir metod kullanmak gerekirdi.

Graphics2D’de birimler int pikseller degil float degerlerdir.

Graphics2D’de sekilleri ifade etmek için kullanılan boyu ve nokta bilgileri int pikseller ile ifade edilmemktedir. Bunun

nedeni sekiller inch ya da milimetre gibi daha esnek birimlerle belirtme olanagı saglamaktır. Bu nedenle birimler

float degerler olarak ele alınmaktadır.

Ancak bu durumda da float degerlerin kullanılması zorunlu bir bildirim gerektirdiginden bu degeri float olarak ele

almak zorlasmaktadır. Örnegin

float f = 1.2 // yanlıstır. Bu deger double kabul edilir. Bunu float yapmak içi 1.2F yazılmalıdır.

Bu kargasayı basitlestirmek amacıyla birer iç sınıf olan Rectangle2D.Double ya da Rectangle2D.Float kullanılabilir.

Böylece koordinat bilgiler ister float istenirse de double türünden ele alınabilir.

114

NOT: yi ama madem float degerlerde tür dönüsümü zorluk çıkarıyorsa neden sadece double degerler

kullanılmıyor?

Çünkü aslında float degerler double degerlerin yarısı kadar yer kaplar ve float degerleri ile yapılan hesapmalara

double degerlerden daha hzlıdır.

import javax.swing.*;

import java.awt.*;

import java.awt.geom.*;

public class SekilCizim extends JFrame {

DrawPanel panel;

Container c;

public SekilCizim() {

c = this.getContentPane();

panel = new DrawPanel();

c.add(panel);

this.setSize(400, 400);

this.setTitle("Sekiller");

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.show();

}

public static void main(String arg[]) {

new SekilCizim();

}

}

class DrawPanel extends JPanel {

public void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D)g;

Rectangle2D rectangle = new Rectangle2D.Double(100, 100, 200, 150);

Ellipse2D ellipse = new Ellipse2D.Double();

super.setBackground(Color.BLACK);

g2.setColor(Color.GREEN);

ellipse.setFrame(rectangle);

g2.draw(rectangle);

g2.draw(ellipse);

}

}

Asagıdaki örnekte de yine Graphics2D kutuphanesi kullanılarak 2 boyutlu basit bir grafik ugulaması gelistirilmistir:

115

import

 

java.awt.event.*;

import java.awt.*;

import javax.swing.*;

import java.awt.geom.*;

public class Eksen extends JFrame implements ActionListener {

JTextField xpoint, ypoint;

JButton setPointsButton;

CoordinatePanel coordinate;

JPanel settings;

Container c;

public Eksen() {

this.prepareComponents();

this.prepareFrame();

}

public void prepareFrame() {

this.setSize(420, 470);

this.setTitle("Sekiller");

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.show();

}

public void prepareComponents() {

c = this.getContentPane();

c.setLayout(new BorderLayout());

coordinate = new CoordinatePanel();

116

c.add(coordinate, BorderLayout.CENTER);

xpoint = new JTextField(3);

ypoint = new JTextField(3);

setPointsButton = new JButton("set point to new coordinates");

setPointsButton.addActionListener(this);

settings = new JPanel();

settings.setLayout(new FlowLayout());

settings.add(new JLabel("x: "));

settings.add(xpoint);

settings.add(new JLabel("y: "));

settings.add(ypoint);

settings.add(setPointsButton);

c.add(settings, BorderLayout.SOUTH);

}

public void actionPerformed(ActionEvent e) {

if(e.getSource() == this.setPointsButton) {

JOptionPane.showMessageDialog(this, "dugmeye basldi");

coordinate.setPoint(Integer.parseInt(xpoint.getText()),

Integer.parseInt(ypoint.getText()));

this.repaint();

}

}

public static void main(String arg[]) {

new Eksen();

}

}

class CoordinatePanel extends JPanel {

int currentX, currentY;

Ellipse2D nokta = new Ellipse2D.Double();

int xSize = 400, ySize = 400;

public CoordinatePanel() {

this.setSize(this.xSize, this.ySize);

this.currentX = 10;

this.currentY = 20;

this.setPoint(currentX, currentY);

}

public void paintComponent(Graphics g) {

Graphics2D g2 = (Graphics2D)g;

Line2D yline = new Line2D.Double(this.xSize/2, 0, this.xSize/2,

this.ySize);

Line2D xline = new Line2D.Double(0, this.ySize/2, this.xSize,

this.ySize/2);

// noktanin yeni koordinatlari relative olarak belirleniyor

117

nokta.setFrame(this.xSize/2+this.currentX-5, this.ySize/2-this.currentY-

5, 10, 10);

g2.draw(xline); g2.draw(yline);

g2.fill(nokta);

}

//Bu metod notanin yeni koordinatlarini set ediyor.

public void setPoint(int x, int y) {

this.currentX = x;

this.currentY = y;

this.repaint();

}

}

SystemColor Sınıfı

Daha önce Color sınıfı yardımıyla birtakım renk nesneleri tanımlayabiliyorduk. SystemColor sınıfı içerisinde öntanımlı

olarak bulunan birçok statik renk nesnesi vardır. Bu nesneler otomatik olarak kullanılan isletim sistemi nesnelerinin

renklerinje göre ayarlanmıstır. Bu statik nesnelerin genel bir listesi:

-

 

desktop

-

 

activeCaption

-

 

window

-

 

windowBorder

-

 

windowText

-

 

menu

-

 

menuText

-

 

text

-

 

textText

-

 

textInactiveText

-

 

textHiglight

-

 

textHiglightText

-

 

scrollbar

-

 

infoText

seklinde verilebilir. Mesela

frame.setBackground(SystemColor.desktop)

Text ve Font’lar

2 Boyutlu uygulamalar içerisinde kesinlikle ele alınması gereken nesneleri içerisinde textler ve fontlar gelmektedir.

Daha önceki örneklerimizden biliyoruz ki g.drawString isimli metod yardımıyla birtakım text bilgileri component

üzerine yazabiliyorduk. Ancak bu yazıda kullanılan fontu kendimiz belirleyemiyrduk.

Font Sınıfı

Java ‘da tanımlı olan Font isimli sınıf sayesinde yeni bir fon belirleyebiliyoruz. Öyle ki, bu font sistemde tanımlı olan

Font ailesinden birisi olacak sekilde, style ve size bilgisi ile yaratılabiliyor: Örnegin:

Font myFont = new Font(“SansSerif”, Font.BOLD, 12);

Font için kullnılabilecek style listesi

-

 

Font.BOLD

118

-

 

Font.ITALIC

-

 

Font.PLAIN

-

 

Font.BOLD + Font.ITALIC

seklinde verilebilir.

Sistemde yer alan fon t ailelerinin isimlerini de elde etmek mümkündür. Bunun için kullanılabilecek metod

GraphicsEnvironment isimli sınıfın içerisinde tanımlı olan getLocalGraphicsEnvironment isimli metodun geri dönüs

degeri olan sınıfın getAvailableFontFamilyNames isimli metodu kullanmak gerekir.

import javax.swing.*;

import java.awt.*;

public class Fonts {

public static void main(String[] args) {

String str= "";

String systemFonts[] =

GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();

for(int i = 0; i < systemFonts.length; i++)

str += i+": "+systemFonts[i]+"\n";

System.out.println(str);

}

}

majlar

Bundan önceki kısımda 2 boyutlu basit imajların nasıl çizilebileegini gördük. Ancak bazen sistemde yer alan fotograf

ve resimlerden meydana gelen imajları çizmek de gerekebilir. Bu imajlar harici olarak ele alınırlar ve program

içerisinde kullanılabilecek bir nesne haline getirilirler.

Öncelikle bir sekilde sistemde ya da ag üzerinde bir imajın yeralması gerekir. Daha sonra bu nesne program

içerisine Image nesnesi olarak çekilebilir. Ancak bu islem Toolkit sınıfnın getDefaultToolkit isimli metodundan geri

gelen sınıfın getImage isimli metodu ile mümkündür. Örnegin sistemimizde “sunset.jpg” isimli bir resim olsun:

import javax.swing.*;

import java.awt.*;

public class ImageFrame extends JFrame {

JScrollPane scroll;

ImagePanel imPanel;

Container c;

int WIDTH;

int HEIGHT;

119

public ImageFrame() {

c = this.getContentPane();

c.setLayout(new BorderLayout());

imPanel = new ImagePanel();

this.WIDTH = imPanel.getWidth();

this.HEIGHT = imPanel.getHeight();

c.add(imPanel);

this.prepareFrame();

}

public void prepareFrame() {

this.setSize(this.WIDTH, this.HEIGHT);

this.setTitle("ImageFrame");

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.show();

}

public static void main(String[] args) {

new ImageFrame();

}

}

class ImagePanel extends JPanel {

Image myImage;

public ImagePanel() {

myImage =

Toolkit.getDefaultToolkit().getImage("G:\\egitim_yazil_seminer\\egitimler\\"+

"ACADEMYTECH\\javaDersleri\\derstekiOrnekler\\Sunset.jpg");

MediaTracker tracker = new MediaTracker(this);

tracker.addImage(myImage, 0);

try {

tracker.waitForID(0);

} catch(InterruptedException e) {}

this.setSize(new Dimension(800, 600));

}

public void paintComponent(Graphics g) {

Graphics2D g2 = (Graphics2D)g;

g2.drawImage(myImage, 0, 0, null);

}

}

Arastırma Ödevi: Toolkit nesnesin ve getDefaultToolKit metodu ile geri gelen nesnenin metdolarını

arastırınız.

120

NOT:

 

ToolKit nesnesi yardımıyla bir frame’in ekranın ortasında görüntülenmesi:

Toolkit kit = Toolkit.getDefaultToolkit();

int screenX = (int)kit.getScreenSize().getWidth();

int screenY = (int)kit.getScreenSize().getHeight();

this.setLocation(screenX/2 -this.WIDTH/2, screenY/2- this.HEIGHT/2);

Olay Kontrolü (Event Handling)

1lk olarak olay kontrolü detaylarına bakacagız.

Daha önce temel olarak olay kontrol mekanizmasını zaten görmüstük. Herhangi bir nesnenin daha önceden

belirlenen bir listener içerisine kayıt edilmesi ve bu listener içerisinde ele alınmasıyla bir nesne için exception

handling yapmıs oluyorduk.

Bildigimiz gibi herhangi bir dinleyiciye kaydedilen nesne üzerinde bir olay meydana gelirse, bu olay even nesnesi

içerisinde tanımlı olarak kayıt edilen dinleyiciye gönderiliyordu.

Simdi bu layout mekanizmasını yeni bilgilerle tekrar ele alalım. asagıdaki örnekte java’da ele alınabilen birtakım

genel görüntü degisimleni saglayan bir program yazılmaktadır. Önce örnegimizi yazalım:

import java.awt.*;

import javax.swing.*;

import javax.swing.plaf.basic.BasicLookAndFeel;

import java.awt.event.*;

public class PlafTest extends JFrame implements ActionListener{

Container c;

JButton metalButton, motifButton, windowsButton;

public PlafTest() {

c = this.getContentPane();

c.setLayout(new FlowLayout());

this.metalButton = new JButton("Metal");

this.metalButton.addActionListener(this);

c.add(this.metalButton);

this.motifButton = new JButton("Motif");

this.motifButton.addActionListener(this);

c.add(this.motifButton);

this.windowsButton = new JButton("Windows");

this.windowsButton.addActionListener(this);

c.add(this.windowsButton);

this.setSize(400, 400);

this.setResizable(false);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.show();

}

public void actionPerformed(ActionEvent e) {

if(e.getSource() == this.metalButton) {

121

this.changeToMetal();

}

else if(e.getSource() == this.windowsButton) {

this.changeToWin();

}

else if(e.getSource() == this.motifButton) {

this.changeToMotif();

}

}

private void changeToMetal() {

try {

UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");

SwingUtilities.updateComponentTreeUI(this);

}

catch(Exception e) {}

}

private void changeToWin() {

try {

UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");

SwingUtilities.updateComponentTreeUI(this);

}

catch(Exception e) {}

}

private void changeToMotif() {

try {

UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");

SwingUtilities.updateComponentTreeUI(this);

}

catch(Exception e) {}

}

public static void main(String arg[]) {

new PlafTest();

}

}

Örnegimizde aslında temel olarak farklı bir islem yapmıyoruz. Sadece LookAndFeel olarak anılan ve genel sistem

görüntüsünü set etmeye yarayan birtakım hazır nesnleri kullanıyoruz. Bu nesneler her seferinde bu sekilde

kullanıldıkları için look-and-feel konusunda daha fazla detaya girmeyecegiz.

WindowEvent’lerin dinlenmesi

Window event, frame dedigimiz nesneler üzerinde meydana gelen olaylardır. Bir WindowEvent’i dinleyebilecek olan

listener ise WindowListener nesnesidir. Bu nesne de tıpkı ActionListener gibi bir arayüzdür. O halde bir sınıfı

WindowListener olarak dizayn etmek istiyorsak tıpkı ActionListener örneginde oldugu gibi ancak bu sefer

122

WindwListener nesnesini implement ederek sınıfımızı WindowEvent dinleyebilecek bir dinleyici sınıf haline

getirebiliriz.

bir WindowListener içerisinde asagıdaki metodlar yeralmaktadır:

public interface WindowListener {

void windowOpened(WindowEvent e);

void windowClosing(WindowEvent e);

void windowIconified(WindowEvent e);

void windowActivated(WindowEvent e);

void windowClosed(WindowEvent e);

void windowDeiconified(WindowEvent e);

void windowDeactivated(WindowEvent e);

}

Adaptör Sınıfları

1yi ama sadece tekbir olayı (mesela pencerenin kapatılması) ele alabilecek bir listener yaratmak için tüm bu

metodları yazmak zorındamıyız. Aslında WindowListener bir arayüz olduguna göre cevap evet olacaktır. 1çleri bos

olsa bile aslında ele almadıgınız olayları da yazmak zorunda kalırsınız. Ancak javba gelistricileri bunun da bir

çözümünü gelistirmislerdir. Öyle ki sadece belirli olayları ele almak istediginiz dinleyici sınıfları yazabilmek için

önceden bu sınıfları implement eden ve gerekli tüm metodlarını bos bir sekilde yazan sınıflar tasarlanmıstır. Bu

sınıflara “adaptör” sınıflar denilir.

Kullanıcı listener için arayüz kullanacagına bu arayüze iliskin adaptör sınıf kullanır ve Polymorphism yöntemiyle

sadece istedigi olayları ele alan metodları yeniden yazması yeterli olacaktır.

asagıdaki örnekte yaratılan çerçeve uygulaması bir windowListener’a kayıt edilecek ancak bu çerçevenin sadece

windowClosing ve windowIconified eventleri ele alınacaktır.

/*WindowEvents.java*/

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class WindowEvents extends JFrame {

Container c;

PencereDinleyici dinleyici = new PencereDinleyici();

public WindowEvents() {

c = this.getContentPane();

c.setLayout(new FlowLayout());

this.addWindowListener(dinleyici);

this.setSize(400, 400);

this.setResizable(false);

//this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.show();

}

public static void main(String arg[]) {

new WindowEvents();

123

}

}

class PencereDinleyici extends WindowAdapter {

public void windowClosing(WindowEvent e) {

JOptionPane.showMessageDialog(null, "Pencere kapaniyor");

System.exit(0);

}

public void windowIconified(WindowEvent e) {

JOptionPane.showMessageDialog(null, "Pencere iconfied ediliyor");

}

}

Yukarıdaki örnegimizde dinleyici olarak tasarkanan sınıf WindowListener nesnesini implement edecek sekilde degil,

WindowAdaptor isimli sınıfı extend edecek sekilde tasarlanmıstır. Daha önce de söyledigimiz gibi aslında

WindowAdaptor isimli sınıf zaten arka planda WindowListener sınıfını implement etmis ve bu arayüzün tüm

metodlarının için bos olarak yazmıstır. Böylece biz WindowAdaptor sınıfından türetme yaparak ve polimorfizm

özelligini kullanarak sadece istedigimiz dinleyici metodlarını yeniden yazarız.

KeyEvent’lerin Dinlenmesi

Klavyeye basıldıgında meydana gelen olaylar KeyEvent nesnesi seklinde yaratılmaktadır. Bu nesnelerin dinlenmesi

için kullanılabilecek dinleyici arayüzler KeyListener arayüzüdür. Ancak önceki kısımda anlattıgımız gibi sadece belirli

key eventler ele alındmak isteniyorsa, KeyAdaptor sınıfı da kullanılabilir. KeyListener arayüzünde yer alan metodlar

KeyListener arayüzünde yer alan metdoların listesi dökümantasyon yardımıyla elde edilebilir.

keyEvent keyReleased, keyTyped Metodları

Kullanıcı bir tusa bastıgı zaman KeyEvent isimli olay yaratılır. Benzer sekilde bir tus bırakıldıgı zaman

KEY_RELEASED isimli olay tetiklenir. Bu iki olayı bele alabileceginiz arayüz metodları keyPressed ve keyReleased

isimli metodlardır. Bu ikisini birden kapsayan 3. metod ise keyTyped isimli metoddur.

VK_ terminolojisi KeyEvent sabitleri ve metodları

Herhangi bir tusa basıldıgında iki tane kavram devreye girer. 1. hangi karaktere basılmıstır? 2. si ise aslında tam

olarak klavye üzerinde hangi tusa basılmıstır. Klavye üzerindeki tusları temsil eden saibitler VK_ ile ifade edilirler.

Örnegin:

KeyEvent.VK_A -> fiziksel olarak A tusunu temsil eder.

KeyEvent.VK_SHIFT -> fiziksel olar4ak shift tusunu temsil eder.

Bu ifadeler keyCode adı verilir ve KeyEvent nesnesinin

 

getKeyCode() metdu ile elde edilir. Bu ifaddelerin sayısal

karsılıkları yerine KeyEvent.VK_A seklinde kullanılmaları çok daha kolay olur.

Bunu yanı sıra klavyedeki control ya da shift gibi tusların o andaki durumlarını elde etmek için yine KeyEvent

nesnesinin

 

isShiftDown, isControlDown, isAltDown metodlarından yararlanılabilir

Mesela

public void keyPressed(KeyEvent e) {

124

int keyCode = e.getKeyCode();

if(keyCode == KeyEvent.VK_SHIFT)

....

Basılan tusun ürettigi tam karakter elde edilmek istendiginde

 

getKeyChar() metodu da kullanılabilir.

Simdi tüm bu bilgilerimizi pekistirmek amacıyla asagıdaki örnegi deneyelim:

/* SketchPanel.java*/

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.event.KeyEvent;

import java.awt.event.KeyListener;

import java.awt.geom.Line2D;

import java.awt.geom.Point2D;

import java.util.ArrayList;

import javax.swing.JPanel;

class SketchPanel extends JPanel {

Point2D last;

ArrayList lines;

public SketchPanel() {

last = new Point2D.Double(100,100);

lines = new ArrayList();

KeyHandler listener = new KeyHandler();

this.addKeyListener(listener);

}

public void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D)g;

//listedeki tum cizgileri ciziliyor

for(int i = 0; i < lines.size(); i++)

g2.draw((Line2D)lines.get(i));

}

public boolean isFocusTraversable() {

return true;

}

public void add(int dx, int dy) {

//last olan noktaya dx dy uzakliginda olan yeni noktayi hesapliyor

Point2D end = new Point2D.Double(last.getX() + dx, last.getY() + dy);

//son noktadan yeni noktaya kadar olan cizgi hazirlaniyor

Line2D line = new Line2D.Double(last, end);

//bu cizgi diger cizgilerin listesine kayit ediliyor

lines.add(line);

repaint();

125

last = end;

}

private class KeyHandler implements KeyListener {

public static final int LARGE_INCREMENT = 5;

public static final int SMALL_INCREMENT = 1;

public void keyPressed(KeyEvent e) {

int keyCode = e.getKeyCode();

//uzakligi ayarliyoruz

int d;

if(e.isShiftDown())

d = LARGE_INCREMENT;

else

d = SMALL_INCREMENT;

if(keyCode == KeyEvent.VK_RIGHT)

add(d, 0);

else if(keyCode == KeyEvent.VK_LEFT)

add(-d, 0);

else if(keyCode == KeyEvent.VK_UP)

add(0, -d);

else if(keyCode == KeyEvent.VK_DOWN)

add(0, d);

}

public void keyReleased(KeyEvent e) {

}

public void keyTyped(KeyEvent e) {

char keyChar = e.getKeyChar();

//uzakligi ayarliyoruz

int d;

if(Character.isUpperCase(keyChar)) {

d = this.LARGE_INCREMENT;

keyChar = Character.toLowerCase(keyChar);

}

else

d = this.SMALL_INCREMENT;

}

}

}

/*SketchFrame.java*/

import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

import java.awt.geom.*;

import java.util.*;

126

public class SketchFrame extends JFrame {

Container c;

public SketchFrame() {

c = this.getContentPane();

SketchPanel panel = new SketchPanel();

c.add(panel);

this.setTitle("Sketch");

this.setSize(400, 400);

this.setResizable(false);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.show();

}

public static void main(String[] args) {

new SketchFrame();

}

}

Yukarıdaki programın tam olarak incelenmesinden önce focus kavramını irdelemekte fayda var.

Focus Hakkında (isFocusTraversable metodu)

Normalde bilgisayar üzerinde mouse yardımıyla herhangi bir pencere ya da nesne seçilerek aktif hale getirilebilir.

Herhangi bir pencere aktif iken klavyeden girilen giris bilgileri dogrudan aktif olan nesneye gönderilmektedir.

Bir java programı çalısırken java’ya ait bir pencere aktif olacaktır. 1ste bu durumda klavyeden gönderilen bir giris

degeri dogrudan bir component üzerine gönderilecektir. Girisin gönderildigi bu nesneye focus denilir.

Bir pencere içerisinde en az bir nesne focus’tur.

Java penereleri içerisinde de focus lar belirli bir sırayala nesneden nesneye geçer. Ancak bazı nesneler hiçbir zaman

focus olmazlar. Paneller bu tip nesnelerdendir. 1ste prgramımızda override edilen isFocusTraversable metodu,

panelimizin focus olmasini saglar. Böylece klavye inputlari artik panele gönderilebilecektir.

MouseEvent’leri Ele Alma

Normalde mouse ile baska bir component tetiklenirse MouseEvent’i yakalamay gerek yoktur. Ancak çesitli paneller

ya da baska compoentler üzerinde mouse ile çizim v.b. isler yapılacaksa o zaman fare tarafından tetiklenen olaylar

ele alınabilir.

Kullanıcı bir fare tusuna bastıgı zaman 3 tane listener metodu tetiklenir:

-

 

mousePressed(MouseEvent e)

-

 

mouseReleased(MouseEvent e)

-

 

mouseClicked(MouseEvent e)

MouseEvent nesnesinin

 

getX ve getY metodları kullanılarak mouse göstericisinin tam olarak nereye bastıgı bilgisi

elde edilebilir. Ayırca tek tıklama ve çift tıklama arasındaki ayrım da getClickCount metodu yardımıyla elde edilebilir.

public void mouseClicked(MouseEvent e) {

int x = e.getX();

int y = e.getY();

if(e.isShiftDown && e.getClickCount() > 2) {

127

Graphics g = getGraphics();

g.drawString(“Selam”, x, y);

g.dispose();

}

}

Yukarıdaki örnekte mouse hareketlerinin dinlemenin yanı sıra graphics nesnesinin elde edilmesine iliskin bir

kullanım vardır. Burada Graphics nesnesini paintComponent metoduna gelen parametre ile elde etmek yerine

kendimiz yaratıyoruz. Bunun nedeni mouse ile panele tıkladıgımzıda paintCompnent nesnesinn çagrılmasını

beklemeden islemi hemen yapmak istememizdir. Bu sekilde kendimiz elde ettigimiz graphics nesneleerin dispose

metodu ile yeniden çizeriz. Ancak parametre ile gelen Graphics nesneleri repaint metodu ile çizilmelidir.

Simdi tüm mouse eventleri ele aln bir örnek yazalım..

/*MouseTracker.java*/

import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

public class MouseTracker extends JFrame implements MouseListener,

MouseMotionListener {

private JLabel statusBar;

public MouseTracker() {

super("Mouse olaylarini ele aliyoruz");

statusBar = new JLabel();

this.getContentPane().add(statusBar, BorderLayout.SOUTH);

this.addMouseListener(this);

this.addMouseMotionListener(this);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setSize(400, 400);

this.show();

}

public void mouseClicked(MouseEvent arg0) {

statusBar.setText("Clicked at [" + arg0.getX() + ", " + arg0.getY() +

"]");

}

public void mouseEntered(MouseEvent arg0) {

statusBar.setText("Mouse is in window");

}

public void mouseExited(MouseEvent arg0) {

statusBar.setText("Mouse is not in window");

}

public void mousePressed(MouseEvent arg0) {

statusBar.setText("Pressed at [" + arg0.getX() + ", " + arg0.getY() +

128

"]");

}

public void mouseReleased(MouseEvent arg0) {

statusBar.setText("Released at [" + arg0.getX() + ", " + arg0.getY() +

"]");

}

public void mouseDragged(MouseEvent arg0) {

statusBar.setText("Dragged at [" + arg0.getX() + ", " + arg0.getY() +

"]");

}

public void mouseMoved(MouseEvent arg0) {

statusBar.setText("Moved at [" + arg0.getX() + ", " + arg0.getY() + "]");

}

public static void main(String[] args) {

new MouseTracker();

}

}

ARASTIRMA ÖDEV: Yukarıdaki uygulamaya ek olarak bir de panele çizgi çizen bir pencere-mouse

uygulaması yazınız. Yani, kullanıcı mouse ile drag islemi yaptıkça ekranda çizgi belirsin.

pucu: üzeri çizilmek üzere bir panel yaratılsın. Bu panel MouseMotionAdapter ile dinlensin. Panelin

paint metodu currentX ve currentY denilen birtakım noktalar üzerinde fillOval metodunu çagırsın...

129

Ders 17

Geçen dersimizde GUI nin en önemli prensiplerinden birisi olan EventHandling mekanizmasını ögrenmistik.

Layout Mekanizması

Bu dersimizde GUI nesnelerini çerçeveler üzerinde yerlestirebilmemiz için gerekli olan ve daha önce sadece özet

seklinde inceledigimiz LayoutManagement mekanizmasını biraz daha detaylı bir sekilde inceleyecegiz.

Daha önce de söyledigimiz gibi Layout mekanizması GUI nesnelerinin çerçeve ya da panel üzerinde hangi sırayla ya

da hangi hiyerarsi ile yerlestirilecegine dair bilgi vermektedir.

BorderLayout

Daha önce de bildigimiz gibi temel bir layout mekanizması olan border layout nesneleri tasıyıcı nesneler üzerinde 5

ayrı parçada yerlestirebilmeyi saglar.

BorderLayout JFrame için öntanımlı olan layout dur

BorderLayout’da nesnelerin pozisyonları

Aslında ilk basta Center bölgesi bütün paneli kapsar. Çerçevenin boyutu degistikçe Center bölgesi de boyutunu

degistirir. Ancak kenar bölgeler boyutlarını degistirmezler. Kenar bölgelerin sınırı da üzerlerine nesne eklendikçe

degisir.

FlowLayout’dan farklı olarak, BorderLayout nesnelerin ilgili bölgenin tamamamını kapsamasına izin verir. Ancak

FlowLayout ilgili nesneleri onların “preferred size” degerlerinde yerlesmesini saglar.

Nesneler BorderLayout ile ayarlanmıs bir panel ya da çerçeve üzerine farklı bölgelere yerlestirilebilirler:

Container c = getContentPane();

c.add(nesne, BorderLayout.SOUTH);

GridLayout

GridLayout nesnelerin yerlesme düzenini satır ve sütünlar üzerinde ele alır.

Ancak GridLayout kullanıldıgı zaman her hücrenin kapladıgı alan hep aynı büyüklükte olacakıtır.

GridLayout ile panel düzeni set edilirken bölünmek istenen satır ve sütün sayısı parametre olarak belirtilir:

panel.setLayout(new GridLayout(3, 4));

3 satır ve 4sütunluk bir layout mekanizması..

Box Layout

130

Nesnelerin tek satır ya da tek sütun içerisinde yerlestirilmesini GridLayout’dan daha esnek bir sekilde ele alan bir

modeldir.

Öntanımlı layout modeli FlowLayout olan JPanel tasıyıcısı gibi, öntanımlı layout modeli BoxLayout olan “Box”

adında bir tasıyıcı sınıfı daha vardır.

Box Layout modeine sahip yeni bir Box tasıyıcı örnegi yaratmak için:

Box b = Box.createHorizontalBox();

Box b = Box.createVerticalBox();

b.add(okButton);

Horizontal box tasıyıcısı nesneleri soldan saga yerlestirir. Vertical Box nesnesi nesneleri yukarıdan asagıya

yerlestirir.

Her nesne 3 adet boyut degerine sahiptir:

prefferred size

maximum size

minimum size

Asagıda bir box layout modeline sahip horizontal Box tasıyıcısının çalısmasına iliskin detaylar sırasıyla

belirtilmektedir:

Box container;

- Önce en yüksek nesnenin maximum yüksekligini hesaplar.

- Daha sonra tüm nesneleri yatay olarak bu yükseklige uzatmayı dener.

- Eger bir nesne bu yükseklikte uzatılamıyorsa, o nesnenin y eksenideki konumu ele alınır. Bu islem

“getAlignmentY” metodu ile saglanır. (0 align to top, 1 align to bottom, 0.5 align to center). Bu metod bu float

degerlerden birtanesini geri döndürür. Böylece nesnenin y ekseni üzerindeki konumlandırılması tamamlanır.

- Her nesnenin “preferred width” degeri elde edilir ve toplanır.

- Eger toplam uzunluklar box uzunlugundan daha az ise, o zaman nesneler “maximum size” degerleri göz önüne

alınarak box uzunluguna genisletilir.Nesneler arasında hiç bosluk bırakılmaz. Eger nesnelerin toplam uzunlugu box

uzunlugundan daha fazla ise, o zaman minimum size degerleri kullanılır. Yine de sıgmazlar ise bazı nesneler

görünmeyecektir.

Vertical box tasıyıcısı için yukarıdaki islemler benzer sekilde çalısacaktır.

Öntnaımlı olarak BoxLayout modelinde nesneler arasında hiç bosluk bırakılmaz. 1stenilen oranda bosluk nırakmak

için bazı alan filtreleri kullanılır:

Struts

Rigid areas

Glue

Strut nesneler arasına bazı bosluklar ekler:

Box b = Box.cerateHorizontalBox();

b.add(label)

b.add(Box.createHorizontalStrut(10));

b.add(textField);

Rigid area filteri de Struts gibi bosluk bırakmak amacıyla kullanılır. Ancak bu filtre hem yatay hem de düzey alanda

tek seferde belirli oranda bosluk bırakmaya olanak verir. Mesela:

b.add(Box.createRigidArea(new Dimension(5, 20));

ifadesi, horizontal bir layout kullnırken nesneler arasında 5 pixel bosluk ve box yükeskligi ile 20 pixel bosluk yaratır.

131

Glue filtresi, nesneler arasına mümkün olan tüm boslugu ekler. Yani bir glue filtresi kullanılması durumunda box

üzerindeki tüm bos alan tüketilir.

b.add(button1);

b.add(Box.createGlue());

b.add(button2);

/*** BoxLayoutTest.java *****/

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class BoxLayoutTest {

public static void main(String arg[]) {

new BoxLayoutFrame();

}

}

class BoxLayoutFrame extends JFrame {

private final int WIDTH = 300, HEIGHT = 400;

public BoxLayoutFrame() {

setTitle("BoxLayoutTest");

setSize(WIDTH, HEIGHT);

JLabel label1 = new JLabel("Name: ");

JTextField textField1 = new JTextField(10);

textField1.setMaximumSize(textField1.getPreferredSize());

Box hbox1 = Box.createHorizontalBox();

hbox1.add(label1);

hbox1.add(Box.createHorizontalStrut(10));

hbox1.add(textField1);

JLabel label2 = new JLabel("Password: ");

JTextField textField2 = new JTextField(10);

textField2.setMaximumSize(textField2.getPreferredSize());

Box hbox2 = Box.createHorizontalBox();

hbox2.add(label2);

hbox2.add(Box.createHorizontalStrut(10));

hbox2.add(textField2);

JButton button1 = new JButton("Ok");

JButton button2 = new JButton("Cancel");

Box hbox3 = Box.createHorizontalBox();

hbox3.add(button1);

hbox3.add(Box.createHorizontalStrut(10));

hbox3.add(button2);

Box vbox = Box.createVerticalBox();

vbox.add(hbox1);

132

vbox.add(hbox2);

vbox.add(Box.createVerticalGlue());

vbox.add(hbox3);

this.getContentPane().add(vbox);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

show();

}

}

GridBagLayout

GridBag layout’u limitsiz bir Grid layout gibi düsünebiliriz. Diger layout modelleri içerisinde en karmasık ve en güçlü

olandır.

Bu modelde kolon ve satırlardaki hücrelerin boyutları degistirilebilmektedir.

Hücreler birbirleri ile birlestirilerek daha genis hücreler elde edilebilir.

GridBagLayout tasarımı ilk önce el yordamıyla kagıt kalem üzerinde yapılmalıdır. Tüm nesnelerin yerleri kaç satır ve

kaç sütun kaplayacakları belirlenir.

GridBagLayout kullanabilmek için öncelikle bir GridBagConstraints nesnesi tasarlanmalıdır. Bu nesne bir nesnenin

GridBagLayout hücrelerine nasıl yerlesecegini belirler.

gridx, gridy, gridwidth, gridheight

Bu özellikler (kısıtlar) bir nesnenin grid üzerinde nereye yerlesecegini belirler.

gridx ve gridy eklenecek olan nesnenin sol üst kısmının yer alacagı hücrenin kendisini belirler.

gridwidth ve gridheight, sol üst kösesi yerlestirilen bu nesnenin kaç tane satır ve kaç tane sütun yer kaplayacagını

belirler.

weightx, weighty

Bu degerler bir nesnenin yer aldıgı hücrenin boyutlarını degismesine iliskin özellikleri belirler.

weightx ve weighty degerlerinin 0’a set edilmesi, tasıyıcının boyutlarının degismesi durumunda ilgili nesnenin yer

aldıgı hücrenin x ya da y boyutlarının sabit kalmasına neden olur. Bu degerlerin 0 dısında set edilmesi panelin

133

yeniden boyutlandırılması durumunda ilgili hücredeki nesnenin de boyutlarının uzamasına nedenl olur. weight

degeri daha büyük olan nesne yeniden boyutlanma sırasında daha fazla yer kaplar.

Eger tüm nesneler için weight degerleri 0 yapılırsa, o zaman GUI boyutları degistikçe nesneler de GUI nin ortasında

yüzecektir.

fill, anchor

fill, bir nesnenin bulundugu alan içerisinde tüm alanı kapsamaması için gerekli ayarı set eder:

GridBagConstraints.NONE: alanı hiç doldurmaz

GridBagConstraints.VERTICAL: sadece dikeyde doldurur

GridBagConstraints.HORIZONTAL: sadece yatayda doldurur

GridBagConstraints.BOTH: tum alanı doldurur

anchor, eger nesne alanı doldurmuyorsa (hiçbiryerde doldurmuyorsa, dikeyde doldurmuyorsa ya da yatayda

doldurmuyorsa) bu bölgede nerede yer alacagını belirlemek için kullanılıır.

GridBagConstraints.NORTH: doldurmadıgı alanda kuzeye dayalı

GridBagConstraints.CENTER: doldurmadıgı alanda merkezde

GridBagConstraints.NORTHEAST: ...

GridBagConstraints.EAST: ...

...

GridBagLayout modelinin sagladıgı bu esnekligi kullanabilmek için aslında asagıdaki 4 temel adım uygulanmaktadır:

1) GridBagLayout türünde bir örnek yaratılır. Ancak hiç bir deger verimez. Sadece öntanımlı olarak bu nesne

yaratılır.

2) Tasıyıcı nesnenin layout modeli bu örnek türüne set edilir.

3) GridBagConstraints türünde bir örnek yaratıolır. Bu nesne aslında diger nesnelerin GridBag içerisinde nasıl

yerlesecegini belirleyecek özellikleri tutar ve set eder.

4) Eklencek olan her nesne için, istenilen GridBagConstraints özellikleri set edilir ve asagıdaki add metodu ile

nesneler tasıyıcı üzerine eklenir:

add(component, constraints);

import

 

 

javax.swing.*;

import

 

 

java.awt.*;

import

 

 

java.awt.event.*;

public class

 

 

GridBagDemo extends JFrame {

private

 

 

Container container;

private

 

 

GridBagLayout gbLayout;

private

 

 

GridBagConstraints gbConstraints;

public

 

 

GridBagDemo()

{

super

 

 

( "GridBagLayout" );

container

 

 

= getContentPane();

gbLayout

 

 

= new GridBagLayout();

container

 

 

.setLayout( gbLayout );

// instantiate gridbag constraints

gbConstraints

 

 

= new GridBagConstraints();

134

JTextArea ta =

 

new JTextArea( "TextArea1", 5, 10 );

JTextArea tx =

 

new JTextArea( "TextArea2", 2, 2 );

String names[] = {

 

"Iron", "Steel", "Brass" };

JComboBox cb =

 

new JComboBox( names );

JTextField tf =

 

new JTextField( "TextField" );

JButton b1 =

 

new JButton( "Button 1" );

JButton b2 =

 

new JButton( "Button 2" );

JButton b3 =

 

new JButton( "Button 3" );

// text area

// weightx and weighty are both 0: the default

// anchor for all components is CENTER: the default

gbConstraints

 

 

.fill = GridBagConstraints.BOTH;

//gbConstraints.fill = GridBagConstraints.HORIZONTAL;

addComponent( ta, 0, 0, 1, 3 );

// button b1

// weightx and weighty are both 0: the default

gbConstraints

 

 

.fill = GridBagConstraints.HORIZONTAL;

addComponent( b1, 0, 1, 2, 1 );

// combo box

// weightx and weighty are both 0: the default

// fill is HORIZONTAL

addComponent( cb, 2, 1, 2, 1 );

// button b2

gbConstraints

 

 

.weightx = 1000; // can grow wider

gbConstraints

 

 

.weighty = 1; // can grow taller

gbConstraints

 

 

.fill = GridBagConstraints.BOTH;

addComponent( b2, 1, 1, 1, 1 );

// button b3

// fill is BOTH

gbConstraints

 

 

.weightx = 0;

gbConstraints

 

 

.weighty = 0;

addComponent( b3, 1, 2, 1, 1 );

// textfield

// weightx and weighty are both 0: fill is BOTH

addComponent( tf, 3, 0, 2, 1 );

// textarea

// weightx and weighty are both 0: fill is BOTH

addComponent( tx, 3, 2, 1, 1 );

setSize( 300, 150 );

show();

}

// addComponent is programmer defined

private void

 

 

addComponent( Component c,

int

 

 

row, int column, int width, int height )

{

// set gridx and gridy

gbConstraints

 

 

.gridx = column;

gbConstraints

 

 

.gridy = row;

// set gridwidth and gridheight

gbConstraints

 

 

.gridwidth = width;

gbConstraints

 

 

.gridheight = height;

135

// set constraints

gbLayout

 

 

.setConstraints( c, gbConstraints );

container

 

 

.add( c ); // add component

}

public static void

 

 

main( String args[] )

{

GridBagDemo app =

 

new GridBagDemo();

app.addWindowListener(

new

 

 

WindowAdapter() {

public void

 

 

windowClosing( WindowEvent e )

{

System.exit( 0 );

}

}

);

}

}

/*** FontDialog.java ***/

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class FontDialog {

public static void main(String[] args) {

new FontDialogFrame();

}

}

class FontDialogFrame extends JFrame {

JComboBox face, size;

JCheckBox bold, italic;

JTextArea sample;

public FontDialogFrame() {

setTitle("Font Dalog");

setSize(400, 400);

/*Contaner ve Layout yaratiliyor*/

Container c = this.getContentPane();

GridBagLayout gbl = new GridBagLayout();

c.setLayout(gbl);

ActionListener listener = new FontAction();

JLabel faceLabel = new JLabel("Face: ");

136

face = new JComboBox(new String[] {"Serif", "SansSerif", "Monospaced",

"Dialog", "DialogInput"});

face.addActionListener(listener);

JLabel sizeLabel = new JLabel("Size: ");

size = new JComboBox(new String[] {"8", "10", "12", "15", "18", "24"} );

size.addActionListener(listener);

bold = new JCheckBox("Bold");

bold.addActionListener(listener);

italic = new JCheckBox("Italic");

italic.addActionListener(listener);

sample = new JTextArea();

sample.setText("Bugun, bundan sonraki gunlerinin ilk gunudur");

sample.setEditable(false);

sample.setLineWrap(true); //satir bitince alt satira gecis

sample.setBorder(BorderFactory.createEtchedBorder());

/*Grid tanimlamalarimini hazirliyoruz*/

GridBagConstraints constraints = new GridBagConstraints();

constraints.fill = GridBagConstraints.NONE;

constraints.anchor = GridBagConstraints.EAST;

constraints.weightx = 0;

constraints.weighty = 0;

add(faceLabel, constraints, 0, 0, 1, 1);

add(sizeLabel, constraints, 0, 1, 1, 1);

constraints.fill = GridBagConstraints.HORIZONTAL;

constraints.weightx = 100;

add(face, constraints, 1, 0, 1, 1);

add(size, constraints, 1, 1, 1, 1);

constraints.weighty = 100;

constraints.fill = GridBagConstraints.NONE;

constraints.anchor = GridBagConstraints.CENTER;

add(bold, constraints, 0, 2, 2, 1);

add(italic, constraints, 0, 3, 2, 1);

constraints.fill = GridBagConstraints.BOTH;

add(sample, constraints, 2, 0, 1, 4);

show();

}

public void add(Component c, GridBagConstraints constraints, int x, int y, int

w, int h) {

constraints.gridx = x;

constraints.gridy = y;

constraints.gridwidth = w;

constraints.gridheight = h;

getContentPane().add(c, constraints);

}

137

private class FontAction implements ActionListener {

public void actionPerformed(ActionEvent e) {

String fontFace = (String)face.getSelectedItem();

int fontStyle = (bold.isSelected() ? Font.BOLD : 0) +

(italic.isSelected() ? Font.ITALIC : 0);

int fontSize = Integer.parseInt( (String)size.getSelectedItem() );

sample.setFont(new Font(fontFace, fontStyle, fontSize));

sample.repaint();

}

}

}

Swing Nesneleri Üzerinde Bir Tur

Model-view-controller (MVC) yapısı swing nesnelerinin tasarlanmasında ve kullanılmasında dikkat edilen 3 temel

yaklasımı temsil eder.

Model: sadece nesnenin içerigidir. Yani gorsel açıdan hiçbirsey ifade etmez. Model içerik hakkında bilgiyi alan ve

içerigi degistirne metodların tasarımıdır.

View: Bir nesnenin ekrandaki goruntusunu temsil eder.

Controller: Kullanıcı girislerini ele alır.

JButton

Bir dugmeye basıldıgı zaman ActionEvent yaratılır. Bu ActionEven uzerinden kullanılabilecek metodlar:

getActionCommand()

getMnemonic() : dugme uzerine fare imleci ile geldiginiziden ekranda beliren ipucu kutucugu

isArmed(): Eger dugmeye basildiysa ve mouse hala uzerindeyse true

isEnabled(): eger dugme secilebilir nitelikte ise true

isPressed(): Eger dugmeye basildiysa ve mouse hala release edilmediyse true

isRollover(): Eger mouse hala uzerindeyse true

isSelected() : Eger dugme tek tıklama gbi bir hareketle secildiyse

JTextFields

Text girislerini elde alamak amacıyla kullanılır.

void setText(String t)

String getText()

void setEditable(boolean b)

setFont(new Font(…)): alan icerisindeki font degerini degistirmek icin kulanılabilir.

JTextField(String str, int colsize)

138

Text field icerisindeki degisiklikler

Text field icerisindeki her degisikligi control etmek icin biraz efor harcamak gerekir. Bu islem icin key listener

dinlemek pek mantıklı olmayabilir. Cunku bazı tuslar zaten bir tex girisi yapmazlar (ok tuslari gibi) Ayrıca text

girisleri fare ile de yapılabilir.

Butun text nesneleri icin “model”, Document denilen bir arayüz tarafından ifade edilir. Kontrol edilmek istenen text

nesnesi icin bir document listener yuklenerek- nesne uzerindeki her degisiklik elde edilebilir:

textField.getDocument().addDocumentListener(listener);

//text nesnesni temsil eden document nesnesi elde edilerek bir document listener nesnesine kaydediliyor.

Bu durumda Text nesnesinde meydana gelen her degisiklikjte asagidaki metodlardan birisi tetiklenir,

void insertUpdate(DocumentEvent e)

void removeUpdate(DocumentEvent e)

void changeUpdate(DocumentEvent e)

3 metod her text nesnesi icin cagrilmaz (style- size v.b. degisiklikler.) Ancak ilk iki metod text alanına yapılan bir

giris ya da slime isleminde tetiklenir:

Kontrollu klavye girisine iliskin bir ornek

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

import javax.swing.event.*;

public class TextTest extends JFrame implements ActionListener, KeyListener {

Container c;

JButton dugme;

JTextField text;

public TextTest() {

c = getContentPane();

c.setLayout(new FlowLayout());

dugme = new JButton("Gonder");

dugme.setToolTipText("int bilgiyi gonderir");

dugme.addActionListener(this);

dugme.setBackground(Color.BLUE);

dugme.setForeground(Color.WHITE);

c.add(dugme);

text = new JTextField("0", 10);

text.addKeyListener(this);

c.add(text);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setSize(240, 120);

setResizable(false);

show();

}

139

public void actionPerformed(ActionEvent e) {

int strInt = strInt = Integer.parseInt(text.getText());

if(strInt == 42)

System.exit(0);

else

JOptionPane.showMessageDialog(this, ""+strInt);

}

public void keyPressed(KeyEvent e) {

int k = e.getKeyCode();

if(k != KeyEvent.VK_0 && k != KeyEvent.VK_1 && k != KeyEvent.VK_2 &&

k != KeyEvent.VK_3 && k != KeyEvent.VK_4 && k != KeyEvent.VK_5 &&

k != KeyEvent.VK_6 && k != KeyEvent.VK_7 && k != KeyEvent.VK_8 &&

k != KeyEvent.VK_9 && k != KeyEvent.VK_BACK_SPACE) {

JOptionPane.showMessageDialog(this, "rakam giriniz..");

String str = text.getText();

str = str.substring(0, str.length()-1);

text.setText(str);

text.validate();

}

c.repaint();

}

public void keyReleased(KeyEvent e) {}

public void keyTyped(KeyEvent e) {}

public static void main(String arg[]) {

new TextTest();

}

}

JPasswordField

Password alanları text girileri gibidir. Ancak kullanıcı tarafından girilen bilgi

ekranda * tuslari ile gorunur.

JPasswordField(String str, int colsize)

void setEchoChar(char echo): gizleyici karakter sembolu

char [] getPassword(): password alanı icerisinde saklanan password bilgisini geri

gonderir.

Ancak bu bilgi String olarak gonderilmez. Bunun nedeni Stringler garbage collector

devreye girene kadar hazfızadan silinmezler.

JTextArea

Bazen kullanıcıdan alınacak olan bilgi textfield gibi kucuk alanlarda degil daha buyuk alanlarda saklanma istenebilir.

JTextArea(line, column)

140

void setLineWrap(boolean b):

 

Text alanının kolon uzunlugundan daha uzun satirlar bolunur. Ancak bu bolme

islemi sanaldir. Yani orjinal text icerisine “\n” eklenmez. Ancak kullanıcı kendisi Enter tusuna basarsa bu bilgi orjinal

tex icerisine eklenir.

Java da bir TextArea nın kendisine ait scroll bar’ı yoktur. Bu nedenle gerektiginde kullanıcı kendisi TextArea

nesnesini bir ScrollBar icerisine eklemelidir.

JScrollPane scroll = new JScrollPane(new JTextArea(8, 40));

contentPane.add(scroll, BorderLayout.CENTER);

Gereginden fazla text girisi yapildiginda scroll bar otomatik olarak belirecektir.

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class TextAreaTest

{

public static void main(String[] args)

{

TextAreaFrame frame = new TextAreaFrame();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.show();

}

}

/**

A frame with a text area and buttons for text editing

*/

class TextAreaFrame extends JFrame

{

public TextAreaFrame()

{

setTitle("TextAreaTest");

setSize(WIDTH, HEIGHT);

Container contentPane = getContentPane();

buttonPanel = new JPanel();

// add button to append text into the text area

JButton insertButton = new JButton("Insert");

buttonPanel.add(insertButton);

insertButton.addActionListener(new

ActionListener()

{

public void actionPerformed(ActionEvent event)

{

textArea.append("The quick brown fox "

+ "jumps over the lazy dog. ");

}

});

// add button to turn line wrapping on and off

wrapButton = new JButton("Wrap");

buttonPanel.add(wrapButton);

wrapButton.addActionListener(new

ActionListener()

141

{

public void actionPerformed(ActionEvent evt)

{

boolean wrap = !textArea.getLineWrap();

textArea.setLineWrap(wrap);

scrollPane.validate();

wrapButton.setText(wrap ? "No Wrap" : "Wrap");

}

});

contentPane.add(buttonPanel, BorderLayout.SOUTH);

// add a text area with scroll bars

textArea = new JTextArea(8, 40);

scrollPane = new JScrollPane(textArea);

contentPane.add(scrollPane, BorderLayout.CENTER);

}

public static final int WIDTH = 300;

public static final int HEIGHT = 300;

private JTextArea textArea;

private JScrollPane scrollPane;

private JPanel buttonPanel;

private JButton wrapButton;

}

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class TextEditTest

{

public static void main(String[] args)

{

TextEditFrame frame = new TextEditFrame();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.show();

}

}

/**

A frame with a text area and components for search/replace.

*/

class TextEditFrame extends JFrame

{

public TextEditFrame()

{

setTitle("TextEditTest");

setSize(WIDTH, HEIGHT);

Container contentPane = getContentPane();

JPanel panel = new JPanel();

// add button, text fields and labels

JButton replaceButton = new JButton("Replace");

panel.add(replaceButton);

replaceButton.addActionListener(new ReplaceAction());

142

from = new JTextField("brown", ;

panel.add(from);

panel.add(new JLabel("with"));

to = new JTextField("purple", ;

panel.add(to);

contentPane.add(panel, BorderLayout.SOUTH);

// add text area with scroll bars

textArea = new JTextArea(8, 40);

textArea.setText

("The quick brown fox jumps over the lazy dog.");

JScrollPane scrollPane = new JScrollPane(textArea);

contentPane.add(scrollPane, BorderLayout.CENTER);

}

public static final int WIDTH = 400;

public static final int HEIGHT = 200;

private JTextArea textArea;

private JTextField from;

private JTextField to;

/**

The action listener for the replace button.

*/

private class ReplaceAction implements ActionListener

{

public void actionPerformed(ActionEvent event)

{

String f = from.getText();

int n = textArea.getText().indexOf(f);

if (n >= 0 && f.length() > 0)

textArea.replaceRange(to.getText(), n,

n + f.length());

}

}

}

Etiketler ve Nesnelerin Etiketlendirilmesi

JLabel(String str, int alignment)

SwingConstants.LEFT, RIGHT, CENTER, NORTH, EAST

setText

setIcon(Icon a)

JCheckBox

Kullanıcıdan sadece “evet” ya da “hayir” girislerini almak icin check box kullanılabilir. Bu nesneler yaratılırken label

ile birlikte yaratılırlar.

JCheckBox(String str)

void setSelected(Boolean b)

boolean isSelected()

143

JRadioButton

Bu nesneler de check box lar gibi olumlu ya da olumsuz bir seçimi ifade ederler.

JRadioButton(String label, boolean selection)

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class ButtonsTest extends JFrame implements ActionListener {

Container c;

JLabel l;

JRadioButton r1, r2;

JPanel bp, lp;

JCheckBox c1, c2;

ButtonGroup group;

Font f;

int boldvalue = 0, italicvalue = 0, size = 24;

public ButtonsTest() {

c = getContentPane();

l = new JLabel("Hakan Gozutok");

f = new Font("Serif", boldvalue + italicvalue, size);

l.setFont(f);

r1 = new JRadioButton("Blue");

r1.addActionListener(this);

r2 = new JRadioButton("Red");

r2.addActionListener(this);

group = new ButtonGroup();

group.add(r1);

group.add(r2);

c1 = new JCheckBox("Bold");

c1.addActionListener(this);

c2 = new JCheckBox("Italic");

c2.addActionListener(this);

bp = new JPanel();

bp.add(r1);

bp.add(r2);

bp.add(c1);

bp.add(c2);

/*label icin hazirlanan panel*/

lp = new JPanel();

lp.add(l);

c.add(lp, BorderLayout.CENTER);

c.add(bp, BorderLayout.SOUTH);

144

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setSize(300, 400);

show();

}

public void actionPerformed(ActionEvent e) {

if(e.getSource() == r1)

l.setForeground(Color.BLUE);

else if(e.getSource() == r2)

l.setForeground(Color.RED);

if(e.getSource() == c1 || e.getSource() == c2) {

boldvalue = c1.isSelected() ? Font.BOLD : 0;

italicvalue = c2.isSelected() ? Font.ITALIC : 0;

f = new Font("Serif", boldvalue + italicvalue, size);

l.setFont(f);

}

l.validate();

c.repaint();

}

public static void main(String[] args) {

new ButtonsTest();

}

}

JComboBox

Birden fazla seçim yapmak gereken durumlarda Combox nesnelerinin kullanmak iyi bir

çözüm olabilir.

faceCombo = new JComboBox();

faceCombo.setEditable(true);

faceCombo.addItem(“Serif”);

faceCombo.addItem(“SansSerif”);

Object getSelectedItem()

JComboBox(String []str)

void removeItemAt(int index)

void removeItem(String item)

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class ButtonsTest extends JFrame implements ActionListener {

Container c;

JLabel l;

JRadioButton r1, r2;

JPanel bp, lp;

JCheckBox c1, c2;

ButtonGroup group;

Font f;

145

int boldvalue = 0, italicvalue = 0, size = 24;

JComboBox sizecombo;

public ButtonsTest() {

c = getContentPane();

l = new JLabel("Hakan Gozutok");

f = new Font("Serif", 0, 24);

l.setFont(f);

r1 = new JRadioButton("Blue");

r1.addActionListener(this);

r2 = new JRadioButton("Red");

r2.addActionListener(this);

group = new ButtonGroup();

group.add(r1);

group.add(r2);

c1 = new JCheckBox("Bold");

c1.addActionListener(this);

c2 = new JCheckBox("Italic");

c2.addActionListener(this);

sizecombo = new JComboBox(new String [] {"8", "12", "24", "48"});

sizecombo.setSelectedItem("24");

sizecombo.setEditable(true);

sizecombo.addActionListener(this);

bp = new JPanel();

bp.add(r1);

bp.add(r2);

bp.add(c1);

bp.add(c2);

bp.add(sizecombo);

/*label icin hazirlanan panel*/

lp = new JPanel();

lp.add(l);

c.add(lp, BorderLayout.CENTER);

c.add(bp, BorderLayout.SOUTH);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setSize(600, 400);

show();

}

public void actionPerformed(ActionEvent e) {

if(e.getSource() == r1)

l.setForeground(Color.BLUE);

else if(e.getSource() == r2)

l.setForeground(Color.RED);

if(e.getSource() == c1 || e.getSource() == c2) {

boldvalue = c1.isSelected() ? Font.BOLD : 0;

italicvalue = c2.isSelected() ? Font.ITALIC : 0;

l.setFont(new Font("Serif", boldvalue + italicvalue, size));

146

}

if(e.getSource() == sizecombo) {

m("combo");

size = Integer.parseInt(sizecombo.getSelectedItem().toString());

l.setFont(new Font("Serif", boldvalue + italicvalue, size));

}

l.validate();

c.repaint();

}

public void m(String str) {

JOptionPane.showMessageDialog(null, str);

}

public static void main(String[] args) {

new ButtonsTest();

}

}

JSlider

Bu nesneler birtakım devam eden sürekli secimler uzerinde kullanıcının secim yapmasını saglayan nesnelerdir.

Kullanıcı bu secim rastgele degil sırayla yapabilir. (Biliyoruz ki combo box lar kullanılırken secim rastgle yapılıyordu)

En genell sekliyle bir JSlider nesnesi asagidaki gibi yaratılır:

new JSlider(min, max, initialValue)

Eger yatay degil de dikey bir JSlider yaratılmak istenirse:

JSlider sl = new JSlider(SwingConstants.VERTICAL, min, max, initialValue)

Ancak bu slider yaratma yöntemleri sadece düz bir slider yaratır. Slider’ların bir dekorasyon ile de yaratılabilecegini

belirtmek gerekir:

ChangeListener

Slider hareket ettigi zaman ChangeEvent yaratılır. Bu nedenle Slider’ların dinlenmesi için onları ChangeListener

nesnesine eklemek gerekir.

Bir ChangeListener arayüzü içerisinde:

stateChanged(ChangeEvent e)

metodu yer alır.

Bir Slider dekoratif olarak da yaratılabilir. Bunun için:

slider.setMajorTickSpacing(20)

slider.setMinorTickSpacing(5);

slider.setPaintTicks(true): Bu dekorların gorunur olmasını saglar.

slider.setPaintLabels(true)

147

metoldarından yararlanılır.

slider.setPaintLabels(true): Major tick space’ leri gorunur kılar

Slider boyutlandirmasi için:

sl.setPreferredSize(new Dimension(550, 50));

sl.setMinimumSize(new Dimension(550, 50));

sl.setMaximumSize(new Dimension(550, 50));

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

import javax.swing.event.*;

public class ButtonsTest extends JFrame implements ActionListener, ChangeListener {

Container c;

JLabel l;

JRadioButton r1, r2;

JPanel bp, lp;

JCheckBox c1, c2;

ButtonGroup group;

Font f;

int boldvalue = 0, italicvalue = 0, size = 24;

JComboBox sizecombo;

JSlider sl;

JPanel np;

public ButtonsTest() {

c = getContentPane();

l = new JLabel("Hakan Gozutok");

f = new Font("Serif", 0, 24);

l.setFont(f);

r1 = new JRadioButton("Blue");

r1.addActionListener(this);

r2 = new JRadioButton("Red");

r2.addActionListener(this);

group = new ButtonGroup();

group.add(r1);

group.add(r2);

c1 = new JCheckBox("Bold");

c1.addActionListener(this);

c2 = new JCheckBox("Italic");

c2.addActionListener(this);

sizecombo = new JComboBox(new String [] {"8", "12", "24", "48"});

sizecombo.setSelectedItem("24");

sizecombo.setEditable(true);

sizecombo.addActionListener(this);

sl = new JSlider(0, 100, 24);

sl.setMajorTickSpacing(5);

sl.setMinorTickSpacing(10);

sl.setPaintTicks(true);

148

sl.setPaintLabels(true);

sl.addChangeListener(this);

bp = new JPanel();

bp.add(r1);

bp.add(r2);

bp.add(c1);

bp.add(c2);

bp.add(sizecombo);

/*label icin hazirlanan panel*/

lp = new JPanel();

lp.add(l);

np = new JPanel();

np.add(sl);

c.add(lp, BorderLayout.CENTER);

c.add(bp, BorderLayout.SOUTH);

c.add(np, BorderLayout.NORTH);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setSize(600, 400);

show();

}

public void actionPerformed(ActionEvent e) {

if(e.getSource() == r1)

l.setForeground(Color.BLUE);

else if(e.getSource() == r2)

l.setForeground(Color.RED);

if(e.getSource() == c1 || e.getSource() == c2) {

boldvalue = c1.isSelected() ? Font.BOLD : 0;

italicvalue = c2.isSelected() ? Font.ITALIC : 0;

l.setFont(new Font("Serif", boldvalue + italicvalue, size));

}

if(e.getSource() == sizecombo) {

m("combo");

size = Integer.parseInt(sizecombo.getSelectedItem().toString());

l.setFont(new Font("Serif", boldvalue + italicvalue, size));

}

l.validate();

c.repaint();

}

public void m(String str) {

JOptionPane.showMessageDialog(null, str);

}

public static void main(String[] args) {

149

new ButtonsTest();

}

public void stateChanged(ChangeEvent e) {

l.setFont(new Font("Serif", boldvalue + italicvalue, sl.getValue()));

}

}

Ayrıca slider uzerindeki bu bilgileri String ya da icon etiketler seklinde de ifade etmek

mumkundur. Bunun icin:

setLabelTable(HashTable ltable)

metodunu kullanırız. Asagida buna iliskin orek kodlar yer alır.

HashTable labelTable = new HashTable();

labelTable.put(new Integer(0), new JLabel(“A”));

labelTable.put(new Integer(20), new JLabel(“B”));

….

labelTable.put(new Integer(100), new JLabel(“F”));

slider.setLabelTable(labelTable);

import java.awt.*;

import java.awt.event.*;

import java.util.*;

import javax.swing.*;

import javax.swing.event.*;

public class SliderTest

{

public static void main(String[] args)

{

SliderTestFrame frame = new SliderTestFrame();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.show();

}

}

/**

A frame with many sliders and a text field to show slider

values.

*/

class SliderTestFrame extends JFrame

{

public SliderTestFrame()

{

setTitle("SliderTest");

setSize(WIDTH, HEIGHT);

sliderPanel = new JPanel();

sliderPanel.setLayout(new FlowLayout(FlowLayout.LEFT));

// common listener for all sliders

listener = new

ChangeListener()

{

public void stateChanged(ChangeEvent event)

{

150

// update text field when the slider value changes

JSlider source = (JSlider)event.getSource();

textField.setText("" + source.getValue());

}

};

// add a plain slider

JSlider slider = new JSlider();

addSlider(slider, "Plain");

// add a slider with major and minor ticks

slider = new JSlider();

slider.setPaintTicks(true);

slider.setMajorTickSpacing(20);

slider.setMinorTickSpacing(5);

addSlider(slider, "Ticks");

// add a slider that snaps to ticks

slider = new JSlider();

slider.setPaintTicks(true);

slider.setSnapToTicks(true);

slider.setMajorTickSpacing(20);

slider.setMinorTickSpacing(5);

addSlider(slider, "Snap to ticks");

// add a filled slider

slider = new JSlider();

slider.setPaintTicks(true);

slider.setMajorTickSpacing(20);

slider.setMinorTickSpacing(5);

slider.putClientProperty("JSlider.isFilled",

Boolean.TRUE);

addSlider(slider, "Filled");

// add a filled and inverted slider

slider = new JSlider();

slider.setPaintTicks(true);

slider.setMajorTickSpacing(20);

slider.setMinorTickSpacing(5);

slider.putClientProperty("JSlider.isFilled",

Boolean.TRUE);

slider.setInverted(true);

addSlider(slider, "Inverted");

// add a slider with numeric labels

slider = new JSlider();

slider.setPaintTicks(true);

slider.setPaintLabels(true);

slider.setMajorTickSpacing(20);

slider.setMinorTickSpacing(5);

addSlider(slider, "Labels");

// add a slider with alphabetic labels

slider = new JSlider();

slider.setPaintLabels(true);

slider.setPaintTicks(true);

151

slider.setMajorTickSpacing(20);

slider.setMinorTickSpacing(5);

Hashtable labelTable = new Hashtable();

labelTable.put(new Integer(0), new JLabel("A"));

labelTable.put(new Integer(20), new JLabel("B"));

labelTable.put(new Integer(40), new JLabel("C"));

labelTable.put(new Integer(60), new JLabel("D"));

labelTable.put(new Integer(80), new JLabel("E"));

labelTable.put(new Integer(100), new JLabel("F"));

slider.setLabelTable(labelTable);

addSlider(slider, "Custom labels");

// add a slider with icon labels

slider = new JSlider();

slider.setPaintTicks(true);

slider.setPaintLabels(true);

slider.setSnapToTicks(true);

slider.setMajorTickSpacing(20);

slider.setMinorTickSpacing(20);

labelTable = new Hashtable();

// add card images

labelTable.put(new Integer(0),

new JLabel(new ImageIcon("nine.gif")));

labelTable.put(new Integer(20),

new JLabel(new ImageIcon("ten.gif")));

labelTable.put(new Integer(40),

new JLabel(new ImageIcon("jack.gif")));

labelTable.put(new Integer(60),

new JLabel(new ImageIcon("queen.gif")));

labelTable.put(new Integer(80),

new JLabel(new ImageIcon("king.gif")));

labelTable.put(new Integer(100),

new JLabel(new ImageIcon("ace.gif")));

slider.setLabelTable(labelTable);

addSlider(slider, "Icon labels");

// add the text field that displays the slider value

textField = new JTextField();

Container contentPane = getContentPane();

contentPane.add(sliderPanel, BorderLayout.CENTER);

contentPane.add(textField, BorderLayout.SOUTH);

}

/**

Adds a slider to the slider panel and hooks up the listener

@param s the slider

@param description the slider description

*/

public void addSlider(JSlider s, String description)

{

s.addChangeListener(listener);

JPanel panel = new JPanel();

panel.add(s);

panel.add(new JLabel(description));

sliderPanel.add(panel);

152

}

public static final int WIDTH = 350;

public static final int HEIGHT = 450;

private JPanel sliderPanel;

private JTextField textField;

private ChangeListener listener;

}

153

Ders 19

Menuler

Menuler bir GUI uygulamasının en vazgecilmez parcalarından birisidir. Bir menu cubugu uzerinde birtakım menu

nesneleri ve alt menuler yer almaktadır. Bu kısımdan menuleri nasıl ele alacagımızı görecegiz.

JMenuBar menuBar = new JMenuBar();

Yukarıda yaratılan bu menu bar istedigimiz yere ekleyebilecegimiz bir nesnedir.

Genelde bir menu, bir JFrame nesnesinin ust kısmına yerlestirilir. Bu islem asagfidaki gibi yapilabilir:

frame.setJMenuBar(menuBar);

menubar icerisine bir takım menuler eklenebilir

JMenu editMenu = new JMenu(“Edit”);

menuBar.addMenu(editMenu);

Her menu icerisinde menu nesneleri vardır.

JMenuItem pasteItem = new JMenuItem(“Paste”);

JMenuItem cutItem = new JMenuItem(“Cut”);

(JMenuItem iconedItem = new JMenuItem(“Iconed”, icon);

editMenu.add(pasteItem);

editMenu.add(cutItem);

Menu nesneleri arasına ayırac da eklenebilir:

JMenu optionMenu = new JMenu(“Select”);

editMenu.addSperator();

editMenu.add(optionsMenu)

Bir menu ya da menu nesnesi secildiginde ActionEvent nesnesi yaratılır. Bu nedenle daha once de ogrendigimiz

sekilde menu nesnelerini ActionListener nesnelerine kaydetmek mumkundur.

MenuItem’lar JCheckBoxMenuItem ya da JRadioButtonMenuItem nesnelerinden de olabilirler.

Popup Menuleri

Popup menu de tıpkı JMenu nesnesi gibi bir menudur. Ancak tek farkı herhangi bir yerde sabit bir sekilde

yerlesmezler.

JPopupMenu popup = new JPopupMenu();

JMenuItem item = new JMenuItem(“Cut”);

item.addActionListener(listener);

popup.add(item);

Bir popup menusunu her seferinde açıkça gostermek gerekir. Bunun için

popup.show(panel, x, y)

metodu kullanılır. panel nesnesi popup menusunu “parent” olan nesnesini temsil eder. X ve y de menunun

gpsterilecegi lokasyon bilgisini belirtir.

Bir popup menusu asagidaki sekilde ele alınabilir:

154

1. bir mouse listener yuklenir.

2. public void mouseReleased(MouseEvent e) {

if(e.isPopupTrigger())

popup.show(e.getComponent(), e.getX(), e.getY());

}

Menulerde Tus Kombinasyonları

Menuler kullanılırken fareye ihtiyaç duymadan bazı klavye tus kombinasyonları yardımıyla menu nesnelerine

ulasılabilir. Java’da bu iselm bir menu nesnesi yaratılırken ayarlanabilir:

JMenuItem cutItem = new JMenuItem(“Cut”, ‘T’);

Bunun yerine bir menu nesnesine sonradan tus kombinasyonu atamak da mümkündür:

cutItem.setMnemonic(‘T’);

NOT:

 

 

Bu tus kombinasyonları sadece MenuItem constructor içerisinde tanımlanır. Eger menu baslangıç metodu

içerisinde de bir tanımlama yapmak istiyorsak o zaman setMnemonic metodu ile sonradan bunu belirtmek gerekir.

Hızlandırıcılar: Dogrudan Alt Menulere Erisim

Menulere tanımlanan bu tus kombinadyonlarınn yanı sıra hızlandırıcılar denilen ve dogrudan alt menu elemanlarına

erisimi saglayan ayarlar da vardır. Çünkü sadece bu mnemonic tanımlamaları ile belirlenen menu elemanlarına

erismek için öncelikle ara menunun açılması gerekir. Ancak hızlandırıcılar ara menu açmaya gereksinim duymaksızın

alt menu nesnelerine de erisimi saglar.

Örnegin bir çok programda tanımlı olan Ctrl+O ve Ctrl+S hızlandırıcılar, dogrudan alt menu olan Save ve Open

seçeneklerine erismeyi saglar.

Bunun için örnegin:

openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));

import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Container;

import java.awt.Dimension;

import java.awt.FlowLayout;

import java.awt.Font;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.InputEvent;

import java.awt.event.KeyEvent;

import javax.swing.ButtonGroup;

import javax.swing.JButton;

import javax.swing.JCheckBoxMenuItem;

import javax.swing.JComboBox;

import javax.swing.JFrame;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.JPanel;

import javax.swing.JRadioButton;

import javax.swing.JTextArea;

import javax.swing.KeyStroke;

public class JPanelOrnek1 extends JFrame implements ActionListener {

JPanel colorPanel, sizePanel, editPanel, southPanel;

JTextArea text;

155

JButton yellowButton, redButton, blueButton;

JRadioButton editable, noneditable;

ButtonGroup group;

Container c;

JMenu fontMenu;

JMenu fontStyleMenu;

JCheckBoxMenuItem boldItem, italicItem;

JMenuBar menuBar, menuBar2;

JComboBox comboMenu;

int boldValue = 0, italicValue = 0;

String face = "Serif";

int size = 24;

public JPanelOrnek1() {

c = this.getContentPane();

c.setLayout(new BorderLayout());

southPanel = new JPanel();

southPanel.setLayout(new BorderLayout());

colorPanel = new JPanel(new FlowLayout());

yellowButton = new JButton("Sari");

yellowButton.addActionListener(this);

colorPanel.add(yellowButton);

redButton = new JButton("Kirmizi");

redButton.addActionListener(this);

colorPanel.add(redButton);

blueButton = new JButton("Mavi");

blueButton.addActionListener(this);

colorPanel.add(blueButton);

yellowButton.setBackground(Color.BLACK);

yellowButton.setForeground(Color.WHITE);

redButton.setBackground(Color.BLACK);

redButton.setForeground(Color.WHITE);

blueButton.setBackground(Color.BLACK);

blueButton.setForeground(Color.WHITE);

southPanel.add(colorPanel, BorderLayout.SOUTH);

editPanel = new JPanel(new FlowLayout());

group = new ButtonGroup();

editable = new JRadioButton("Duzenlenebilir", false);

group.add(editable);

editable.addActionListener(this);

editPanel.add(editable);

noneditable = new JRadioButton("Duzenlenemez", true);

group.add(noneditable);

noneditable.addActionListener(this);

editPanel.add(noneditable);

southPanel.add(editPanel, BorderLayout.NORTH);

text = new JTextArea();

text.setText("Deneme Yazisi");

text.setEditable(true);

c.add(text, BorderLayout.CENTER);

c.add(southPanel, BorderLayout.SOUTH);

156

menuBar = new JMenuBar();

fontMenu = new JMenu("Font");

fontMenu.setToolTipText("Fontlarla ilgili ayarlari yapabilirsiniz");

fontMenu.setMnemonic('F');

fontStyleMenu = new JMenu("StyLe");

boldItem = new JCheckBoxMenuItem("bold");

boldItem.addActionListener(this);

boldItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B,

InputEvent.CTRL_MASK));

fontStyleMenu.add(boldItem);

italicItem = new JCheckBoxMenuItem("italic");

italicItem.addActionListener(this);

fontStyleMenu.add(italicItem);

fontMenu.add(fontStyleMenu);

this.comboMenu = new JComboBox(new String[] {"12", "24", "48"});

this.comboMenu.setMaximumSize(new Dimension(50, 30));

this.comboMenu.addActionListener(this);

menuBar.add(fontMenu);

menuBar.add(comboMenu);

this.setJMenuBar(menuBar);

this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);

this.setSize(300, 300);

//this.show();

}

public void actionPerformed(ActionEvent e) {

if(e.getSource() == yellowButton) {

text.setBackground(Color.YELLOW);

yellowButton.setBackground(Color.YELLOW);

redButton.setBackground(Color.BLACK);

blueButton.setBackground(Color.BLACK);

}

else if(e.getSource() == redButton) {

text.setBackground(Color.RED);

yellowButton.setBackground(Color.BLACK);

redButton.setBackground(Color.RED);

blueButton.setBackground(Color.BLACK);

}

else if(e.getSource() == blueButton) {

text.setBackground(Color.BLUE);

157

yellowButton.setBackground(Color.BLACK);

redButton.setBackground(Color.BLACK);

blueButton.setBackground(Color.BLUE);

}

if(e.getSource() == editable)

text.setEditable(true);

else if(e.getSource() == noneditable)

text.setEditable(false);

if(e.getSource() == this.boldItem || e.getSource() == this.italicItem ||

e.getSource() == this.comboMenu) {

this.boldValue = this.boldItem.isSelected() ? Font.BOLD : 0;

this.italicValue = this.italicItem.isSelected() ? Font.ITALIC : 0;

this.size = Integer.parseInt((String)this.comboMenu.getSelectedItem());

this.text.setFont(new Font(this.face, this.boldValue + this.italicValue,

this.size));

}

this.repaint();

}

public static void main(String[] args) {

JPanelOrnek1 jp = new JPanelOrnek1();

jp.show();

}

}

NOT:

 

 

Hızlandırıcılar sadece menu nesnelerine eklenebilir. Menulere hızlandırıcı ataması yapılmaz.

Menu Nesnelerinin Geçerli ya da Geçersiz Hale Getirilmesi

JMenuItem openItem = new JMenuItem(“Open”, ‘O’);

openItem.setEnabled(false);

ya da

openItem.setEnabled(true);

javax.swing.awt paketi içerisinde MenuListener isminde bir arayüz tanımlıdır ve bu arayüzün metodları

class MenuListener {

void menuSelected(MenuEvent e) ;

void menuCanceled(MenuEvent e);

void menuDeselected(MenuEvent e) ;

}

Araç Çubukları (Toolbars)

158

Araç çubukları tahmin edebilecegimiz gibi üzerinde 1 ya da 1 den fazla dügme barındıran görünür menuler olarak

tanımlanabilir.

NOT: Eger içerisinde tanımlandıgı Container ‘ın layout modeli BorderLayout ise toolbar’ın drag

özelligi çalısacaktır

 

 

.

Ornek:

JToolBar bar = new JToolBar();

bar.add(blueButton);

bar.addSeperator();

Ornek:

contentPane.add(bar, BorderLayout.NORTH);

Ornek::

bar = new JToolBar(“Title”, SwingConstants.VERTICAL);

Asagıdaki örnek Sun Microsytems tarafından yayınlanan Core Java 1 kitabından aynen alınmıstır.

import java.awt.*;

import java.awt.event.*;

import java.beans.*;

import javax.swing.*;

public class ToolBarTest

{

public static void main(String[] args)

{

ToolBarFrame frame = new ToolBarFrame();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.show();

}

}

/**

A frame with a toolbar and menu for color changes.

*/

class ToolBarFrame extends JFrame

{

public ToolBarFrame()

{

setTitle("ToolBarTest");

setSize(WIDTH, HEIGHT);

// add a panel for color change

Container contentPane = getContentPane();

panel = new JPanel();

contentPane.add(panel, BorderLayout.CENTER);

// set up actions

Action blueAction = new ColorAction("Blue",

new ImageIcon("blue-ball.gif"), Color.blue);

Action yellowAction = new ColorAction("Yellow",

new ImageIcon("yellow-ball.gif"), Color.yellow);

Action redAction = new ColorAction("Red",

new ImageIcon("red-ball.gif"), Color.red);

Action exitAction = new

AbstractAction("Exit", new ImageIcon("exit.gif"))

159

{

public void actionPerformed(ActionEvent event)

{

System.exit(0);

}

};

exitAction.putValue(Action.SHORT_DESCRIPTION, "Exit");

// populate tool bar

JToolBar bar = new JToolBar();

bar.add(blueAction);

bar.add(yellowAction);

bar.add(redAction);

bar.addSeparator();

bar.add(exitAction);

contentPane.add(bar, BorderLayout.NORTH);

// populate menu

JMenu menu = new JMenu("Color");

menu.add(yellowAction);

menu.add(blueAction);

menu.add(redAction);

menu.add(exitAction);

JMenuBar menuBar = new JMenuBar();

menuBar.add(menu);

setJMenuBar(menuBar);

}

public static final int WIDTH = 300;

public static final int HEIGHT = 200;

private JPanel panel;

/**

The color action sets the background of the frame to a

given color.

*/

class ColorAction extends AbstractAction

{

public ColorAction(String name, Icon icon, Color c)

{

putValue(Action.NAME, name);

putValue(Action.SMALL_ICON, icon);

putValue(Action.SHORT_DESCRIPTION,

name + " background");

putValue("Color", c);

}

public void actionPerformed(ActionEvent evt)

{

Color c = (Color)getValue("Color");

panel.setBackground(c);

panel.repaint();

}

}

}

DialogPencereleri

Oldukça fazla sayıda hazır dialog pencereleri kullanılabilir:

160

Asaıdaki örnekte hazır olarak kullanılabilecek tüm dialog pencereleri oldukça detaylı bir sekilde ele alınmıstır:

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.*;

import java.util.*;

import javax.swing.*;

import javax.swing.border.*;

public class OptionDialogTest

{

public static void main(String[] args)

{

OptionDialogFrame frame = new OptionDialogFrame();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.show();

}

}

/**

A panel with radio buttons inside a titled border.

*/

class ButtonPanel extends JPanel

{

/**

Constructs a button panel.

@param title the title shown in the border

@param options an array of radio button labels

*/

public ButtonPanel(String title, String[] options)

{

setBorder(BorderFactory.createTitledBorder

(BorderFactory.createEtchedBorder(), title));

setLayout(new BoxLayout(this,

BoxLayout.Y_AXIS));

group = new ButtonGroup();

// make one radio button for each option

for (int i = 0; i < options.length; i++)

{

JRadioButton b = new JRadioButton(options[i]);

b.setActionCommand(options[i]);

add(b);

group.add(b);

b.setSelected(i == 0);

}

}

/**

Gets the currently selected option.

@return the label of the currently selected radio button.

*/

public String getSelection()

{

return group.getSelection().getActionCommand();

}

private ButtonGroup group;

}

/**

A frame that contains settings for selecting various option

161

dialogs.

*/

class OptionDialogFrame extends JFrame

{

public OptionDialogFrame()

{

setTitle("OptionDialogTest");

setSize(WIDTH, HEIGHT);

JPanel gridPanel = new JPanel();

gridPanel.setLayout(new GridLayout(2, 3));

typePanel = new ButtonPanel("Type",

new String[]

{

"Message",

"Confirm",

"Option",

"Input"

});

messageTypePanel = new ButtonPanel("Message Type",

new String[]

{

"ERROR_MESSAGE",

"INFORMATION_MESSAGE",

"WARNING_MESSAGE",

"QUESTION_MESSAGE",

"PLAIN_MESSAGE"

});

messagePanel = new ButtonPanel("Message",

new String[]

{

"String",

"Icon",

"Component",

"Other",

"Object[]"

});

optionTypePanel = new ButtonPanel("Confirm",

new String[]

{

"DEFAULT_OPTION",

"YES_NO_OPTION",

"YES_NO_CANCEL_OPTION",

"OK_CANCEL_OPTION"

});

optionsPanel = new ButtonPanel("Option",

new String[]

{

"String[]",

"Icon[]",

"Object[]"

});

inputPanel = new ButtonPanel("Input",

new String[]

{

"Text field",

"Combo box"

162

});

gridPanel.add(typePanel);

gridPanel.add(messageTypePanel);

gridPanel.add(messagePanel);

gridPanel.add(optionTypePanel);

gridPanel.add(optionsPanel);

gridPanel.add(inputPanel);

// add a panel with a Show button

JPanel showPanel = new JPanel();

JButton showButton = new JButton("Show");

showButton.addActionListener(new ShowAction());

showPanel.add(showButton);

Container contentPane = getContentPane();

contentPane.add(gridPanel, BorderLayout.CENTER);

contentPane.add(showPanel, BorderLayout.SOUTH);

}

/**

Gets the currently selected message.

@return a string, icon, component or object array,

depending on the Message panel selection

*/

public Object getMessage()

{

String s = messagePanel.getSelection();

if (s.equals("String"))

return messageString;

else if (s.equals("Icon"))

return messageIcon;

else if (s.equals("Component"))

return messageComponent;

else if (s.equals("Object[]"))

return new Object[]

{

messageString,

messageIcon,

messageComponent,

messageObject

};

else if (s.equals("Other"))

return messageObject;

else return null;

}

/**

Gets the currently selected options.

@return an array of strings, icons or objects, depending

on the Option panel selection

*/

public Object[] getOptions()

{

String s = optionsPanel.getSelection();

if (s.equals("String[]"))

return new String[] { "Yellow", "Blue", "Red" };

else if (s.equals("Icon[]"))

return new Icon[]

{

new ImageIcon("yellow-ball.gif"),

new ImageIcon("blue-ball.gif"),

163

new ImageIcon("red-ball.gif")

};

else if (s.equals("Object[]"))

return new Object[]

{

messageString,

messageIcon,

messageComponent,

messageObject

};

else

return null;

}

/**

Gets the selected message or option type

@param panel the Message Type or Confirm panel

@return the selected XXX_MESSAGE or XXX_OPTION constant

from the JOptionPane class

*/

public int getType(ButtonPanel panel)

{

String s = panel.getSelection();

try

{

return JOptionPane.class.getField(s).getInt(null);

}

catch(Exception e)

{

return -1;

}

}

/**

The action listener for the Show button shows a

Confirm, Input, Message or Option dialog depending

on the Type panel selection.

*/

private class ShowAction implements ActionListener

{

public void actionPerformed(ActionEvent evt)

{

if (typePanel.getSelection().equals("Confirm"))

JOptionPane.showConfirmDialog(

OptionDialogFrame.this,

getMessage(),

"Title",

getType(optionTypePanel),

getType(messageTypePanel));

else if (typePanel.getSelection().equals("Input"))

{

if (inputPanel.getSelection().equals("Text field"))

JOptionPane.showInputDialog(

OptionDialogFrame.this,

getMessage(),

"Title",

getType(messageTypePanel));

else

JOptionPane.showInputDialog(

OptionDialogFrame.this,

getMessage(),

"Title",

getType(messageTypePanel),

164

null,

new String[] { "Yellow", "Blue", "Red" },

"Blue");

}

else if (typePanel.getSelection().equals("Message"))

JOptionPane.showMessageDialog(

OptionDialogFrame.this,

getMessage(),

"Title",

getType(messageTypePanel));

else if (typePanel.getSelection().equals("Option"))

JOptionPane.showOptionDialog(

OptionDialogFrame.this,

getMessage(),

"Title",

getType(optionTypePanel),

getType(messageTypePanel),

null,

getOptions(),

getOptions()[0]);

}

}

public static final int WIDTH = 600;

public static final int HEIGHT = 400;

private ButtonPanel typePanel;

private ButtonPanel messagePanel;

private ButtonPanel messageTypePanel;

private ButtonPanel optionTypePanel;

private ButtonPanel optionsPanel;

private ButtonPanel inputPanel;

private String messageString = "Message";

private Icon messageIcon = new ImageIcon("blue-ball.gif");

private Object messageObject = new Date();

private Component messageComponent = new SamplePanel();

}

/**

A panel with a painted surface

*/

class SamplePanel extends JPanel

{

public void paintComponent(Graphics g)

{

super.paintComponent(g);

Graphics2D g2 = (Graphics2D)g;

Rectangle2D rect = new Rectangle2D.Double(0, 0,

getWidth() - 1, getHeight() - 1);

g2.setPaint(Color.yellow);

g2.fill(rect);

g2.setPaint(Color.blue);

g2.draw(rect);

}

public Dimension getMinimumSize()

{

return new Dimension(10, 10);

}

}

165

Yeni Dialog Pencerelerinin Yaratılması

Yeni bir dialog penceresi yaratmak için JDialog sınfından türetme yapmak gerekir. Aslında yeni bir dialog penceresi

yaratmak, yeni bir JFrame nesnesi yaratmaya benzer. Tıpkı JFrame yaratır gibi çesitli nesneleri JDialog nesnesi

üzerinde yerlestirerek istedigimiz gibi bir dilog penceresi yaratılabilir.

Asagıda oldukça basit bir dialog yaratma islemi gösterilmektedir:

class AboutDialog extends JDialog

{

public AboutDialog(JFrame owner)

{

/*owner parametresi bu dialog nesnesinin parent olan nesnesini

belirler*/

super(owner, "About DialogTest", true);

Container contentPane = getContentPane();

// add HTML label to center

contentPane.add(new JLabel(

"<HTML><H1><I>Core Java</I></H1><HR>"

+ "By Cay Horstmann and Gary Cornell</HTML>"),

BorderLayout.CENTER);

// Ok button closes the dialog

JButton ok = new JButton("Ok");

ok.addActionListener(new

ActionListener()

{

public void actionPerformed(ActionEvent evt)

{

setVisible(false);

}

});

// add Ok button to southern border

JPanel panel = new JPanel();

panel.add(ok);

contentPane.add(panel, BorderLayout.SOUTH);

setSize(250, 150);

}

}

import java.awt.Container;

import java.awt.FlowLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.JButton;

import javax.swing.JFrame;

/**

* @author DATAPRO

*

166

* TODO To change the template for this generated type comment go to

* Window - Preferences - Java - Code Style - Code Templates

*/

public class AboutTestFrame extends JFrame {

Container c;

JButton button = new JButton("About");

AboutDialog d;

public AboutTestFrame() {

c = getContentPane();

c.setLayout(new FlowLayout());

d = new AboutDialog(this);

button.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

d.show();

}

});

c.add(button);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setSize(300, 300);

this.show();

this.setResizable(false);

}

public static void main(String[] args) {

new AboutTestFrame();

}

}

Ancak yukarıdaki örnekte eksik olan sey bu dialog pencersinin bir deger üretmemesidir. Yani önemli olan sey dialog

pencereleri yardımıyla kullanıcıya birtakım bilgiler vermenin yanısıra aynı zamanda kullanıcıdan birtakım verileri

almaktır.

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

import javax.swing.event.*;

public class CustomDialog extends JDialog implements ActionListener {

private String entered;

JTextField tf;

public CustomDialog(JFrame owner) {

super(owner, "Ozel Dialog Penceresi", true);

Container c = getContentPane();

c.setLayout(new FlowLayout());

167

tf = new JTextField("Enter val", 10);

JButton b = new JButton("Tamam");

b.addActionListener(this);

c.add(tf);

c.add(b);

setSize(300, 80);

setResizable(false);

}

String getValue() {

show();

return entered;

}

public void actionPerformed(ActionEvent e) {

entered = tf.getText();

setVisible(false);

}

}

import java.awt.event.*;

import java.awt.*;

import javax.swing.*;

public class DialogTesFrame extends JFrame implements ActionListener {

Container c;

DialogTesFrame() {

c = getContentPane();

c.setLayout(new FlowLayout());

JButton dugme = new JButton("Dialog Goster");

dugme.addActionListener(this);

c.add(dugme);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setSize(600, 600);

show();

}

public void actionPerformed(ActionEvent e) {

CustomDialog cd = new CustomDialog(this);

System.out.print(cd.getValue());

}

public static void main(String arg[]) {

new DialogTesFrame();

168

}

}

FileDialog Nesneleri

Kullandıgımız programların birçogunda bilinen sekliyle open ve save menu seçenekleriyle birlikte gelen ve sistemde

herhangi birdosyayı “gözat” yöntemiyle bulup seçebilecegimiz dialog pencerelerine FileDialog pencereleri adı verilir.

Java’da bu islemi JFileChooser nesnesiyle kolaylıkla yapabiliyoruz. Bu nesnenin iki tane metodu ile dosya açmak ya

da dosya kaydetmek için pencereyi görüntülemek mümkündür:

-

 

showOpenDialog

-

 

showSaveDialog

JFileChooser fc = new JFileChooser();

fc.setCurrentDirectory(new File(“.”));

fc.setMultiSelectionEnabled(true); //birden fazla dosya seçimine izin verir.

fc.setFileSelectionMode(FileChooser.FILES_ONLY);

fc.setFileSelectionMode(FileChooser.DIRECTORIES_ONLY);

fc.setFileSelectionMode(FileChooser.FILES_AND_DIRECTORIES);

int result = fc.showOpenDialog(parent);

int result = fc.showSaveDialog(parent);

//JFileChooser.APPROVE_OPTION ya da JFileChooser.CANCEL_OPTION geri dönecektir.

String filename = fc.getSelectedFile().getPath();

Paketler

Java da bir grup sınıf ya da paketi bazı genel paketler alttında topladıgımızı daha önceden biliyoruz. Bunun nedeni

hem aynı konuya iliskin çalısmaları tek bir hiyerarsi altında toplamak hem de birtakım isim çakısmalarını önlemektir.

Öyle ki eger A isimli bir sınıfımızı kendi paketimiz içerisinde yazarsak, bir baska A isimli sınıf ancak baska bir paket

içerisinde yer alabilir ve böylece isim çakısmaları engellenmis olur.

Bir sınıf kendi paketi içerisindeki tüm sınıflara ve baska paketler içerisindeki public sınıflara erisebilir. Bu erisim için

ya ilgili paketin tam adını kullnarak sınıf adıyla erisim ya da sadece paketi import ederk sınıf adıyla erisim yapmak

gerekir. Örnegin com,academytech isimli paket içerisinde A isimli bir sınıfa erismek için:

a) import com.academytech.A ya da com.academytech.*;

...

A a = new A();

...

b) ...

com.academytech.A a = new com.academytech.A();

seklinde erisim yapılır.

Java da bir paketin içerisindeki tüm sınıflar import edildigi zaman gereksiz bir kod büyümesi olmaz. Bu konuda bir

performans düsüklügü olmaz.

Paketlere Sınıfların Eklenmesi

169

Java da bir sınıfı belirli paketin içerisine dahil etmek istiyorsak, dahil edilmek istenen sınıf bildiriminin basına

“package” anahtar sözcügü ile ait oldugu hiyerarsi yapısını yazarız.

Mesela;

A

 

herhangi bir yerde bir sınıf olarak yaratılsın.

A_1

 

sınıfı com.academytech.utils paketine ait olsun.

A_2

 

sınıfı com.academytech. messages paketinde olsun.

Diyelim ki A sınıfı kendi içinde A_1 ve A_2 sınıflarını kullansın. Bu durumda bu sınıflar disk üzerinde asagıda dizin

yapısına göre yerlestirilir:

parent

---------

A.java

com

|-------- academytech

|

|----------- utils

| -----

| A_1.java

|

|

|

|----------- messages

--------------

A_2.java

A_1 ve A_2 sınıflarının bildirimleri su sekilde yapılır:

/**** A_1.java ***/

package com.academytech.utils;

class A_1 {

}

/*** A_2.java ***/

package com.academytech.messages;

class A_2 {

}

Bu paketler içerisindeki A_1.java ve A_2.java sınıflarının derlenme ve yorumlanma

asamaları da su sekildedir:

# javac com/academytech/utils/A_1.java

# java com.academytech.utils.A_1

Bu durumda A sınıf içerisinde A_1 ve A_2 nesneleri kullanabilmek için A sınıfının içinde:

/*** A.java ***/

import com.academytech.utlis.*;

import com.academytech.messages.*;

class A {

170

...

A_1 a = new A_1(...);

...

A_2 b = new A_2(...);

}

JVM’nin Paketleri Bulması

Yukarıdaki örnekte görmekteyiz ki A sınıfı içerisinde kullanılan harici paketler sınıf ile aynı dizin altında yer alıyor.

Ancak bu durum çok esnek degildir. Yani her zaman kullanılan paketler, bu paketleri kullnadıgımız sınıflarla aynı

dizinde yer alamyabilir. Bu durum zaten projenin esnekligini ve tasınabilirligini de ortadan kaldıracagı için pek tercih

edilmez.

Birden fazla farklı paketin çalısılan dizinden bagımsız olarak kullanılabilmesi için:

1) paketlerin yer alacagı bir dizin yaratılır. Örnegin:

 

/home/academytech/javapaketleri

2) Daha önce sizin ya da baskalarının yazdıgı bu paketler parent dizinleri ile birlikte (com gibi) bu ana dizin

altına kopyalanır. Bizim örnegimiz için

 

com/academytech dizini /home/academytech/javapaketleri

dizini altına kopyalanır.

3) class path ayarı yapılır. CLASSPATH, JVM’ye aranacak paketlerin nerelerde aranacagını belirten bir ayardır.

(linux’de export ile windows’da environment variables ayarı ile yapılabilir. Bkz. ders 1)

Herhangi bir yerdeki sınıfı derlerken derleme ve yorumlama asamasında da classpath bilgisi verilebilir:

# javac –classpath (ya da -cp) /home/academytech/javapaketleri:. A.java

# java –classpath /home/academytech/javapaketleri:. A

Bu örnekte A.java com.academytech paketi altındaki A_1 ve A_2 sınıflarını kullanıyor.

Normalde compiler ilk olarak jre/lib ve jre/lib/ext dizinleri altındaki sistem kütüphanelerinde gerekli sınıfları arar.

Burada bulamadıgı sınıfları da classpath içerisinde arar.

Paket Faliyet Alanı

Bir sınıf, metod ya da degisken public ise baska herhangi bir sınıf tarafından kullanılabilir.

Bir sınıf, metod ya da degisken private ise sadece kendi dosyası içerisindeki baska sınıflar tarafından kullanılabilir.

Bir sınıf, metod ya da degisken bildiriminde public ya da private anahtar sözcügü yer almıyorsa o zaman o sınıf,

metod ya da degiskene sadece kendi paketindeki diger sınıflar erisebilir.

Dökümantasyon Yaratma (javadoc)

Java’da kod içerisine yazılacak birtakım etiketler sayesinde profosyonel bir dökümantasyon hazırlamak mümkündür.

Aslında java’nın kendi dökümantasyonu da az sonra bahsedilecek olan yöntemlerle hazırlanmıstır.

javadoc denilen komut kod içerisindeki bu özel etiketleri algılayarak istenilen dizinler altında dökümantasyonu .html

sayfaları olarak üretir.

171

Genel olarak dökümantasyon paketler, public sınıflar ve arayüzler, public ve protected metodlar ile public ve

protected veri elemanları için hazırlanır.

Her dökümantasyon komutu /** ve */ sembolleri arasında ve dökümante edilecek paket, sınıf, metod ya da

degiskenin hemen üstünde yer alır.

@author yazar adi

@return <açıklama>: metodun geri dönüs degerine iliskin bir açıklama

@param <deger> <aciklama>: parametrenin açıklanması

@see “” : See Also kısmının hazırlanması

Bu etiketlerin yanı sıra bilinen tüm html etiketleri de kullanılabilir. Bunlardan

bazıları:

<code> : Kod stili seklinde yazma

<img > : imaj ekleme

<strong> : strong vurgu yapmak

gibi..

Eclipse’de File/Export menu seçenegi yardımıyla otomatik olarak olusturulabilir. Ancak bu ousturma asamasında

Eclipse sizden “javadoc” komutunun lokasyonunu girmenizi isteyecektir.

JAR Dosyalarının Olusturulması

Jar dosyalarını olusturmaktaki temel amaç uygulamanın tek bir arsivde toplanması hatta tek bir dosya seklinde

çalıstırılmasını saglamaktır.

Aslında genel olarak bakıldıgında jar dosyası olusturmak birkaç küçük adımdan ibarettir.

Bir jar arsivi yaratmak için:

#jar cvf <arsiv_adi>.jar <arsivlenecek_dosya1> [ve/veya] <arsivlenecek_dosya2> [ve/veya]

*.java

Örnegin bulundugum dizin altındaki A.java, B.java ve C.java dosyaları ile a.gif dosyasını içeren bir .jar arsivi

olusturmak için:

#jar cvf program.jar A.class B.class C.class a.gif

yazmak yeterlidir.

Bir arsivin içerisine ayrıca “manifest” adı verilen özel bir dosya daha yerlestirilir. Bu dosya aslında arsiv hakkında

birtakım konfigurasyon bilgileri verir.

Aslında genel java sistem kütüphaneleri bu sekilde arsivler içerisinde tutularak kullanılmaktadır. SDK’nın runtime

kütüphanesi olan rt.jar böyle bir arsivdir.

Sonuç olarak .jar arsivleri bir programın ihtiyaç duyacagı tüm dosyaları barındıran sıkıstırılmıs bir dosyadır. Ayırca

arsivin tüm teknik bilgilerini barındıran MANIFEST.MF dosyası da arsivin içerisinde yer alır.

Manifest Dosyasının çerigi

/*** MANIFEST.MF ***/

Manifest-Version: 1.0

<arsivi tanimlayan satirlar>

Name: Person.class

<Sınıfı tanımlayan satırlar>

Name: com/academytech/

172

<bu paketi tanımlayan satırlar>

Bu sekilde bir manifest dosyasını, com/academytech paketini ve Genel sınıfını içeren bir arsiv yaratmak için:

#jar cfm program.jar manifest.mf com/academytech/*.class A.class

Kendi basına çalısabilen bir arsiv yaratmak için manifest dosyası içerisinde bir de bu programı çalıstıracak main

metodunu içeren sınıfn bilgisi de eklenmelidir:

Main-Class: com/academytech/Main

Bundan sonra arsiv su sekilde çalıstırılabilir:

java –jar program.jar

Konsolda basit bir uygulama:

1) Asagıdaki iki sinifi yaziniz.

2) B.java sınıfını com/academytech dizini altına yerlestiriniz. Daha sonra bu com dizinini yerlestirdigniz

lokasyonu classpath olarak ayarlayınız.

import com.academytech.*;

class A {

public static void main(String arg[]) {

B b = new B();

b.show();

}

}

package com.academytech;

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class B extends JFrame implements ActionListener {

Container c;

public B() {

c = getContentPane();

c.setLayout(new FlowLayout());

JButton b = new JButton("submit");

b.addActionListener(this);

c.add(b);

setSize(300, 400);

}

public void actionPerformed(ActionEvent e) {

JOptionPane.showMessageDialog(null, "Merhaba");

}

public static void main(String arg[]) {

B b = new B();

b.show();

}

}

173

3) Asagıdaki gibi manifest.mf dosyasını olusturunuz:

/*** manifest.mf ***/

Manifest-Version: 1.0

Main-Class: A

/***************/

NOT: Main-Class: A yazdıktan sonra bir satır bosluk bırakıldıgına dikkat

ediniz.

4) komut: java cvfm program.jar manifest.mf A.class com\academytech\B.class

5) sonuc: java –jar program.jar

174

Java Derleri

Bölüm 20

Java Collections

Bu kısımda programcılık açısından oldukça önemli olan veri yapıları kavramlarının Java’da nasıl ele alındıgını

inceleyecegiz.

Aslında veri yapıları kavramları genel olarak oldukça fazal ve detaylı bilgileri içerir. Biz ise burada sadece en temel

olanları ele alacagız. Bu kısım tamalandıktan sonra elinizdeki herhangi bir veri yapısını Java Programalama dilinde

kolaylıkla çevirebileceginizi umuyoruz.

Collection ve Iterator Arayüzü Kavramı

Java’da veri yspıları mekanizmalarını ele alan ve herbirini daha sonra ele alacagımız bu tasıyıcıların hepsi Collection

denilen bir arayüzden türemistir.

Bir Collection arayüzünün temel olan iki metodu

boolean add(Object obj)

Iterator iterator

 

()

itarator isimli metod kullanılan tasıyıcı üzerinde Iterator sınıfını implement eden bir sınıfı geri gönderir. Bu Iterator

arayzünün temel metodları:

Object next()

boolean hasNext()

void remove()

bu Iterator nesnesi yardımıyla tasıyıcı üerindeki elemanlar tek tek ziyaret edilebilir. Ancak tasıyıcının sonuna

gelindiginde NoSuchElementException üretilir. Bu nedenle tasıyıcı üzerinde gezerken hasNext metoduyla kontrol

yapılarak gezme islemi sürdürülür:

//c bir collection olarak yaratılmıs olsun

Iterator iter = c.iterator();

while(iter.hasNext()) {

Object obj = iter.next();

...

}

remove metodu ile iteraturun next ile elde edilen son eleman listeden silinir. Yani bu kullanım bir eleman elde

edilmeden silinmesine engel olmaktadır. Önce next ile eleman kontrol edilmeli ve sonra remove edilmelidir. Bir

eleman next ile geçilmeden önce remove ile silinemez.

Iterator iter = c.iterator();

Object obj = iter.next(); sıradki eleman alındı.

175

iter.remove(); az once alınan eleman silindi.

Normalde kullanıcılar kendileri de isterlerse Collection ve Iterator sınıflarını implement edebilirler. Hatta bunu

arayüzlerin tüm metdlarını implement etmek ygrucu gelebilecegi için AbstrackCollection sınıfı da implement

edilebilir. Bu arayüzlerin içerdikleri metdoların listesine dökümantasyon üzerinden erisilebilir.

LinkedList

LinkedList nesnesi bilinen baglı liste implementasyonunu gerçekler.

LinkedList ogrenciler = new LinkedList();

ogrenciler.add(“Academytech”);

ogrenciler.add(“Caglar”);

ogrenciler.add(“Ahmet”);

LinkedList nesnesi için kullanılan iterator ListIterator olarak isimlendirilir. Bu iterator’de Iterator arayüzünden

olmayan “add” metodu yer alır. Böylece iterator baglı liste üzerinde istenilen pozisyona getirilerek yeni bir eleman

araya eklenebilir.

ListIterator iter = ogrenciler.iterator();

Ayrıca ListIterator nesnesinde yer alan “previous” ve “hasPrevious” metodları ile de geri yönlü bir tarama yapılabilir.

ListIterator nesnesinin “set” isimli metodu next ile elde edilen son elemanı yeni bir elemanla degistirmeye yarar.

Object eskiDeger = iter.next();

iter.set(yeniDeger);

ÖDEV:

Asagıdaki örnekte henüz operasyonları tanımlanmamıs olan Next, Previous, Add New Object ve Remove Object

metodlarını hazırlayınız ve programı tamamlayınız.

import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Container;

import java.awt.Font;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.util.LinkedList;

import java.util.ListIterator;

import javax.swing.JButton;

176

import javax.swing.JFrame;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JTextArea;

public class LinkedListHandler extends JFrame implements ActionListener {

JButton add_1, list, next, remove, previous, add_2;

JTextArea screen;

JPanel tourPanel, mainPanel;

Container c;

LinkedList objectlist;

public LinkedListHandler() {

prepareComponents();

prepareFrame(600, 300, false, true);

}

private void prepareFrame(int x_size, int y_size, boolean resizable, boolean

show) {

this.setSize(x_size, y_size);

this.setResizable(resizable);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

if(show)

this.show();

}

private void prepareComponents() {

c = getContentPane();

add_1 = new JButton("Add");

add_1.addActionListener(this);

177

list = new JButton("List All");

list.addActionListener(this);

next = new JButton("Next Object");

next.addActionListener(this);

previous = new JButton("Previous Object");

previous.addActionListener(this);

remove = new JButton("Remove Current Object");

remove.addActionListener(this);

add_2 = new JButton("Add New Object");

add_2.addActionListener(this);

tourPanel = new JPanel();

tourPanel.add(next);

tourPanel.add(previous);

tourPanel.add(remove);

tourPanel.add(add_2);

c.add(tourPanel, BorderLayout.SOUTH);

mainPanel = new JPanel();

mainPanel.add(list);

mainPanel.add(add_1);

c.add(mainPanel, BorderLayout.NORTH);

screen = new JTextArea();

screen.setEditable(false);

screen.setBackground(Color.BLACK);

screen.setForeground(Color.GREEN);

screen.setFont(new Font("Serif", Font.BOLD, 24));

c.add(screen, BorderLayout.CENTER);

}

private void prepareButton(JButton button, String button_name, ActionListener

listener) {

button = new JButton(button_name);

button.addActionListener(listener);

}

178

public void actionPerformed(ActionEvent e) {

if(e.getSource() == add_1) {

if(this.objectlist == null)

this.objectlist= new LinkedList();

if(this.objectlist.add(JOptionPane.showInputDialog(this, "New

Record")));

screen.setText("Yeni kayit eklendi...");

screen.validate();

}

else if(e.getSource() == this.list) {

StringBuffer buf = new StringBuffer("");

if(this.objectlist != null) {

ListIterator iter = (ListIterator)objectlist.iterator();

while(iter.hasNext())

buf.append("\n"+(String)iter.next());

}

else

buf.append("nothing is recorded yet!!!");

screen.setText(buf.toString());

screen.validate();

}

}

public static void main(String[] args) {

new LinkedListHandler();

}

}

179

Vector Nesnesi

Bu nesne aslında diziler gibi bir veri yapısını meydana getirir .Ancak dizilerde olmayan dinamik olarak büyüme

özelligi de Vector nesneleri ile birlikte gelir.

Herhangi bir zaman dilimi içerisinde bir Vector nesnesi kendi kapasitesinden daha az ya da esit sayıda nesne

barındırır. Eger kapasitesi dolduysa ve büyümesi gerekiyorsa o zaman istenilen miktarda dinamik olarak

genisletilebilir.

Eger kullanıcı herhangi bir kapasite artıs miktarı belirtmezse o zaman vektor kendi boyutunun iki katı genislige

büyütülür.

Vector nesnesi de diger yapılar gibi Object nesnelerini tasır.

NOT:

 

Vector nesnelerinin ArrayList nesnelerinden farkı senkron edilmelidir. Eger birden fazla thread Vector

üzerinde kullnılıyorsa Vector nesnesi sürekli senkron olur. Ancak ArrayList böyle bir islem yapmaz. Eger birden fazla

thread kullanılımıyorsa senkron için zaman harcamadıgından dolayı ArrayList tercih edilebilir.

Enumaration Nesnesi ile Vector içerisinde dolasmak

Asagıdaki örnekte kullanılan Enumaration nesnesi Vector sınıfının elements isimli metodu tarafından gönderilen bir

nesnedir. Bu nesne vector içerisinde dolasabilmeyi saglayan iki tane metoda sahiptir:

nextElement()

hasMoreElements()

import

 

 

java.util.*;

import

 

 

java.awt.*;

import

 

 

java.awt.event.*;

import

 

 

javax.swing.*;

public class

 

 

VectorTest extends JFrame {

public

 

 

VectorTest()

{

super

 

 

( "Vector Example" );

final

 

 

JLabel status = new JLabel();

Container c = getContentPane();

final

 

 

Vector v = new Vector( 1 );

c.setLayout(

 

new FlowLayout() );

c.add(

 

new JLabel( "Enter a string" ) );

final

 

 

JTextField input = new JTextField( 10 );

c.add( input );

JButton addBtn =

 

new JButton( "Add" );

addBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

180

v.addElement( input.getText() );

status.setText(

 

"Added to end: " +

input.getText() );

input.setText(

 

"" );

}

}

);

c.add( addBtn );

 

// add the input value

JButton removeBtn =

 

new JButton( "Remove" );

removeBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

if

 

 

( v.removeElement( input.getText() ) )

status.setText(

 

"Removed: " +

input.getText() );

else

status.setText( input.getText() +

" not in vector"

 

 

);

}

}

);

c.add( removeBtn );

JButton firstBtn =

 

new JButton( "First" );

firstBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

try

 

 

{

status.setText(

 

"First element: " +

v.firstElement() );

}

catch

 

 

( NoSuchElementException exception ) {

status.setText( exception.toString() );

}

}

}

);

c.add( firstBtn );

JButton lastBtn =

 

new JButton( "Last" );

lastBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

try

 

 

{

status.setText(

 

"Last element: " +

v.lastElement() );

}

catch

 

 

( NoSuchElementException exception ) {

status.setText( exception.toString() );

}

}

}

);

c.add( lastBtn );

181

JButton emptyBtn =

 

new JButton( "Is Empty?" );

emptyBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

status.setText( v.isEmpty() ?

"Vector is empty"

 

 

: "Vector is not empty" );

}

}

);

c.add( emptyBtn );

JButton containsBtn =

 

new JButton( "Contains" );

containsBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

String searchKey = input.getText();

if

 

 

( v.contains( searchKey ) )

status.setText(

 

"Vector contains " +

searchKey );

else

status.setText(

 

"Vector does not contain " +

searchKey );

}

}

);

c.add( containsBtn );

JButton locationBtn =

 

new JButton( "Location" );

locationBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

status.setText(

 

"Element is at location " +

v.indexOf( input.getText() ) );

}

}

);

c.add( locationBtn );

JButton trimBtn =

 

new JButton( "Trim" );

trimBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

v.trimToSize();

status.setText(

 

"Vector trimmed to size" );

}

}

);

c.add( trimBtn );

JButton statsBtn =

 

new JButton( "Statistics" );

statsBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

status.setText(

 

"Size = " + v.size() +

"; capacity = "

 

 

+ v.capacity() );

}

}

182

);

c.add( statsBtn );

JButton displayBtn =

 

new JButton( "Display" );

displayBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

Enumeration enum = v.elements();

StringBuffer buf =

 

new StringBuffer();

while

 

 

( enum.hasMoreElements() )

buf.append(

enum.nextElement() ).append(

 

" " );

JOptionPane.showMessageDialog(

 

null,

buf.toString(),

 

"Display",

JOptionPane.

 

PLAIN_MESSAGE );

}

}

);

c.add( displayBtn );

c.add( status );

setSize( 300, 200 );

show();

}

public static void

 

 

main( String args[] )

{

VectorTest app =

 

new VectorTest();

app.addWindowListener(

new

 

 

WindowAdapter() {

public void

 

 

windowClosing( WindowEvent e )

{

System.exit( 0 );

}

}

);

}

}

Stack Nesnesi

Bu nesne Vector nesnesinde türetilerek elde edilmis ve Stack adı verilen veri yapılarını ele almak için tasarlanmıstır.

Vector sınıfı gibi, Stack sınıfı içerisinde Object türünden nesneler saklanmaktadır. Eger primitive type verileri bu

yapılar içinde saklamak isterseniz bunları daha önce inceledigimiz Integer, Double gibi sargı sınıfları yardımıyla

nesne haline getirerek kullanabilirsiniz.

183

Bir stack nesnesi içerisine yeni bir eklemek “push” denilen bir operasyon ile gerçeklesir. Stack içerisine bir veri push

ile eklendikten sonra “pop” ile elde dilebilir. Bu durumda Stack veri yapısı üzerinde LIFO (Last In First Out) mantıgı

geçerlidir.

Asagıdaki örnek Deitel&Deitel tarafından yazılan Java HowTo Program, Third Edition kitabından degistirilmeden

alınmıstır.

import

 

 

java.util.*;

import

 

 

java.awt.*;

import

 

 

java.awt.event.*;

import

 

 

javax.swing.*;

public class

 

 

StackTest extends JFrame {

public

 

 

StackTest()

{

super

 

 

( "Stacks" );

Container c = getContentPane();

final

 

 

JLabel status = new JLabel();

final

 

 

Stack s = new Stack();

c.setLayout(

 

new FlowLayout() );

c.add(

 

new JLabel( "Enter a string" ) );

final

 

 

JTextField input = new JTextField( 10 );

c.add( input );

JButton pushBtn =

 

new JButton( "Push" );

pushBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

status.setText(

 

"Pushed: " +

s.push( input.getText() ) );

}

}

);

c.add( pushBtn );

JButton popBtn =

 

new JButton( "Pop" );

popBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

try

 

 

{

status.setText(

 

"Popped: " + s.pop() );

}

catch

 

 

( EmptyStackException exception ) {

status.setText( exception.toString() );

}

}

}

);

c.add( popBtn );

JButton peekBtn =

 

new JButton( "Peek" );

peekBtn.addActionListener(

new

 

 

ActionListener() {

184

public void

 

 

actionPerformed( ActionEvent e )

{

try

 

 

{

status.setText(

 

"Top: " + s.peek() );

}

catch

 

 

( EmptyStackException exception ) {

status.setText( exception.toString() );

}

}

}

);

c.add( peekBtn );

JButton emptyBtn =

 

new JButton( "Is Empty?" );

emptyBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

status.setText( s.empty() ?

"Stack is empty"

 

 

: "Stack is not empty" );

}

}

);

c.add( emptyBtn );

JButton searchBtn =

 

new JButton( "Search" );

searchBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

String searchKey = input.getText();

int

 

 

result = s.search( searchKey );

if

 

 

( result == -1 )

status.setText( searchKey +

 

" not found" );

else

status.setText( searchKey +

" found at element "

 

 

+ result );

}

}

);

c.add( searchBtn );

JButton displayBtn =

 

new JButton( "Display" );

displayBtn.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

Enumeration enum = s.elements();

StringBuffer buf =

 

new StringBuffer();

while

 

 

( enum.hasMoreElements() )

buf.append(

enum.nextElement() ).append(

 

" " );

JOptionPane.showMessageDialog(

 

null,

buf.toString(),

 

"Display",

JOptionPane.

 

PLAIN_MESSAGE );

}

}

);

c.add( displayBtn );

c.add( status );

185

setSize( 675, 100 );

show();

}

public static void

 

 

main( String args[] )

{

StackTest app =

 

new StackTest();

app.addWindowListener(

new

 

 

WindowAdapter() {

public void

 

 

windowClosing( WindowEvent e )

{

System.exit( 0 );

}

}

);

}

}

Örnekte kullanılan “peek” isimli metod stack nesnesi üzerinde herhangi “pop” islemi yapmadan en yukarıdaki

elemanı görüntülemeye yarar.

Bu örnek içerisinde de stack içerisinde dolasmak için yine Enumaration isimli nesne elde dilmistir. Stack nesnesinin

aslında Vector nesnesinden bir türetme oldugu buradan da anlasılabilir.

HashTable Nesnesi

Hashing islemi ve bu islemi gerçeklestirmek için kullanılan algoritma oldukça detaylı bir konudur. Burada önemli

olan HashTable nesnesinin verileri nasıl ele aldıgıdır.

HashTable verilerin fazla sayıda oldugu ve sırasından ziyade çabuk ulasılabilir olmasıın tercih edildigi durumlarda

kullanılan bir yapıdır. 1ç mekanizması hashing islemine dayanan bu yapı verilere çok hızlı bir sekilde erisebilmeyi

saglar. Ancak bu erisimde verilerin yerlesimi Vector ve LinkedList yapılarında oldugu gibi belirli bir sırada degildir.

Onun yerine her veri için özel bir hesapla atanan “hash number” anahtarı yardımıyla her elemanı LinkedList olan bir

diziye bu veriler yerlestirilir. Bu hash number aslında verinin lokasyonu konusunda bilgi içerdiginden verilere erisim

oldukça hızlı bir sekilde gerçeklesir.

put metodu belirli bir key ile birlikte yeni bir nesne eklemeye yarar. Ancak bu metodu geri dönüs degeri Object’tir.

Eger eklenecek olan anahtar tabloda zaten varsa, bu abahtarın gösterdigi nesne kullanıcıya geri döner. Eger

eklenecek olan anahtar tabloda yoksa o zaman null degeri gei dönecektir.

get metodu kendisine verilen anahtarla eslesmis olan Object nesnesini geri gönderir. Eger böyle bir nahtarla

iliskilendirilmis bir nesne tabloda yoksa, o zaman null deger geri dönecktir.

elements ve keys metodları, tablodaki anahtar ve nesnelerin iteratörlerini yani Enumaration nesnelerini geri

gönderir.

186

Asagıdaki örnek Deitel&Deitel tarafından yazılan Java HowTo Program, Third Edition kitabından degistirilmeden

alınmıstır.

import

 

 

java.util.*;

import

 

 

java.awt.*;

import

 

 

java.awt.event.*;

import

 

 

javax.swing.*;

public class

 

 

HashTableTest extends JFrame {

public

 

 

HashTableTest()

{

super

 

 

( "Hashtable Example" );

final

 

 

JLabel status = new JLabel();

final

 

 

Hashtable table = new Hashtable();

final

 

 

JTextArea display = new JTextArea( 4, 20 );

display.setEditable(

 

false );

JPanel northPanel =

 

new JPanel();

northPanel.setLayout(

 

new BorderLayout() );

JPanel northSubPanel =

 

new JPanel();

northSubPanel.add(

 

new JLabel( "First name" ) );

final

 

 

JTextField fName = new JTextField( 8 );

northSubPanel.add( fName );

northSubPanel.add(

 

new JLabel( "Last name (key)" ) );

final

 

 

JTextField lName = new JTextField( 8 );

northSubPanel.add( lName );

northPanel.add( northSubPanel, BorderLayout.

 

NORTH );

northPanel.add( status, BorderLayout.

 

SOUTH );

JPanel southPanel =

 

new JPanel();

southPanel.setLayout(

 

new GridLayout( 2, 5 ) );

JButton put =

 

new JButton( "Put" );

put.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

Employee emp =

 

new Employee(

fName.getText(), lName.getText() );

Object val = table.put( lName.getText(), emp );

if

 

 

( val == null )

status.setText(

 

"Put: " + emp.toString() );

else

status.setText(

 

"Put: " + emp.toString() +

"; Replaced: "

 

 

+ val.toString() );

}

}

);

southPanel.add( put );

JButton get =

 

new JButton( "Get" );

get.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

Object val = table.get( lName.getText() );

if

 

 

( val != null )

187

status.setText(

 

"Get: " + val.toString() );

else

status.setText(

 

"Get: " + lName.getText() +

" not in table"

 

 

);

}

}

);

southPanel.add( get );

JButton remove =

 

new JButton( "Remove" );

remove.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

Object val = table.remove( lName.getText() );

if

 

 

( val != null )

status.setText(

 

"Remove: " +

val.toString() );

else

status.setText(

 

"Remove: " +

lName.getText() +

 

" not in table" );

}

}

);

southPanel.add( remove );

JButton empty =

 

new JButton( "Empty" );

empty.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

status.setText(

 

"Empty: " + table.isEmpty() );

}

}

);

southPanel.add( empty );

JButton containsKey =

 

new JButton( "Contains key" );

containsKey.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

status.setText(

 

"Contains key: " +

table.containsKey( lName.getText() ) );

}

}

);

southPanel.add( containsKey );

JButton clear =

 

new JButton( "Clear table" );

clear.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

table.clear();

status.setText(

 

"Clear: Table is now empty" );

}

}

);

southPanel.add( clear );

JButton listElems =

 

new JButton( "List objects" );

188

listElems.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

StringBuffer buf =

 

new StringBuffer();

for

 

 

( Enumeration enum = table.elements();

enum.hasMoreElements(); )

buf.append(

enum.nextElement() ).append(

 

'\n' );

display.setText( buf.toString() );

}

}

);

southPanel.add( listElems );

JButton listKeys =

 

new JButton( "List keys" );

listKeys.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

StringBuffer buf =

 

new StringBuffer();

for

 

 

( Enumeration enum = table.keys();

enum.hasMoreElements(); )

buf.append(

enum.nextElement() ).append(

 

'\n' );

JOptionPane.showMessageDialog(

 

null,

buf.toString(),

 

"Display",

JOptionPane.

 

PLAIN_MESSAGE );

}

}

);

southPanel.add( listKeys );

Container c = getContentPane();

c.add( northPanel, BorderLayout.

 

NORTH );

c.add(

 

new JScrollPane( display ), BorderLayout.CENTER );

c.add( southPanel, BorderLayout.

 

SOUTH );

setSize( 540, 300 );

show();

}

public static void

 

 

main( String args[] )

{

HashTableTest app =

 

new HashTableTest();

app.addWindowListener(

new

 

 

WindowAdapter() {

public void

 

 

windowClosing( WindowEvent e )

{

System.exit( 0 );

}

}

);

}

}

class

 

 

Employee {

private

 

 

String first, last;

189

public

 

 

Employee( String fName, String lName )

{

first

 

 

= fName;

last

 

 

= lName;

}

public

 

 

String toString() { return first + " " + last; }

}

JDBC Teknolojisi

1996 yazında Sun JDBC aracının ilk versiyonunu duyurdu. Böyle bir aracın gelistirilmesindeki asıl maksat tek bir

arayüz üzerinde birbirinden bagımsız veri tabanlarına erisimi saglamaktı.

Bu erisim saglandıktan sonra standart SQL dili ile veri tabanı üzerinde sorgu yapılabilecekti.

Daha özel olarak bahsetmek gerekirse JDBC iki katmandan meydana gelir. En yukarıda JDBC arayüzü vardır. Bu

API JDBC sürücü yöneticisi ile haberleserek ona birtakı SQL sorguları gönderir.

Sürücü yöneticisi de kendisi de API den gelen bu sorguları ele alır ve 3. parti veri tabanı sistemleri ile iletisim

kurarak sorguları bu veri tabanları üzerinde çalıstırır ve sonuçları tekrar API’ye gönderir.

Class.forName(“COM.ibm.db2.jdbc.app.DB2Driver”):

Bu bildirim yukarıdaki semada belirtilen JDBC Driver API katmanının ihtiyaç duyacagı 3. parti sürücüyü kayıt etmek

için (yüklemek için) kullanılır. O halde aslında bu bildirim için gerekli olan bu sürücü (burada

“COM.ibm.db2.jdbc.app.DB’Driver”)

 

3. parti veri tabanı üreticileri tarafından sunulmalıdır.

190

Böyle bir sürücü sisteme indirildikten sonra CLASSPATH tarafından görülen bir lokasyona ya da java’nın default

olarak görebildigi herhangi bir lokasyona yerlestirilir. Böylece artık yukarıdaki bildirimi kullanmak için bir engel

kalmaz. 1ndirdiginiz sürücü .zip ya ya da .jar uzantılı olabilir. CLASSPATH içerisine koyulacak olan path bilgisinde bu

.zip ya da .jar uzantılı dosya da yer almalıdır. Örnegin sürücümüz mysql.jar olsun:

CLASSPATH = /bir/yer; ....; /home/drivers/ java/mysql.jar

Database URL

Database sistemde yüklendikten ve yukarıdaki gibi sürücü yüklendikten sonra veri tabanına baglanma asamasına

gelinmistir. Bu asamada baglanmak için kullanılan veri tabanı sistemine uygun bir URL ile baglantı kurulur. Bu

URL’nin en genel hali:

jdbc:<alt protokol ismi>:<diger bilgiler>

seklindedir. Bu URL 3. parti veri tabanı sistemi tarafından saglanır. Bu url kullanılarak

Connection conn=DriverManager.getConnection(url, username, password);

Bilgisi ile veri tabanına JDBC API üzerinden baglantı saglanır.

SQL Komutlarının Çalıstırılması

SQL komutlarının çalıstırılması için öncelikle Statement türünden bir nesne yaratılır. Bunun için öceden yaratılmıs

olan Connection nesnesi üzerinden createStatement() metodu çagrılır.

Statement st = conn.createStatement();

Bu Statement nesnesi üzerinde

int executeUpdate(String query):

st.executeUpdate(“UPDATE Books SET Price = Price – 500 WHERE Title NOT LIKE ‘%HTML 3%’”);

gibi bir tablo güncelleme komutu çalıstırılabilir. Bu metodun geri dönüs degeri bu güncellemeden etkilenen satır

sayısıdır.

executeUpdate komutu ile INSERT, UPDATE, DELETE, CREATE TABLE ve DROP TABLE operasyonları çalıstırılabilir.

ResultSet executeQuery(String query):

Ancak bir sorgu çalıstırıldıgında gelecek olan sonuçlarla ilgileniriz. Statement nesnesinin executeQuery metodu bize

bu sonuçları içeren bir ResultSet nesnesi gönderir.

191

ResultSet rs = st.executeQuery(“SELECT * FROM Books”);

while(rs.next()) {

String name = rs.getString(“Name”);

...

}

Böylece ResultSet içerisine gelen her satır rs.next() ile elde edilirken bu satır içerisindeki her sütun kendi adıyla

birlikte rs.getString(“<sütun adi>”) nesnesi içerisinde kullanılır ve degerler elde edilir.

JDBC-ODBC Köprüsü ile Access Veri Tabanına Baglantı

1. Sistemde Access veri tabanı yüklü olmalıdır. Ayrıca bu veri tabanı sistemi üzerinde olusturulmus bir veri

tabanı hazır olmalıdır. (Bu örnekte Books.mdb kullanılacak)

2. Elde edilen bu veri tabanı ODBC üzerinde kaydedilmelidir. Bu islem için Microsoft Control Panel üzerinde

Administrative Task -> Data Sources (ODBC) seçilir. Daha sonra asagıdaki 3 adım gerçeklestirilir.

192

Daha sonra önceden hazırlanmıs olan Access Veri tabanı sistemden seçilir:

Son olarak bu veri tabanına erisim için gerekli olan sifre ve parola bilgisi girilir:

193

Artık JDBC-ODBC köprüsü hazırlanmıstır. Geriye sadece uygun bir program yazmak ve program içerisinde bu veri

tabanına erisimi saglamaktır. Asagıdaki örnek kod parçası bu erisimin nasıl yapılacagını göstermektedir:

String url =

 

"jdbc:odbc:Books"; //Books veri tabanı ismi

String username =

 

"ermanaykac";

String password =

 

"197919";

try

 

 

{

Class.forName(

 

"sun.jdbc.odbc.JdbcOdbcDriver");

//Bu url JDBC-ODBC köprüsü için gerekli

connection

 

 

= DriverManager.getConnection(url, username, password );

}

 

catch ( ClassNotFoundException cnfex ) {

System.

 

err.println( "Failed to load JDBC/ODBC driver." );

cnfex.printStackTrace();

System.exit( 1 );

 

// terminate program

}

catch

 

 

( SQLException sqlex ) {

System.

 

err.println( "Unable to connect" );

sqlex.printStackTrace();

System.exit( 1 );

 

// terminate program

}

Asagıdaki örnekte bütünüyle bu baglantı ve baglantı üzerinde kullanılan sorgular

incelenmektedir.

import

 

 

java.sql.*;

194

import

 

 

javax.swing.*;

import

 

 

java.awt.*;

import

 

 

java.awt.event.*;

import

 

 

java.util.*;

public class

 

 

DisplayQueryResults extends JFrame {

// java.sql types needed for database processing

private

 

 

Connection connection;

private

 

 

Statement statement;

private

 

 

ResultSet resultSet;

private

 

 

ResultSetMetaData rsMetaData;

// javax.swing types needed for GUI

private

 

 

JTable table;

private

 

 

JTextArea inputQuery;

private

 

 

JButton submitQuery;

public

 

 

DisplayQueryResults()

{

super

 

 

( "Enter Query. Click Submit to See Results." );

// The URL specifying the Books database to which

// this program connects using JDBC to connect to a

// Microsoft ODBC database.

String url =

 

"jdbc:odbc:Books";

String username =

 

"ermanaykac";

String password =

 

"197919";

// Load the driver to allow connection to the database

try

 

 

{

Class.forName(

 

"sun.jdbc.odbc.JdbcOdbcDriver" );

connection

 

 

= DriverManager.getConnection(url, username, password );

}

catch

 

 

( ClassNotFoundException cnfex ) {

System.

 

err.println(

"Failed to load JDBC/ODBC driver."

 

 

);

cnfex.printStackTrace();

System.exit( 1 );

 

// terminate program

}

catch

 

 

( SQLException sqlex ) {

System.

 

err.println( "Unable to connect" );

sqlex.printStackTrace();

System.exit( 1 );

 

// terminate program

}

// If connected to database, set up GUI

inputQuery

 

 

=new JTextArea( "SELECT * FROM Authors", 4, 30 );

submitQuery

 

 

= new JButton( "Submit query" );

submitQuery

 

 

.addActionListener(

new

 

 

ActionListener() {

public void

 

 

actionPerformed( ActionEvent e )

{

getTable();

}

}

);

JPanel topPanel =

 

new JPanel();

topPanel.setLayout(

 

new BorderLayout() );

topPanel.add(

 

new JScrollPane( inputQuery),

BorderLayout.

 

CENTER );

topPanel.add(

 

submitQuery, BorderLayout.SOUTH );

195

table

 

 

= new JTable( 4, 4 );

Container c = getContentPane();

c.setLayout(

 

new BorderLayout() );

c.add( topPanel, BorderLayout.

 

NORTH );

c.add(

 

table, BorderLayout.CENTER );

getTable();

setSize( 500, 500 );

show();

}

private void

 

 

getTable()

{

try

 

 

{

String query =

 

inputQuery.getText();

statement

 

 

= connection.createStatement();

resultSet

 

 

= statement.executeQuery( query );

displayResultSet(

 

resultSet );

}

catch

 

 

( SQLException sqlex ) {

sqlex.printStackTrace();

}

}

private void

 

 

displayResultSet( ResultSet rs )

throws

 

 

SQLException

{

// position to first record

boolean

 

 

moreRecords = rs.next();

// If there are no records, display a message

if

 

 

( ! moreRecords ) {

JOptionPane.showMessageDialog(

 

this, "ResultSet contained no records" );

setTitle(

 

"No records to display" );

return

 

 

;

}

Vector columnHeads =

 

new Vector();

Vector rows =

 

new Vector();

try

 

 

{

// get column heads

ResultSetMetaData rsmd = rs.getMetaData();

for

 

 

( int i = 1; i <= rsmd.getColumnCount(); ++i )

columnHeads.addElement( rsmd.getColumnName( i ) );

// get row data

do

 

 

{

rows.addElement( getNextRow( rs, rsmd ) );

}

 

while ( rs.next() );

// display table with ResultSet contents

table

 

 

= new JTable( rows, columnHeads );

JScrollPane scroller =

 

new JScrollPane( table );

Container c = getContentPane();

c.remove( 1 );

c.add( scroller, BorderLayout.

 

CENTER );

c.validate();

}

196

catch

 

 

( SQLException sqlex ) {

sqlex.printStackTrace();

}

}

private

 

 

Vector getNextRow( ResultSet rs,

ResultSetMetaData rsmd )

throws

 

 

SQLException

{

Vector currentRow =

 

new Vector();

for

 

 

( int i = 1; i <= rsmd.getColumnCount(); ++i )

switch

 

 

( rsmd.getColumnType( i ) ) {

case

 

 

Types.VARCHAR:

case

 

 

Types.LONGVARCHAR:

currentRow.addElement( rs.getString( i ) );

break

 

 

;

case

 

 

Types.INTEGER:

currentRow.addElement(

new

 

 

Long( rs.getLong( i ) ) );

break

 

 

;

default

 

 

:

System.

 

out.println( "Type was: " +

rsmd.getColumnTypeName( i ) );

}

return

 

 

currentRow;

}

public void

 

 

shutDown()

{

try

 

 

{

connection

 

 

.close();

}

catch

 

 

( SQLException sqlex ) {

System.

 

err.println( "Unable to disconnect" );

sqlex.printStackTrace();

}

}

public static void

 

 

main( String args[] )

{

final

 

 

DisplayQueryResults app =

new

 

 

DisplayQueryResults();

app.addWindowListener(

new

 

 

WindowAdapter() {

public void

 

 

windowClosing( WindowEvent e )

{

app.shutDown();

System.exit( 0 );

}

}

);

}

}

Bu web sitesi ücretsiz olarak Bedava-Sitem.com ile oluşturulmuştur. Siz de kendi web sitenizi kurmak ister misiniz?
Ücretsiz kaydol