Docstoc

java oracle

Document Sample
java oracle Powered By Docstoc
					YAZILIM VE VERİTABANI




C# ve T-SQL
Geliştiriciler için Java
ve Oracle
Yalçın Kaya




Editör C. Banu Üçüncüoğlu


                            19-0
C# ve T-SQL Geliştiriciler için Java ve Oracle
Yalçın Kaya




Editör: C. Banu Üçüncüoğlu

Kapak Tasarımı: Melih Sancar

Grafik Tasarım: Tuna Erkan

Grafik Uygulama: Soner Işık

Genel Yayın Yönetmeni: Mehmet Çömlekçi




1. Basım: Şubat 2008

Bilge Adam Yayınları: 21

Eğitim Yayınları Dizisi: 21

ISBN: 978-605-5987-19-0




Copyright © 2007, Bilge Adam Bilgisayar ve Eğitim Hizmetleri San. ve Tic. A.Ş.

Eserin tüm yayın hakları Bilge Adam Bilgisayar ve Eğitim Hizmetleri San. ve Tic. A.Ş.’ye aittir. Yayınevinden yazılı izin
alınmadan kısmen ya da tamamen alıntı yapılamaz, hiçbir şekilde kopya edilemez, çoğaltılamaz ve tekrar yayımlanamaz.
Bilge Adam’ın öğrencilerine ücretsiz armağanıdır, para ile satılamaz.




Bilge Adam Bilgisayar ve Eğitim Hizmetleri San. ve Tic. A.Ş.
19 Mayıs Mahallesi, 19 Mayıs Caddesi, UBM Plaza, No: 59-61, Kat: 4-7; Şişli, İstanbul
Telefon: (212) 272 76 00 – (212) 217 05 55 Faks: (212) 272 76 01
www.bilgeadam.com - info@bilgeadam.com




                          Tanıtım nüshasıdır, para ile satılamaz.
                                                          İçindekiler
Java’ya Giriş��������������������������������������������������������������������������������������������������������������������������������3

    Java Nedir?����������������������������������������������������������������������������������������������������������������������������� 3

                                             �
              Windows Ortamında Java Kurulumu�����������������������������������������������������������������������������3

    Java Uygulamaları Nasıl Çalışır?�������������������������������������������������������������������������������������������� 7

    Basit Veri Tipleri���������������������������������������������������������������������������������������������������������������������� 9

              Ondalıklı Tipler�������������������������������������������������������������������������������������������������������������11

              Mantıksal Tip����������������������������������������������������������������������������������������������������������������11

              Karakter Tipi�����������������������������������������������������������������������������������������������������������������11

              Aritmetik İşlemler ve Taşma�����������������������������������������������������������������������������������������11

    Java’da Operatörler��������������������������������������������������������������������������������������������������������������� 14

              Kaydırma (Shift) İşlemleri���������������������������������������������������������������������������������������������15

              İşlemlerde Parantez Kullanımı�������������������������������������������������������������������������������������16

              Karar Vermek ve Koşullu İfadeler��������������������������������������������������������������������������������16

        �
Döngüler ������������������������������������������������������������������������������������������������������������������������������������23

    While Döngüsü���������������������������������������������������������������������������������������������������������������������� 23

    do Döngüsü��������������������������������������������������������������������������������������������������������������������������� 24

    for Döngüsü��������������������������������������������������������������������������������������������������������������������������� 24

    break ve continue Deyimleri������������������������������������������������������������������������������������������������� 25

Niteleyiciler (Modifiers)�������������������������������������������������������������������������������������������������������������29

    Access Modifiers (Erişim Niteleyicileri)��������������������������������������������������������������������������������� 29
                                            �

              Niteleyicilerde Metod Ezme (Access Modifiers Overriding) ����������������������������������������30

              Diğer Niteleyiciler ��������������������������������������������������������������������������������������������������������30

Casting ve Conversion��������������������������������������������������������������������������������������������������������������35

    Basit Tiplerde Conversion����������������������������������������������������������������������������������������������������� 36

                                              �
              Basit Tiplerde Conversion: Atama�������������������������������������������������������������������������������36

              Basit Tiplerde Conversion: Metod Çağırma�����������������������������������������������������������������38

              Basit Tiplerde Conversion: Aritmetik Yükseltme ���������������������������������������������������������38

              Basit Tiplerde Casting��������������������������������������������������������������������������������������������������39

    Referans Tiplerde Conversion ��������������������������������������������������������������������������������������������� 40
                                 �

              Referans Tiplerde Conversion: Atama ������������������������������������������������������������������������40

                                                           �
              Referans Tiplerde Csonversion: Metod Çağırma  �������������������������������������������������������41
IV   İçindekiler



           Yapısal Programlama����������������������������������������������������������������������������������������������������������������45

                   Yapısal Programlama Nedir?������������������������������������������������������������������������������������������������ 45

                            Nesne Yönelimli Programlamanin Temel Bileşenleri���������������������������������������������������45

                   Nesne Yönelimli Programlamanın Temel Kavramları����������������������������������������������������������� 51

                            Kapsülleme (Encapsulation) ���������������������������������������������������������������������������������������51

           Swing������������������������������������������������������������������������������������������������������������������������������������������67

                   Swing’e Giriş������������������������������������������������������������������������������������������������������������������������� 67

                            JButton�������������������������������������������������������������������������������������������������������������������������68

                                  �
                            JLabel��������������������������������������������������������������������������������������������������������������������������69

                                      �
                            JTextField��������������������������������������������������������������������������������������������������������������������70

                                                      �
                            Event Handling Mekanizması��������������������������������������������������������������������������������������71

                            JTextArea���������������������������������������������������������������������������������������������������������������������74

                            JOptionPane����������������������������������������������������������������������������������������������������������������75

                            JCheckBox�������������������������������������������������������������������������������������������������������������������77

                                        �
                            JRadioButton���������������������������������������������������������������������������������������������������������������79

                                     �
                            JComboBox�����������������������������������������������������������������������������������������������������������������81

                            JList �����������������������������������������������������������������������������������������������������������������������������83

                            Mouse Event’lerinin Yönetilmesi:���������������������������������������������������������������������������������89

                   Klavye Event’lerinin Yönetilmesi������������������������������������������������������������������������������������������� 94

               �
           JDBC ����������������������������������������������������������������������������������������������������������������������������������������103

                   Veritabanı Bağlantısının Kurulması ������������������������������������������������������������������������������������ 108
                                                     �

                   Veri Değiştirme Komutları (insert, update, delete)�������������������������������������������������������������� 109

                   Veri Sorgulama Komutları (Select)�������������������������������������������������������������������������������������� 110

                            Parametreli SQL İfadelerinin Çalıştırılması����������������������������������������������������������������112

                            Stored Procedure’lerin Çalıştırılması�������������������������������������������������������������������������113

              �
           JSP �������������������������������������������������������������������������������������������������������������������������������������������123

                   JSP Teknolojisinde Kullanılan Etiketler������������������������������������������������������������������������������� 128

                                            �
                            JSP Direktifleri�����������������������������������������������������������������������������������������������������������128

                                                 �
                            JSP Script Etiketleri���������������������������������������������������������������������������������������������������129

                   Form Verilerinin Kullanılması���������������������������������������������������������������������������������������������� 129

                   Durum Yönetimi ����������������������������������������������������������������������������������������������������������������� 131
                                  �

           JAVA I/O ����������������������������������������������������������������������������������������������������������������������������������143

                   Dosyalar ve Dizinler ����������������������������������������������������������������������������������������������������������� 143
                                                                                                                                         İçindekiler   



             FilterInputStream Sınıfları������������������������������������������������������������������������������������������145

             FileInputStream ve FileOutputStream Sınıflarının Kullanımı�������������������������������������146

                                         �
             Reader ve Writer Sınıfları: ����������������������������������������������������������������������������������������150

             Standart Giriş-Çıkış Biriminin Kullanılması:���������������������������������������������������������������154

    Java ile Ağ Programlama: �������������������������������������������������������������������������������������������������� 155

Oracle Veritabanı Ailesi����������������������������������������������������������������������������������������������������������161

    Oracle Üzerinde Uygulama Geliştirme�������������������������������������������������������������������������������� 161

             Oracle Veri Tabanı Sisteminin Kurulması������������������������������������������������������������������161

                       �
             Tablespace����������������������������������������������������������������������������������������������������������������167

             Undo Tablespace�������������������������������������������������������������������������������������������������������167

             Oracle’da Veri Tabanı Oluşturmak�����������������������������������������������������������������������������168

             Temel Veri Tipleri�������������������������������������������������������������������������������������������������������179

             Oracle’da Kullanıcı Yönetimi ve Güvenlik������������������������������������������������������������������179

Oracle Üzerinde Programlama�����������������������������������������������������������������������������������������������185

    PL/SQL Nedir?�������������������������������������������������������������������������������������������������������������������� 185

             SQL Plus��������������������������������������������������������������������������������������������������������������������185

             TOAD�������������������������������������������������������������������������������������������������������������������������187

             PL/SQL ile Programlama�������������������������������������������������������������������������������������������189

             PL/SQL’de Kontrol Yapıları����������������������������������������������������������������������������������������191

             PL/SQL’de Alfanümerik Tipler������������������������������������������������������������������������������������201

             PL/SQL’de Mantıksal Tipler���������������������������������������������������������������������������������������207

             PL/SQL’de Tarih ve Zaman Tipleri�����������������������������������������������������������������������������207

             Referans Tipleri����������������������������������������������������������������������������������������������������������213

             LOB (Large Object) Tipleri�����������������������������������������������������������������������������������������216

                                     �
             PL/SQL’de Döngü Yapıları ����������������������������������������������������������������������������������������216
1   Java’ya
    Giriş
1 Java’ya Giriş
• Java Nedir?

• Java Uygulamaları Nasıl Çalışır?

• Basit Veri Tipleri

• Java’da Operatörler
                                     Java’ya Giriş
Bölüm Hedefleri:

    Java platformu üzerinde Java diliyle basit uygulamalar yazmak.
    Temel veri tiplerini tanımak.

Java Nedir?
Java, işlemci mimarisinden ve işletim sisteminden bağımsız olarak tasarlanmış bir platformdur.
Aynı zamanda da bu platform üzerinde uygulama geliştirilen dilin adıdır. Microsoft .NET plat-
formuyla karşılaştırdığımızda .NET platformuna karşılık gelen yapının adı Java olduğu gibi C#
.NET, Visual Basic .NET gibi .NET dillerine karşılık gelen dilin adı da Java’dır. Bu açıklamadan
anlaşılacağı gibi Microsoft .NET platformundan farklı olarak Java platformunda uygulama geliş-
tirilebilecek tek dil vardır. Java platformu pek çok yönden Microsoft .NET platformuna benzediği
gibi Java dili de yetenekleri bağlamında C# diline çok benzer.

Java platformu da Microsoft .NET platformu ve modern nesne yönelimli diller gibi geniş bir sınıf
kütüphanesine sahiptir. Yine .NET platformuna benzer olarak bir Java uygulamasının çalışması
için doğrudan işletim sistemi kullanılmaz. Bu sebeple bir Java uygulaması, işletim sistemine ve
mimari platforma göre geliştirilmiş olan JVM(Java Virtual Machine) aracılığıyla çalıştırılır.

Java ile uygulama geliştirme için kullanılan ortamlar (IDE – Integrated Development Environment),
.NET için kullanılan ortamlara göre çok daha fazla sayıdadır ve kolaylık olarak farklılık gösterir.
Yaygın olarak kullanılan bütünleşik geliştirme ortamlarından (IDE) biri Eclipse’tir. Eclipse’i http://
www.eclipse.org adresinden indirebilirsiniz. Kitaptaki örnekleri gerçekleştirmek için herhangi bir
bütünleşik geliştirme ortamı indirmenize gerek yoktur, bütün örnekleri Windows üzerinde Notepad
ya da herhangi bir metin editörü ile gerçekleştirebilirsiniz.

Windows Ortamında Java Kurulumu
Java platformunu Windows işletimi üzerinde kurmak ve uygulamaları yazabilir hale gelmek için
öncelikle Java Development Kit’i (JDK) bilgisayarınızda kurmalısınız. JDK’nın sürümlerini http://
www.javasoft.com adresinden indirebilirsiniz. İndirdiğiniz dosyayı Windows’un tüm sürümlerinde
kurabilirsiniz.

Kurulumu gerçekleştirdikten sonra Windows ortamında çevre değişkenleri (environment variab-
les) üzerinde işlem yapmamız gerekir. Komut satırında herhangi bir noktadan derleme ve çalış-
tırma programlarını kullanabilmek için Path değişkenine Java’yı kurduğumuz dizinin içindeki bin
dizinini eklemelisiniz.
   Bölüm 1



         Uygulama 1.1:

         Windows XP:

         1� Şekil 1’de gösterilen, Bilgisayarım (My Computer) ikonunu sağ tıklayın. Açılan menüde Özel-
            likler (Properties) öğesini seçin.




                                        Şekil 1


         2. Şekil 2’de gösterildiği gibi, açılan pencerede Gelişmiş (Advanced) sekmesini tıklayın.
         3� Şekil 2’de gösterildiği gibi, gelen pencerede Çevre Değişkenleri (Environment Variables) bu-
            tonuna tıklayın.




                              Şekil 2


         4. Şekil 3’te gösterilen, Sistem Değişkenleri (System Variables) içinde Path’i bulun ve en sonuna
            “;” ekleyin.
                                                                                        Java’ya Giriş   




                       Şekil 3

5. Şekil 4’te olduğu gibi, sonuna da <Java’yi kurduğunuz yer>\<JDKxxx>\bin yazın.




                       şekil 4


Windows Vista:

1� Şeki 5’daki gibi, Bilgisayarım (My Computer) ikonunu sağ tıklayın. Açılan menüde Özellikler
   (Properties) öğesini seçin.




                             Şekil 5
   Bölüm 1



         2. Şekil 6’de gösterilen, Tasks bölümünden Advanced System Settings link’ine tıklayın.




               Şekil 6


         3� Şekil 8’de gösterildiği gibi, gelen pencerede Çevre Değişkenleri (Environment Variables) bu-
            tonuna tıklayın.




                              Şekil 7
                                                                                              Java’ya Giriş   



4. Şekil 8’da gösterildiği gibi, Sistem Değişkenleri (System Variables) içinde Path’i bulun ve en
   sonuna “;” ekleyin.




                        Şekil 8

5. Şekil 9’daki gibi, sonuna da <Java’yi kurduğunuz yer>\<JDKxxx>\bin yazın.




                           Şekil 9


Java Uygulamaları Nasıl Çalışır?
Bir Java uygulamasının makinenizde çalışması için JVM’in kurulu olması gerekir. JVM Microsoft
.NET platformunun IL (Intermediate Language - MSIL) üzerinden çalışması mantığına benzer
bir mantıkla çalışır. Java tarafında IL’e karşılık gelen yapı bytecode’dur. JVM sadece bytecode
üzerinden çalışır. Bu sebeple yazmış olduğunuz Java kaynak kodunu öncelikle Java derleyicisiy-
le derleyerek bytecode’a çevirmelisiniz. Bununla birlikte dikkat edilmesi gereken bir nokta da bir
Java sınıfının derlenebilmesi için kaynak kodu tutan .java uzantılı dosyanın adının, içindeki public
sınıfın adıyla aynı olması gerektiğidir.

Örnek Uygulama 1.1:

       public	class	IlkJavaUygulamasi
      1	
       {
      2	
       	
      3	        public	static	void	main(	String[]	args)
       	
      4	        {
       	
      5	        	        System.out.println(“Ilk	Java	Uygulamasi”);
       	
      6	        }
       }
      7	
   Bölüm 1



         İşlem adımları:

         Örnekleri kolaylık açısından Windows’ta oluşturacağınız bir dizin içinde toparlamanız faydalı ola-
         caktır.

         1� Yukarıdaki kodu herhangi bir metin editöründe yazın ve “IlkJavaUygulamasi.java” adıyla kay-
            dedin.
         2. Command Prompt’u açın.
         3� Dosyayı kaydettiğiniz dizine girin.
         4. javac IlkJavaUygulamasi.java ifadesini çalıştırın.
         5. Eğer hata almazsanız IlkJavaUygulamasi.class dosyasının kaynak kodla aynı yerde oluştu-
            ğunu görmelisiniz.
         6. Java IlkJavaUygulamasi ifadesini çalıştırdığınızda komut satırında “Ilk Java Uygulamasi” ifa-
            desini görmelisiniz.
         Uygulamanın açıklaması: 1 numaralı satırda C#’ta olduğu gibi IlkJavaUygulamasi adında bir
         sınıf tanımlanır. Java dilinde de, C#’ta olduğu gibi kod blokları sınıfların içinde yer almalıdır. 2
         numaralı ve 4 numaralı satırlarda “{“ (küme parantezi, curly brace) işareti aynen C#’ta olduğu gibi
         blok başı işaretidir. 2 numaralı satırdaki “{“ sınıf için tanımlanan bloğun başlangıcıyken 4 numaralı
         satırdaki “{“ işareti de main metodunun başlangıcıdır.
         6 numaralı ve 7 numaralı satırlardaki “}” işareti blok sonu işaretidir. 6 numaralı satırdaki “}” işareti
         main bloğunun sonuyken, 7 numaralı satırdaki “}” işareti sınıf için açılan bloğun sonudur.
         Blok başı ve blok sonu ifadelerinde dikkat etmeniz gereken en önemli nokta son açılan blok her
         zaman ilk kapatılan bloktur ve her açılan blok mutlaka kapatılmalıdır.
         3 numaralı satırda aynen C#’ta olduğu gibi main metodunun tanımını görebilirsiniz. public
         static void ifadelerinin anlamları C# ile aynı olmakla birlikte daha sonra detaylı olarak ince-
         lenecektir. Main metodunun parametresi olan String[] args de metodun parametre olarak
         bir String dizisi aldığını belirtir. Main metodu, Java’da da konsol uygulamalarının otomatik olarak
         çalışan ilk metodudur.
         5 numaralı satırda main metodu çalıştığında ne yapacağını gösterir. System.out.println();
         ifadesi C#’taki Console.WriteLine() ifadesine karşılık gelir. Burada System.out standart
         çıktı birimini temsil eder. Varsayılan olarak kullandığınız ekrandır. println() metodu, kendisine
         parametre olarak verilen ifadeye yazar ve sonundaki “ln” (line) kısmından dolayı bir satır aşağıya
         geçer. İfadenin sonundaki “;” işareti Java’da da C#’taki her ifadenin sonunda mutlaka bulunması
         gereken satır sonlandırıcısıdır.
         Bu basit uygulamaya bakarak C# dili ile Java dilinin birbirine pek çok noktada benzediğini gö-
         rebilirsiniz. Bundan sonraki pek çok aşamada C# dili ile Java dili arasındaki benzerliklere tanık
         olacaksınız.
         İlk uygulamada konsola System.out.println() yazdırdığımız ifadeyi bir mesaj kutusunda
         yazdırmak istersek bir miktar değişiklik yapmamız gerekecektir.
         Örnek Uygulama 1.2a:

                public	class	MesajKutusu
               1	
                {
               2	
                			public	static	void	main(	String[]	args)
               3	
                			{
               4	
                	
               5	          javax.swing.JOptionPane.showMessageDialog(null,	“Ilk	Java		
               		          Uygulamasi”);
                			}
               6	
                }
               7	
                                                                                                          Java’ya Giriş   



Uygulamanın açıklaması: Bu uygulamanın 5 numaralı satırı dışındakiler önceki uygulamadan
farklı değildir. 5 numaralı satırda da C#’taki MessageBox.Show() metodunun Java’daki benzeri
olan JoptionPane.showMessageDialog() metodu kullanılmıştır. Bu kodun başındaki ja-
vax.swingdeJOptionPane sınıfının içinde bulunduğu pakettir. Java’daki paketleri .NET’teki
assembly’ler gibi düşünebilirsiniz. Dolayısıyla C#’taki using ifadesinin karşılığı olarak import
ifadesini kullanarak kodumuzu aşağıdaki şekilde güncelleyebiliriz.

Örnek Uygulama 1.2b:

        import	javax.swing.JOptionPane;
       1	
        public	class	MesajKutusu
       2	
       {
      3	
       	
      4	         public	static	void	main(	String[]	args)
       	
      5	         {
       	
      6	         	        JOptionPane.showMessageDialog(null,	“Ilk		Java			
      		         	        Uygulamasi”);
       	
      7	         }
       }
      8	

Bu örnekte 1 numaralı satırdaki import ifadesi javax.swing paketindeki JOptionPane sınıfı-
nın yüklenmesini sağlar. Bir kere yüklendikten sonra tekrar paket adının kod içinde kullanmamıza
gerek kalmaz. Burada yapılan yükleme işlemi, .NET’teki gibi, yüklenen paketin içerdiği kodu,
oluşturulan .class dosyasının içine eklemez, sadece o pakete erişimi sağlayacak kodu oluşturur.

Uygulama 1.2b’deki 6 numaralı satırda JOptionPane sınıfının                 Java’da comment’lerin kullanı-
showMessageDialog metodunun ilk parametresi swing paketi-                   mı C# ile aynıdır. // Satır com-
                                                                            ment. /* */ Blok comment.
nin detaylarına gelene kadar sürekli null olarak kullanılacaktır. 2.
parametre de tahmin edebileceğiniz gibi mesaj kutusunda yazdırı-
lacak ifadedir.


Basit Veri Tipleri
Java’daki basit (primitive)veri tipleri .NET’teki basit veri tipleriyle çok benzerdir. Herhangi bir veri
tipinin tanımlanması C#’takinden farklı değildir. Bununla birlikte Java’daki sayısal tiplerin hepsi
işaretlidir (signed – hem negatif hem de pozitif sayıları tutar), işaretsiz veri tipi yoktur. Öncelikle
tam sayısal veri tiplerinden başlayalım:

byte: Adından da anlaşılabileceği gibi 1 byte’lık, tam sayı tutan veri tipidir. C#’ta sbyte’a, .NET
CTS’te System.SByte’a karşılık gelir. Herhangi bir byte değişken tanımlaması aşağıdaki şe-
killerde yapılabilir:

      byte yas; //ilk değer verilmeden.
      byte yas = 67; //ilk değer verilerek.

short: 2 byte’lık, tam sayı tutan veri tipidir. C#’ta short’a, .NET CTS’te System.Int16’ya
karşılık gelir. Herhangi bir short değişken tanımlaması aşağıdaki şekillerde yapılabilir:

      short derinlik; //ilk değer verilmeden.
      short derinlik = 23245; //ilk değer verilerek.

int: 4 byte’lık, tam sayı tutan veri tipidir. C#’ta int’e, .NET CTS’te System.Int32’ye karşılık
gelir. Herhangi bir int değişken tanımlaması aşağıdaki şekillerde yapılabilir:
10   Bölüm 1



                int sayi; //ilk değer verilmeden.
                int sayi = 12; //ilk değer verilerek.

          long: 8 byte’lık, tam sayı tutan veri tipidir. C#’ta long’a, .NET CTS’te System.Int64’e karşılık
          gelir. Herhangi bir long değişken tanımlaması aşağıdaki şekillerde yapılabilir:

                long GNP; //ilk değer verilmeden
                long GNP = 1234567890; //ilk değer verilerek

          Bunların dışında basit veri tipi olmamakla birlikte şu aşamada bilmeniz gereken bir veri tipi daha
          var: String�String tipi referans üzerinden çalışan bir veri tipidir. Yani, aslında basit veri tip-
          lerinden farklı olarak bir nesne üzerinden çalışırlar; fakat tanımlaması şu ana kadar bahsedilen
          veri tiplerinden farklı değildir. String’in detaylarına ilerleyen bölümlerde değineceğiz. Burada
          dikkat etmemiz gereken nokta Java’da küçük harf “s” ile başlayan string tanımının olmamasıdır.
          Herhangi bir String veri tanımlaması aşağıdaki şekillerde yapılabilir:

                String Ad; //ilk değer verilmeden
                String Ad = “Yalcin”; //ilk değer verilerek

          Artık kullanıcıdan 2 sayı alıp bunları matematiksel herhangi bir işlem içinde kullanabilecek hemen
          her şeye sahibiz. Tek eksiğimiz bu sayıları kullanıcıdan nasıl alacağımız. Matematiksel işlemlerin
          nasıl yapıldığına gelirsek, ileride farklılıklarına değineceğemizi belirterek C#’taki yazılışlarından
          şu an için hiçbir farkı yoktur diyebiliriz. Şimdi bunu örnekleyelim:

          Örnek Uygulama 1.3:

                 import	javax.swing.JOptionPane;
                1	
                 public	class	MesajKutusu
                2	
                 {
                3	
                 	
                4	         public	static	void	main(	String[]	args)
                 	
                5	         {
                 	
                6	         	       String	birinciSayi,	ikinciSayi;
                 	
                7	         	       int	toplam,	sayi1,	sayi2;
                 	
                8	         	       birinciSayi	=	JOptionPane.showInputDialog(“Birinci		
                		         	       sayiyi	giriniz:”);
                 	
                9	         	       ikinciSayi	=	JOptionPane.showInputDialog(“Ikinci		
                		         	       sayiyi	giriniz:”);
                10	        	       sayi1	=	Integer.parseInt(birinciSayi);
                11	        	       sayi2	=	Integer.parseInt(ikinciSayi);
                12	        	       toplam	=	sayi1	+	sayi2;
                13	        	       JOptionPane.showMessageDialog(null,	toplam);
                14	        }
                15}

          Kod Açıklaması: 6 numaralı satırda String tipinde 2 değişken tanımlanmıştır. Unutmayın ki bu
          2 değişken de basit veri tipi değil referans tipli değişkenlerdir. Bu değişkenler JOptionPane sını-
          fının showInputDialog metodunun döndürdüğü değerleri tutmak için kullanılmıştır. 7 numaralı
          satırda 3 tane tam sayı tanımlanmıştır. toplam adlı değişken JOptionPane.showInputDia-
          log() metoduyla aldığımız değerlerin sayıya dönüştürülmüş hallerini toplamak için kullanılmış-
          tır. sayi1 ve sayi2 değişkenleri de JOptionPane.showInputDialog() metoduyla aldığımız
                                                                                              Java’ya Giriş   11



değerlerin sayıya dönüştürülmüş hallerini tutacaktır. 8 ve 9 numaralı satırlarda JOptionPane.
showInputDialog() metodlarıyla, yukarıda tanımladığımız String’lerin içine, kullanıcının gi-
receği değerler alınmaktadır. Burada dikkat etmemiz gereken nokta, rakamlar dışında değerler
girdiğimizde 10 ve 11 numaralı satırlarda dönüştürme hatasıyla karşılaşma durumumuzdur. Bu
satırlarda kullanıcı tarafından girilmiş olan String’ler Integer sınıfının parseInt() aracılı-
ğıyla int’e çevrilmeye çalışılır.Integer sınıfı .NET’teli System.Int32 sınıfına karşılık gelen
sınıftır ve terimsel olarak wrapper class olarak geçer. parseInt() metodu da Int32 sınıfının
Parse() metoduyla aynı şekilde çalışır. Eğer kendisine gönderilen parametre int’e çevrilemi-
yorsa “NumberFormatException” oluşturur. Bunun için de C#’taki gibi istisna yönetimi (excep-
tion handling), yani try-catch-finally bloklarını kullanabiliriz.

10 ve 11 numaralı satırlarda eğer herhangi bir exception oluşmazsa, yani bir int’in alabileceği
değer aşılmazsa 12 numaralı satır çalışır. Eğer 2 değerin toplamı bir int’in alabileceği en büyük
değeri aşıyorsa toplam değişkeninin alacağı değer negatif bir sayıya dönecektir. Çünkü Java, C
geleneğinden dolayı sayıları kontrol etmez. Bu durumu daha küçük bir tam sayı tipi olan byte
üzerinden Uygulama 1.4’te açıklayacağım.

13 numaralı satırda bir önceki örnekte kullandığımız JOptionPane.showMessageDialog()
metoduyla toplam değişkeninin değerini yazdırıyoruz. Sınıf adıyla kullanılması sebebiyle show-
MessageDialog() metodunun JOptionPane sınıfının static bir metodu olduğunu anlaya-
bilirsiniz.

Ondalıklı Tipler
double: 8 byte’lık ondalıklı veri tipidir. Tanımlandığı standart (IEEE 754) çerçevesinde yük-
sek doğruluk isteyen işlemlerde kullanılmamalıdır; ancak ondalıklı kısımda yüksek yoğunluk çok
önemli değilse kullanılabilir. C#’ta float’a, .NET CTS’te System.Single’a karşılık gelir.

float: 4 byte’lık ondalıklı veri tipidir. Hem tanımlandığı standart çerçevesinde hem de double
veri tipine göre daha küçük bir veri tipi olması sebebiyle yüksek doğruluk isteyen işlemlerde kulla-
nılmamalıdır; ancak ondalıklı kısımda yüksek yoğunluk çok önemli değilse kullanılabilir. Eğer bel-
lek yetersizliği ile ilgili bir problem yoksa float yerine double tercih edilmelidir. C#’ta double’a,
.NET CTS’te System.Double’a karşılık gelir.

Her 2 ondalıklı veri tipinin yerine java.math paketinde bulunan BigDecimal sınıfı kullanılabi-
lir.

Mantıksal Tip
boolean:true ya da false değerlerinde birini taşıyabilen basit veri tipidir. Taşıdığı veri sade-
ce 1 bit ile gösterilebiliyor olsa da kapladığı alan 1 bit değildir. C#’ta bool’a, .NET CTS’te Sys-
tem.Boolean’a karşılık gelir.

Karakter Tipi
char: 2 byte’lık Unicode karakter olarak herhangi bir karakter bilgisini tutmak için kullanılır. C
ailesi geleneğinden dolayı işaretsiz tam sayısal veri tipi olarak değerlendirilebilir. C#’ta char’a,
.NET CTS’te System.Char’a karşılık gelir.

Aritmetik İşlemler ve Taşma
Java’da tam sayısal aritmetik işlemler, işleme giren değerlerin tipleri eğer birer int değilse int’e
dönüştürülerek yapılır. Eğer işleme giren tiplerden en az biri long ise long’a dönüştürülerek
yapılır.

Eğer tipler ondalıklı ise işlemler, işleme giren tipler double’a dönüştürülerek yapılır. Dolayısıyla
aşağıdaki örnekleri dikkatle incelemek gereklidir:
12   Bölüm 1



          Örnek Uygulama 1.4a:

                 public	class	TipDonusumleri1
                1	
                 {
                2	
                 	
                3	        public	static	void	main(	String[]	args)
                 	
                4	        {
                 	
                5	        	        byte	sayi1	=	120;
                 	
                6	        	        byte	sayi2	=	110;
                 	
                7	        	        byte	toplam	=	sayi1	+	sayi2;
                 	
                8	        }
                 }
                9	

          Bu örnekte 7 numaralı satırda sayi1 + sayi2 ifadesi, işlem int üzerinden yapıldığından çalı-
          şacaktır; ancak toplam değişkeninin tipi byte olduğu için derlenemeyecektir ve possible loss of
          precision (değer kaybı ihtimali) hatası verecektir. Bunun sebebi toplanan byte tipindeki değiş-
          kenlerin değerlerinin toplamının, byte tipindeki bir alana sığmaması değildir. (120 + 110 = 230,
          byte tipinin alabileceği en büyük değer ise 127’dir). Bunu sayi1’in değerini 12, sayi2’nin değerini
          11 yaparak görebilirsiniz. Possible loss of precision hatasını bu durumda da alacaksınız. (12 +
          11 = 23, byte tipinin içine sığar). Dolayısıyla bu hatanın sebebi, sayi1 + sayi2 işleminin int üze-
          rinden yapılmasıdır. Bunu anlamak için 7 numaralı satırda tanımlanan toplam değişkeninin tipini
          byte’tan short’a çevirip tekrar derleyerek de görebilirsiniz. Bu durumda 120 ile 110’un toplamı
          olan 230 değeri short tipine sığacak bir değer olmasına rağmen possible loss of precision ha-
          tasını yine alırsınız; ancak toplam değişkeninin değerini int ya da long yaparak bu hatadan
          kurtulabilirsiniz.

          Uygulama 1.4a örneği üzerinde düşündüğümüzde yapılan işlem anormal gelmemelidir. Çünkü
          burada 2 tane byte tipli değişkenin toplamının değerinin byte tipine sığmaması ihtimali yük-
          sektir. Bu durumda, eğer bu işlemi byte tipi üzerinden gerçekleştirmek istersek ne yapmalıyız?
          Bunun cevabını da Uygulama 1.4b’de görebilirsiniz.

          Örnek Uygulama 1.4b:

                 public	class	TipDonusumleri2
                1	
                 {
                2	
                 	
                3	        public	static	void	main(	String[]	args)
                 	
                4	        {
                 	
                5	        	        byte	sayi1	=	12;
                 	
                6	        	        byte	sayi2	=	11;
                 	
                7	        	        byte	toplam	=	(byte)(sayi1	+	sayi2);
                 	
                8	        	        System.out.println(toplam);
                 	
                9	        }
                10}

          Örnek Uygulama 1.4b’de 7 numaralı satırda yaptığımız işlem bir explicit cast (göstererek dönüş-
          türme) işlemidir. Uygulama 1.4a’da int’e dönüştürme ise implicit cast (gizli dönüştürme) işlemi
          olarak adlandırılır. Daha sonra bu işlemleri farklı isimlerle tekrar değerlendireceğiz. Burada sayi1
          + sayi2 işlemi önce yine int üzerinden yapılır ve sonra byte’a dönüştürme yapılır. Bu şekilde
          12 ile 11’in toplamı olan 23 değerini byte olarak elde edebilirsiniz. Buraya kadar herşey gü-
          zel; ancak bu noktada Uygulama 1.3’deki taşma problemimize geri dönelim ve 5 ve 6 numaralı
          satırlarda tanımladığımız byte tipli değişkenlerimizin değerlerini sırasıyla 120 ve 110 yapalım.
          Yeni değerlerin her ikisi de byte tipine sığabilirler; fakat toplamları olan 230 değeri byte tipine
                                                                                                   Java’ya Giriş   13



sığmaz. Java uygulaması bu durumda hata vermeyecektir ve 8 numaralı satırdaki System.out.
println()’den dolayı konsola -26 yazacaktır. Bunu detayıyla şu şekilde açıklayabiliriz:

Bildiğiniz gibi güncel bilgisayar sistemleri 2’lik (binary) sistemle çalışırlar, yani herşey 1 ve 0 ile
ifade edilir. Dolayısıyla sayi1 ve sayi2 değişkenlerimizin 2’lik sistemdeki karşılıkları şu şekildedir:

       sayi1	=	120	=	(01111000)2
       sayi2	=	110	=	(01101110)2

Sayıların 2’lik sistemdeki karşılıklarının başındaki 0, byte tipinin 1 byte’lık yani 8 bitlik olma-
sından dolayı sayıyı 8 bite tamamlamak içindir; ancak en başa eklediğimiz bu 0’ın taşıdığı çok
daha farklı bir anlam vardır, Bu ilk değer sayının pozitif ya da negatif olmasını belirler. Eğer 0 ise
arkasından gelen tüm bitler pozitif sayıya göre yorumlanacaktır, eğer 1 ise negatif sayıya göre
yorumlanacaktır. Şimdi de sayıları toplayalım:

       sayi1	+	sayi2	=	120	+	110	=	230
       sayi1	+	sayi2	=	(01111000)2	+	(01101110)2	=	(11100110)2
       toplam	=	(11100110)2

Az önce bahsettiğimiz işaret biti durumundan dolayı 2’lik sayının en başındaki değer olan 1, ge-
risindeki 7 bitin negatif sayıya göre yorumlanacağını gösterir. Dolayısıyla Java’da tamsayıların
tümünde sayı değeri en soldaki bitin pozitif ya da negatif olması durumu netleştikten sonra ortaya
çıkar. Örnek olarak şu sayıları ele alalım:

       5	=	(00000101)2

En baştaki 0 sayının pozitif olduğu anlamına gelir. Devamındaki 0000101’de de ilk 1’e kadar olan
0’ların bir anlamı yoktur. Böylece elimizde (101)2 kalır. Bunun da karşılığı 10’luk sistemde 5’tir.
Açılımı ise şu şekildedir.

       1	x	20	=	1
       0	x	21	=	0
       1	x	22	=	4
       1	+	0	+	4	=	5

Bu noktadan sonra eğer sayımız negatif ise durumun değiştiğini göreceğiz. Örnek olarak -1’i ele
alacağız.

Eğer 1 = (00000001)2 ise; -1 = (11111110)2 + (00000001)2’dir. Yani (11111111)2’dir. Bu yönteme
2’nin tamlayanı yöntemi denir. (11111110)2 de (00000001)2’nin bire tamlayanıdır. Burada niçin bu
kadar dolandırılmış diye düşünebilirsiniz; ancak unutmayın ki gündelik hayatta kullandığımız gibi
bir “-” işaretine sahip değiliz. Bu durumu -1 ile 1’i toplayarak deneyelim:

       (00000001)2		+	(11111111)2	=	(100000000)2

Elimizde 9 bitlik bir veri oluştu; ancak byte veri tipi 8 bitlik bir veri tipiydi. Bu durumda en baştaki
1 değeri hiçbir değerlendirmeye katılmadan son 8 bit değerlendirilir; yani (00000000)2 değeri kul-
lanılır. Burada ilk bit 0 olduğu için sayı pozitiftir diyebiliriz. Geri kalan 7 bit de 0 olduğu için sayı
10’luk sistemdeki 0’a karşılık gelir. Bu durumda aklınıza takılabilecek olan soru 0’ın pozitifliği ya
da negatifliği olabilir. 0 sayısı matematikte ne pozitif tam sayılar kümesinin ne de negatif tamsayı-
lar kümesinin bir üyesidir; ancak programlama dillerinde 0 değeri pozitiftir.
14   Bölüm 1



          Sonuç olarak bilgisayar için negatif bir sayının 2’lik sistemde nasıl yazıldığını bulmak istiyorsak şu
          şekilde bir işlem gerçekleştirmeliyiz:

          Sayıyı 2’lik sistemde pozitif olarak yazın.

          Oluşan sayıdaki 0’ları 1, 1’leri 0 yapın.

          Sayıya 2’lik sistemde 1 ekleyin.

          Örnek olarak -5’e ulaşmaya çalışalım:

                     5	=	(00000101)2
                     1’	e	tamlayan	=	(11111010)2
                     2’ye	tamlayan	=	(11111011)2

          Böylece Uygulama 1.4b’nin açıklamasında elde ettiğimiz (11100110)2 değerini irdeleyebilir duru-
          ma geldik. Yukarıdaki işlemi tersten yaptığınızda da sayıya ulaşabilirsiniz.

                     (11100110)2	–	(00000001)2	=	(11100101)2
                     1’e	tamlayan	=	(00011010)2
                     (00011010)2	=	26

          Dolayısıyla elimizdeki sayı 10’luk sistemdeki -26’ya karşılık gelir. Bu detayları bilmemeniz halinde
          basit bir sayısal problem üzerinde çok zaman harcayabilirsiniz. Çünkü gördüğünüz şekilde Java
          aritmetik işlemlerde taşan sayılar için hata vermez.


          Java’da Operatörler
          Java’da tipler üzerinde işlem yapmak için pek çok operatör bulunur. Bu operatörlerin çoğu C#’ta
          da aynı şekilde mevcuttur.

          Öncelik Sırası
           Öne gelen (prefix)                   ++ifade, --ifade
           Sona gelen (postfix)                 ifade++, ifade--
           Tek ifade alan                       +ifade, -ifade, ~, !
           Çarpımsal                            *, /, %
           Toplamsal                            +, -
           Kaydırma                             <<, >>, >>>
           İlişkisel                            <, >, <=, >=, instanceof
           Eşitlik                              ==, !=
           Bit üzerinde (bitwise) VE (AND)      &
           Bit üzerinde özel VEYA (EX-OR)       ^
           Bit üzerinde VEYA (OR)               |
           Mantıksal VE (AND)                   &&
           Mantıksal VEYA (OR)                  ||
           Üçlü ifade alan (ternary) operatör   ?:
           Atama                                =, +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=, >>>=
                                                                                                   Java’ya Giriş   15



Gördüğünüz gibi Java’daki birkaç operatör dışında hemen hemen tüm operatörler C# ile aynıdır.
Bit üzerinde işlem yapan operatörler kestirmeli (shortcut) operatörlerdir. Yani operandlarından
(işleme giren değerlerinden) biri işlemin sonucunu kesin olarak ortaya koyuyorsa işlemin deva-
mındaki operand değerlendirilmez.

Örnek Uygulama 1.5a:

        public	class	Operatorler1
       1	
       {
      2	
       	
      3	         public	static	void	main(	String[]	args)
       	
      4	         {
       	
      5	         	        int	sayi,	sonuc;
       	
      6	         	        sayi	=	5;
       	
      7	         	        sonuc	=	sayi++	+	++sayi;
       	
      8	         	        System.out.println(sonuc);
       	
      9	         	        System.out.println(sayi);
      10	        }
      11}

Bu uygulamada 8 ve 9 numaralı satırlar işlendiğinde ekranda yazacak değerlerin ne olduğunu ve
7 numaralı satırın nasıl işlediğine bakalım. 6 numaralı satırda sayi değişkeninin değeri 5 yapıl-
dıktan sonra 7 numaralı satırda sonuc = sayi++ + ++sayi; ifadesi işletilmektedir. Bu satırı
daha detaylı inceleyelim:

sonuc = sayi++ + ++sayi; ifadesinde önce ++sayi ifadesi çalışacaktır ve sayi değişke-
nine 1 ekleyerek değerini 6 yapacaktır. Daha sonra sayi++ işlemeden sayi değeri ile artırılmış
sayi değerleri toplanarak sonuc değişkenine atama yapılacaktır. Böylece 6 + 6 = 12 değeri so-
nuc değişkeninin değeri olur. Bu atama yapıldıktan sonra sayi değişkenine sayi++’dan dolayı
tekrar 1 eklenecektir ve sayi değişkeninin değeri 7 olacaktır.

Kaydırma (Shift) İşlemleri
Kaydırma işlemleri genellikle sistem programlama, oyun programlama gibi uzmanlık gerektiren
alanlarda kullanılır. Değerimizi temsil eden 2’lik sayı sistemindeki değeri sağa ya da sola belirti-
len bit sayısı kadar kaydırır ve kaydırılan alanlara 0 değerini koyar. İşaret bitiyle ilgili detayları da
vardır. Bu sebeple bir örnekle gösterip detaylı olarak anlatmayacağım.

Örnek Uygulama 1.5b:

        public	class	Operatorler2
       1	
       {
      2	
       	
      3	         public	static	void	main(	String[]	args)
       	
      4	         {
       	
      5	         	        int	sayi;
       	
      6	         	        sayi	=	5;
       	
      7	         	        sayi	<<=	2;
       	
      8	         	        System.out.println(sayi);
       	
      9	         }
      10}

Bu örnekte 7 numaralı satırda sayi değişkeninin bitleri 2 kademe sola kaydırılmaktadır. Bu işlem
nasıl yapılıyor inceleyelim:
16   Bölüm 1



          int 32 bit (4 byte) olduğu için 2’lik sayı sisteminde aşağıdaki gibi gösterilir.

                sayi	=	5	=	00000000	00000000	00000000	00000101

          Bu değer sola 1 bir kaydırıldığında;

                sayi	=	0	00000000	00000000	00000000	00001010	=	10

          değeri elde edilir. En baştaki 0 düşen bittir, ve en sondaki 101 değerleri sola kaydırılarak en sona
          da 1 tane 0 eklenmiştir.

          sayi <<= 2 ifadesi sola doğru 2 bitlik kaydırma işlemi olduğu için sayi 1 bit daha sola kaydırıl-
          malıdır.

                sayi	=	00	00000000	00000000	00000000	00010100	=	20

          Böylece sayi değişkeninin değeri 20 olur. Dikkat ederseniz sola kaydırma 2 ile çarpma gibidir.

          İşlemlerde Parantez Kullanımı
          Matematiksel ya da mantıksal işlemlerde parantezlerin içine alınan ifadelerin önceliği ilk sıraya çı-
          kar. Matematik bilgimizden tek farkı kullandığımız tek işaretin sadece normal parantez olmasıdır,
          köşeli parantez ya da küme parantezi kullanılmaz.

          Örnek: Bu ifadeyi matematiksel olarak yazmak istediğimizde eğer;

                d	=	m	*	P	/	n	*	r	*	T;

          şeklinde yazarsak çarpma ve bölmenin önceliklerinin aynı olması sebebiyle işlem soldan sağa
          sırayla gerçekleşecektir. Böyle olunca m ile P çarpıldıktan sonra n ile bölünecek, bunun sonucu
          da r ile T’nin çarpımıyla çarpılacaktır. Oysa ifadenin gösterdiği m ile P’nin çarpımının n, r ve T’nin
          çarpımına bölünmesi şeklindedir. Bu sebeple bu matematiksel ifadeyi;

                d	=	m	*	P	/	(n	*	r	*	T);

          şeklinde yazmalıyız.

          Karar Vermek ve Koşullu İfadeler
          Java’da da C#’taki gibi karar verme ve koşullu ifade yazmak için 2 ifade ve 1 operatör söz konu-
          sudur. Bunlar:

          1� if...else
          2. Üçlü ifade alan operatör (? :)
          3� switch...case

          if...else Yapısı
          if... else yapısı Java’da da aynen C#’taki gibi kullanılır. En basit yapısı sadece if’in kullanıldığı
          şeklidir. Koşullu ifadelerde dikkat edilmesi gereken nokta koşulun sonucunun true ya da false,
          yani boolean bir ifade üretmesi gerekliliğidir. Bu yönüyle C geleneğiyle farklılaşır.
                                                                                                  Java’ya Giriş   17



Örnek Uygulama 1.6a:

       import	javax.swing.JOptionPane;
      1	
       public	class	Kosul1
      2	
       {
      3	
       	
      4	         public	static	void	main(	String[]	args)
       	
      5	         {
       	
      6	         	       int	sayi1	=	Integer.parseInt(JOptionPane.		                          	
                         showInputDialog(“Birinci sayıyı giriniz”));
       	
      7	         	       int	sayi2	=	Integer.parseInt(JOptionPane.		                          	
                         showInputDialog(“Ikinci sayıyı giriniz”));
       	
      8	         	       if(	sayi1	<	sayi2)
       	
      9	         	       {
      10	        	       	        JOptionPane.showMessageDialog(null,	sayi1	+	
      		         	       	        “	kucuktur	“	+	sayi2);
      11	        	       }
      12	        }
      13}
8 numaralı satırda yapılan karşılaştırmanın sonucu, yani sayi1 değişkeninin değerinin sayi2 değiş-
keninin değerinden küçük olma durumu true ya da false, daha genel bir ifadeyle boolean bir so-
nuç üretir. Eğer karşılaştırmanın sonucu true ise if bloğunun içi çalıştırılır, if bloğu sonlandığında
da akış kaldığı yerden devam eder; aksi takdirde if bloğunun içi çalıştırılmadan programın akışı if
bloğu yokmuş gibi çalışmaya devam eder. Koşullar gibi bir sonraki bölümde inceleyeceğimiz döngü ve
tekrarlı yapılarda da kodun okunurluğunu artırmak için if bloğunun içi tek ifadeden oluşsa bile blok
parantezlerini, tek ifade için şart olmamasına rağmen kullanmayı alışkanlık haline getirin.
Örnek Uygulama 1.6b:

       import	javax.swing.JOptionPane;
      1	
       public	class	Kosul2
      2	
       {
      3	
       	
      4	         public	static	void	main(	String[]	args)
       	
      5	         {
       	
      6	         	       int	sayi1	=	Integer.parseInt(JOptionPane.		                          	
                         showInputDialog(“Birinci sayıyı giriniz”));
       	
      7	         	       int	sayi2	=	Integer.parseInt(JOptionPane.		                          	
                         showInputDialog(“Ikinci sayıyı giriniz”));
       	
      8	         	       if(	sayi1	<	sayi2)
       	
      9	         	       {
      10	        	       	        JOptionPane.showMessageDialog(null,	sayi1	+	
      		         	       	        “	kucuktur	“	+	sayi2);
      11	        	       }
      12	        	       else	if(	sayi1	>	sayi2)
      13	        	       {
      14	        	       	        JOptionPane.showMessageDialog(null,	sayi1	+	
      		         	       	        “	buyuktur	“	+	sayi2);
      15	        	       }
      16	        }
      17}
18   Bölüm 1



          Bu örnekteki çalışma şekli Uygulama 1.6a’dakiyle aslında aynı şekildedir. Eğer 8 numaralı satır-
          daki karşılaştırma true sonuç vermezse akış 12 numaralı satırdan devam edecektir. Bu blok da
          else bloğudur. else bloğu aslında if bloğundan sonraki akışın ilk parçasıdır. else bloğunda
          bir karşılaştırma daha yapılmaktadır. Bu karşılaştırmada da aynen 8 numaralı satırdaki if bloğu
          gibi bir çalışma mekanizması söz konusudur. Eğer karşılaştırma sonucu true ise else bloğu ça-
          lışır; aksi takdirde else bloğundan sonraki noktadan; yani 16 numaralı satırdan itibaren çalışma
          devam eder. Bu uygulamada, Örnek Uygulama1.6a’ya göre farklılaşan tek nokta eğer 8 numaralı
          satırdaki karşılaştırma true sonuç üretirse 12 numaralı satırdaki else bloğu, her ne kadar ken-
          dinden sonra gelen ilk ifade olsa da çalışmaz.

          Örnek Uygulama 1.6c:

                 import	javax.swing.JOptionPane;
                1	
                 public	class	Kosul3
                2	
                 {
                3	
                 	
                4	        public	static	void	main(	String[]	args)
                 	
                5	        {
                 	
                6	        	        int	sayi1	=	Integer.parseInt(JOptionPane.		     	
                                   showInputDialog(“Birinci      sayıyı giriniz”));
                 	
                7	        	        int	sayi2	=	Integer.parseInt(JOptionPane.		     	
                                   showInputDialog(“Ikinci       sayıyı giriniz”));
                 	
                8	        	        if(	sayi1	<	sayi2)
                 	
                9	        	        {
                10	       	        	       JOptionPane.showMessageDialog(null,	sayi1	+	
                		        	        	       “	kucuktur	“	+	sayi2);
                11	       	        }
                12	       	        else	if(	sayi1	>	sayi2)
                13	       	        {
                14	       	        	       JOptionPane.showMessageDialog(null,	sayi1	+	
                		        	        	       “	buyuktur	“	+	sayi2);
                15	       	        }
                16	       	        else
                17	       	        {
                18	       	        	       JOptionPane.showMessageDialog(null,	sayi1	+	
                		        	        	       “	esittir	“	+	sayi2);
                19	       	        }
                20	       }
                21}

          Bu uygulamada değişen tek nokta 16 numaralı satırdaki koşulu olmayan else bloğudur. Böylece
          sayi1 değişkenin değeri ile sayi2 değişkeninin değeri arasında yapılan karşılaştırmada durum
          ne olursa olsun, bir exception üretilmediği sürece, bu 3 bloktan birinin çalışması kesindir. 16 nu-
          maralı satırdaki else bloğunun çalışması için 8 ve 12 numaralı satırlardaki karşılaştırmalardan
          false üretilmesi gerekir. Bu örnekte bu durum 2 sayıyı karşılaştırırken, iki sayının birbirine eşit
          olması durumudur. Bu bloklardan hangisi çalışırsa çalışsın, akış 20 numaralı satırdan devam
          edecektir.
                                                                                              Java’ya Giriş   19



Örnek Uygulama 1.6d:

       import	javax.swing.JOptionPane;
      1	
       public	class	Kosul4
      2	
       {
      3	
       	
      4	        public	static	void	main(	String[]	args)
       	
      5	        {
       	
      6	        	        int	sayi1	=	Integer.parseInt(JOptionPane.		     	
                         showInputDialog(“Birinci      sayıyı giriniz”));
       	
      7	        	        int	sayi2	=	Integer.parseInt(JOptionPane.		     	
                         showInputDialog(“Ikinci       sayıyı giriniz”));
       	
      8	        	        if(	sayi1	<	sayi2)
       	
      9	        	        {
      10	       	        	       JOptionPane.showMessageDialog(null,	sayi1	+	
      		        	        	       “	kucuktur	“	+	sayi2);
      11	       	        }
      12	       	        else	if(	sayi1	<	sayi2)
      13	       	        {
      14	       	        	       JOptionPane.showMessageDialog(null,	sayi1	+	
      		        	        	       “	buyuktur	“	+	sayi2);
      15	       	        }
      16	       }
      17}

Bu uygulamalarda göstermek istediğim durum 8 ve 12 numaralı satırlardaki karşılaştırmaların
aynı olmasıdır. Bu durumda eğer 8 numaralı satırdaki karşılaştırma true üretirse 12 numaralı
satır, aynı karşılaştırmayı yapmasına rağmen çalışmayacaktır. Eğer 8 numaralı satırdaki karşılaş-
tırma false üretirse 12 numaralı satırdaki aynı karşılaştırma tekrar yapılacaktır ve doğal olarak
o da false üreteceğinden else bloğu da çalışmayacaktır. Bunun da anlamı uygulamada durum
ne olursa olsun hiçbir zaman else bloğunun çalışmayacağıdır.

Sayısal karşılaştırmalardan sonra şimdi mantıksal işlemlere bakalım. Mantıksal işlemler sayısal
ifadelerden farklı olarak zaten boolean sonuç üretir. Mantıksal işlemler AND (VE), OR (VEYA),
EX-OR (ÖZEL VEYA), NOT (DEĞİL) işlemleridir. Mantıksal işlemlerin kestirmeli ve kestirmesiz
olmak üzere 2 şekli vardır. Kestirmeli (short-circuited) işlemler doğruluğu kontrol edilecek ifa-
denin içinde bulunan ifadelerden herhangi biri bütün ifadenin sonucunu belirlediği anda diğer
ifadeler kontrol edilmez. Kestirmeli (short-circuited) işlemlerde, bir ifadenin içinde bulunan bütün
ifadelerin doğruluğu kontrol edilir, sonuç belirlense bile işlem sona ermez.
2   Döngüler
2 Döngüler
• While Döngüsü

• do Döngüsü

• for Döngüsü

• break ve continue Deyimleri
                                         Döngüler
Birçok programlama dilinde olduğu gibi, Java dilinde de döngüler önemli bir yere sahiptir. Döngü-
ler, yinelenen işlemler için oluşturulan kod bloğunun, belirli bir koşula bağlı olarak tekrarlanmasını
sağlayan yapılardır.

Java dilinde 3 tip döngü mevcuttur. Bunlar;

    while
    do
    for
döngüleridir.

Oluşturulan döngü yapıları birkaç farklılık dışında, içinde bulunan kod parçacığını baştan belirle-
nen ya da program akışı içerisinde belirlenen sayıda tekrarlanmasını sağlar. Döngüler belirli sayı-
da işlenmek üzere kurulabileceği gibi kod bloğu içerisinde gerçekleştirilecek bir koşul sağlanana
kadar tekrarlanmak üzere de gerçekleştirilebilir.

Döngülerin oluşturulması sırasında dikkat edilmesi gereken en önemli noktalardan biri, döngü
içerisinde işlenecek kod parçacığının işlem sayısıdır. Belirli bir sayı ya da bir kontrol koşulu ile
kurulmayan döngüler, program akışının sürekliliğini bozarak çalışan kodu sonsuz döngüye soka-
bilir.

Bir döngünün işlenmesi sırasında ya da sonsuz döngü durumunda, kod bloğunun içerisinde mü-
dahaleler gerekli olabilir. Bu müdahaler de break ve continue yapıları ile sağlanmaktadır.


While Döngüsü
while döngüsünün genel yapısı aşağıdaki gibidir.

       while(	boolean_kontol_ifadesi)	{
       	 Tekrarlanan_Ifade(ler)	;
       }

Bu ifadede yer alan boolean_kontol_ifadesi kontrolu sonrasında boolean bir sonuç veren her-
hangi bir ifade olabilir. Tekrarlanan_Ifade(ler) ise yinelenmesi istenen kod bloğudur.

C ve C++ dillerinde farklı veri tipleri ile kontrol yapılabilirken, Java da farklı olarak buradaki kontrol
boolean bir ifade ile yapılabilir.

While döngüsünde yineleme, belirlenen koşulun sağlanmasına kadar devam edecektir. Yineleme
kontrolu çevrimin başında yapılır. Kontol ifadesinin sağlanmaması halinde, döngü içerisinde tek-
rarlanması istenen kod parçacığı hiç çalışmayabilir.

Örnek uygulama 2.1:

       1		       int	sayac=0;
        	
       2	        while	(sayac++	<	5)	{
        	
       3	        	        system.out.println(“Merhaba	Dünya”)
        }
       4	

Uygulama 2.1’ i incelediğimizde, ilk satırda, sayac adlı bir değişken tanımlanarak 0 değeri atan-
mıştır. Kontrol ifadesi, sayac++ ifadesiyle artırılan sayac değeri 5’ten küçük olduğu sürece “Mer-
haba Dünya” ifadesi yazdırılacaktır. Bu örnekte “Merhaba Dünya” ifadesi 5 kez yazılacaktır.
24   Bölüm 2




          do Döngüsü
          Genel yapısı,

                do	{
                	 Tekrarlanan_Ifade	(ler)	;
                }	while	(boolean_kontol_ifadesi)

          şeklindedir.

          do döngüsü işleyiş biçimi olarak while döngüsüne benzer. Benzer şekilde bu yapıda da boolean
          bir koşul ile döngünün yinelenmesi kontrol edilmektedir. do döngüsünün en önemli farkı, kontol
          ifadesi başta değil sonda yapıldığından tekrarlanan ifade(ler) en azından bir kere işlenecektir.


          for Döngüsü
          Birçok programlama dilindeki temel gereksinimlerden biri olan, bir değişkenin belirli bir aralıkta
          artırılması ile kurulan döngü yapılarının en çok kullanılanı for döngüsüdür.

          Genel yapısı;

                for(ifade;	booelan_kontrol_ifadesi	;	deyim)	{
                	 tekrarlanan_ifade(ler)
                }
          şeklindedir.

          ifade olarak adlandırılan kod, sıra döngünün işlenmesine geldiğinde ilk olarak çalışan ifadedir.
          Henüz döngü içerisindeki kod parçacığı çalışmaya başlamadan bir defaya mahsus olarak çalışa-
          cak, sonraki iterasyonlarda bu ifade çalışmayacaktır. Çoğunlukla döngüde kullanılacak değişke-
          nin başlangıç değer atamasında kullanılır.

          boolean_Kontrol_ifadesi doğru değerini verdiği sürece döngünün yinelenmesini sağlayan kon-
          trol ifadesidir. while döngüsünde olduğu gibi koşulun sağlanmaması durumunda for döngüsü
          de hiç çalışmayabilir.

          deyim ise döngü bloğunun sonunda çalışır. Çoğunlukla kullanılan değişkenin arttırımı bu bölüm-
          de yazılan kod ile sağlanır.

          Örnek Uygulama 2.2:

                 For(int	x=0;	x	<	10;	x++)	{
                1	
                2         System.out.println(“Değer=” + x );
                 }
                3	

          Uygulama 2.2’de, döngüde kullanılan sayısal bir x değişkeni ilk ifadede tanımlanmış ve 0 değer
          ataması yapılmış, deyim bölümünde ise arttırımı gerçekleşmiştir. Kontrol ifadesi x değişkeninin
          10’ dan küçük olduğu tüm değerler için doğrulanacak ve döngü aşağıdaki sonucu üretecektir:

                Değer=0
                Değer=1
                .....
                Değer=8
                Değer=9
                                                                                              Döngüler   25



for döngülerinde genellikle döngünün sayılması için kullanılan bir değişken ihtiyacı oldduğun-
dan, ifade bölümünde değişken tanımlamasına ve değer atamasına izin verilmektedir. Burada ta-
nımlanan değişken, sadece for döngüsü içinde geçerlidir. Böylece diğer kısımlarda tanımlanan
değişkenler ile çakışma ihtimali engellenmektedir.

Döngü bloğu (scope) içerisinde kullanılacak başka değişkenler de yine ifade olarak adlandırılan
bölümde tanımlanabilir. Bu işlem Örnek Uygulama 2.3’de belirtildiği gibi, tanımlanacak değişken-
ler arasına virgül konularak yapılır.

Örnek Uygulama 2.3:

       int	j,k;
      1	
       For(j	=	3,	k	=	6;	j	+	k	<	20	;	j++,	k	+=2	)	{
      2	
      3         System.out.println(“ j değeri=” + j +” k değeri= “ + k);
       }
      4	


break ve continue Deyimleri
breakvecontinue deyimleri Java’da da C#’ ta olduğu gibi kullanılır.

Döngü yapıları içerisinde zaman zaman kod bloğunun işlenmesi ile ilgili müdahale ihtiyaçları or-
taya çıkabilir. Belirli bir noktada döngüden çıkmak ya da o anda işlenen çevrimin sonlandırılması
istenebilir. Bu ihtiyaçlar break ve continue deyimleri ile sağlanır.

breakdeyimi, kod bloğunda kullanıldığı yerde döngünün tamamen sonlandırılmasını sağlar. An-
cak dikkat edilmesi gereken en önemli nokta, içiçe (nested) yapılar kullanıldığında break sadece
bulunduğu döngü bloğunun sonlandırılmasını sağlar, bir üst döngü işlenmeye devam edecektir. 
3   Niteleyiciler
    (Modifiers)
3 Niteleyiciler (Modifiers)
• Access Modifiers (Erişim Niteleyicileri)

• Niteleyicilerde Metod Ezme (Access
  Modifiers Overriding)

• Diğer Niteleyiciler
                        Niteleyiciler (Modifiers)
Niteleyiciler derleyiciye, kod bloğu içinde oluşturulan sınıf ve sınıf elemanları ile ilgili bilgi sağla-
yan anahtar kelimeler grubudur.

En sık kullanılan niteleyiciler erişim niteleyicileridir. Bunlar;

    public
    protected
    private
Erişim niteleyicileri dışında belirli bir biçimde kategorize edilemeyen niteleyiciler de bulunmakta-
dır. Bunlar ise;

    final
    abstract
    static
    transient
    synchoronized
    volatile
Tanımlama sırasında bir niteleyici ile belirlenmeyen sınıf elemanları defaultolarak belirlenir. De-
fault kod içerisinde kullanılan bir anahtar kelime olmayıp, bir niteleyici saptanmamasını ortadan
kaldırmak için otomatik olarak atanır.


Access Modifiers (Erişim Niteleyicileri)
Erişim niteleyicileri olarak adlandırılan niteleyiciler, sınıf ve sınıf elemanlarının (değişken, method)
erişim seviyeleri ile ilgili kısıtlama sağlar.

Sınıf, değişken ya da metodların tanımlamalarında kullanılan bu anahtar kelimelerle erişim kısıt-
lamaları belirlenerek oluşturulan kodun güvenliği artırılır.

Bazı istisnalar dışında erişim niteleyicileri tarafından kontrol edilebilen değişkenler sınıf seviyesi
değişkenlerdir. Bir sınıfın içerisinde tanımlanan değişkenler erişim niteleyicileri ile belirlenmemiş
olabilir. Bir metod değişkeni sadece o metodun içerisinde kullanılır.

public
Bir Java programında public olarak tanımlanan bir sınıf, değişken ya da metod herhangi bir kı-
sıtlama olmaksızın kullanılabilir. Bir uygulamanın main() metodu, tüm Java runtime ortamlarından
çağırılabilmesi için public olarak tanımlanır.

Üst sınıflarda (top-level class) kullanılabilen tek erişim niteleyicisi public’tir. Üst sınıflarda pri-
vate ya da protected tanımlaması yapılmamaktadır.

private
privateolarak tanımlanan değişken ya da metodlar, sadece bulunduğu sınıf içinde kullanılabi-
lir. Tanımlandığı sınıf dışından erişimi mümkün değildir.

protected
Sadece değişken ve metodlar protected olarak tanımlanabilir. protected sınıf elemanları bu-
lundukları paket (package) içerisinde erişilebilir durumdadır. Bu özelliğiyle default yapısında ben-
zemekle beraber, yer aldığı sınıfın alt sınıfları (sub classes) tarafından da erişilebilir durumdadır.
protected olarak tanımlanan sınıf elemanı, bulunduğu sınıfın inherit edildiği bir başka package
içerisinden de erişilebilir durumdadır.
30   Bölüm 3




          Niteleyicilerde Metod Ezme (Access Modifiers Overriding)
          Niteleyici olarak adlandırılan sınıf elemanlarında overriding aşağıda belirtilen biçimlerde gerçek-
          leşir.

          Geçerli Overriding
          Şekil 1:


                  private                  default                  protected                   public


              private olarak tanımlanan bir metod; private, default, protectedvepublic metod-
               lar tarafından override edilebilir.
              Default bir metod; default, protectedvepublic metodlar tarafından override edilebilir.
              protected bir metod; protectedvepublic metodlar tarafından override edilebilir.
              public bir metod ise sadece public bir metod tarafından override edilebilir.

          Geçersiz Overriding
          Şekil 2:


                  public                 protected                  default                     private


              Default bir metod; private bir metod tarafından override edilemez.
              protected olarak tanımlanan bir metod; default ve private metodlar tarafından override
               edilemez.
              public bir metod ise; protected, default ve private metodlar tarafından override edile-
               mez.

          Diğer Niteleyiciler
          Java’da kullanılan diğer niteleyicilerin tanımlanmasında sıra önem taşımaz. Örneğin public
          final tanımlaması ile final public tanımlaması birbirinden farklı değildir. Yine ptotected
          staticilestatic protected tanımlamaları aynı şekilde geçerli olacaktır.

          final
          final niteleyicisi, sınıf, metod ve değişkenlere uygulanmaktadır. final olarak belirlenen bir
          sınıf elemanı değiştirilemez.

          Örneğin,

                  class	SubMath	extends	java.lang.Math	{	}

          ifadesi derlendiğinde, “Can’t subclass final classes.” hatası verecektir.

          Dikkat edilmesi gereken önemli noktalardan biri, final bir değişken bir nesneye refere edildi-
          ğinde, değiştirilemeyen nesnenin instance’ı (örnek) değil, referans tipli değişkendir. Bir başka de-
          yişle; final bir referans nesne değişkeni değiştirilemez ancak yaratılan instance bu kısıtlanmadan
          etkilenmez. Final niteleyicisinin C#’taki karşılığı sealed anahtar kelimesidir.
                                                                                      Niteleyiciler (Modifiers)   31




abstract
abstractniteleyicisi sınıf ve metodlara uygulanmaktadır. abstract,. Microsoft .NET platfor-
mu üzerinde kullanılan Visual Basic .NET dilinde abstract bir sınıf oluşturmak için kullanılan
anahtar kelime MustInherit’tir. Buradan anlayacağınız gibi, abstract bir sınıftan mutlaka
türetme yapılmalıdır ve türetilen sınıf kullanılmalıdır.

Eğer bir sınıf birden fazla abstract metoda sahipse, derleyici sınıfın abstract olar-
ak tanımlanmasını zorlar. Bu durum kullanılabilirliği artırır. Sınıfı kullanırken, türetilen sınıf
kullanılması gerektiğini ya da örneklenebileceğinin belirlenmesi için bakılması gereken yer sınıfın
tanımlamasıdır.

Aşağıda belirtilen durumlardan en az birisi gerçeklendiğinde, derleyici bir sınıfın abstract olarak
tanımlanmasını zorlayacaktır.

    Sınıf birden çok abstract metoda sahipse
    Sınıf implementasyon sağlamayan bir veya birden çok abstract metod inherit ediyorsa
    Sınıf bir arayüz (interface) implemente etmek üzere tanımlandığı halde, interface’in tüm me-
     todları için implementasyon sağlamıyorsa

static
static niteleyicisi değişkenler, metodlar hatta bir metodun parçası olmayan kod blokları için
kullanılabilir. static olarak belirlenen sınıf elemanları bir sınıfla bağlantılı olmaktan çok sınıfa
ait olarak düşünülebilir.

static olarak belirlenmiş bir değişkenin değeri, ne kadar instance (örnek) türetilmiş olursa olsun
değerini koruyarak sabit kalacaktır.

static bir değişkeni refere etmenin iki yolu vardır:

    Sınıfın instance’ına referans verme yolu ile.
    Sınıf adı ile.
Metodlar da static olarak tanımlanabilir. Sınıfın static verilerine ulaşabildikleri ve sınıfın
diğer static metodlarını çağırabildikleri halde, static metodlar sınıflarının non-static (statik
olmayan) elemanlarını kullanamazlar.

Non-static metodlar thisadlı örtülü (implicit) bir değişkene sahiptir. Non-static metodlarda, hangi
nesnenin ya da metodun olduğunu belirtmeden bir değişken veya metod çağırılabilir.

Örnek Uygulama 3.1:

          class	Xyz
         1	
          {
         2	
          	
         3	           int	ix;
          	
         4	           void	f1()	{
          	
         5	           ix++;
         6				        }
          }
         7	

Örnek Uygulama 3.1’de tanımlanan ix değişkeni, hangi nesne ya da metoda ait olduğu belirtil-
meden ix++ ifadesi ile artırılmaktadır. Derleyici varsayılan olarak bu ifadeyi this.ix++ olarak
algılar ve doğru bir biçimde işler.

static metodlarda ise thisyapısı bulunmamaktadır. static bir metod içerisinden, bir başka
metod ulaşılmak ya da çağırılmak istendiğinde ”Undefined variable:this” hatası verecektir.
32   Bölüm 3



          static bir metod, non-static bir değişkene ulaşmak istediğinde hangi sınıfın değişkeni olduğunu
          ya da metodu çalıştıran sınıfın hangisi olduğunu belirterek çağırmak zorundadır.

          static bir metod non-static olarak override edilemez. Bu durumda “Static methods can’t be
          overriden” hata mesajı verecektir.

          transient
          transient niteleyicisi sadece değişkenler için kullanılmaktadır. transient bir değişken kendi
          objesinin sürekli bir parçası olarak tutulmaz.

          synchronized
          synchronized değişkenler multithread programlarda, kritik kodlara erişimi kontrol etmek
          amacıyla kullanılır. Multithreading daha sonraki bölümlerde detaylı olarak incelenecektir.

          volatile
          volatile olarak belirlenen değişkenler asenkron olarak değiştirilebilen değişkenlerdir.vola-
          tile değişkenler çok işlemcili ortamların konusudur.

          Niteleyiciler ile ilgili özeti aşağıdaki tabloda bulabilirsiniz.

          Şekil 3:

          Niteleyici                    Sınıf              Değişken           Metod            Constructor
          public                                                                                 
          protected                       –                                                       
          (Default)*                                                                             
          private                         –                                                       
          final                                                                                   –
          abstract                                             –                                   –
          static                          –                                                        –
          transient                       –                                    –                    –
          volatile                        –                                    –                    –
          synchronized                    –                     –                                   –

          * default bir niteleyici değil, niteleyici belirlenmediğinde varsayılan olarak kullanılan anahtar söz-
          cüktür.
4   Casting ve
    Conversion
4 Casting ve Conversion
• Basit Tiplerde Conversion

• Referans Tiplerde Conversion
                          Casting ve Conversion
Java’ da, C# ve tüm programlama dillerinde olduğu gibi kullanılan her değişkenin bir tipi vardır.
Bunlar int, longvedouble gibi basit (primitive) değişkenler olduğu gibi, sınıf değişkenleri (Ve-
ctor, Graphics vb) ya da arayüzler (LayoutManager ve Runnable vb) olabilir.

Bu bölümde, veri tipleri arasındaki dönüşümleri ele alacağım.

Veriler gerek açıkça (explicitly) ya da örtülü (implicitly) olarak dönüştürülebilir. Bir başka deyişle
kendi bilgi ve isteğimiz dahilinde ya da derleyici tarafından otomatik olarak yapılan veri tipi dönü-
şümleri mümkündür.

Açıkça gerçekleştirilen veri tipi dönüşümleri casting olarak adlandırılır. Bu durumda kodlama es-
nasında kendi isteğimizle bir değişkenin tipini değiştiririz.

Örnek Uygulama 4.1:

        ix	=	(int)	mylix;
       1	

Örnek Uygulama 4.1’de, mylix değişkeni, int olarak ix değişkenine casting yapılarak atan-
maktadır.

Örtülü olarak gerçekleşen veri tipi dönüşümleri ise, değişken atamaları sırasında derleyici tara-
fından otomatik olarak yapılmaktadır. Açık olmayan, örtülü dönüşümler conversion olarak adlan-
dırılır.

Örnek Uygulama 4.2:

        int	x,	y;
       1	
        double	d;	
       2	
        x	=	3;		
       3	
        y	=	5;	
       4	
        d	=	x	+	y;
       5	

Örnek Uygulama 4.2’de double değişkenine atanan tam sayı değerlerin toplamı 8.000000... de-
ğerini alacaktır. Bu durumda gerçekleştirilen değişken tipi dönüşümü derleyici tarafından otomatik
olarak gerçekleştirilecektir.

Java programlama dilinde basit tipler ve referans tipleri olmak üzere iki veri tipi kategorisi bulun-
maktadır.

Basit tipler olarak adlandırılan veri tipleri; boolean, char, byte, short, int, long, float,
double’dır. Referans tipleri ise; JDK tarafından sağlanan birçok sınıf, arayüzün yanısıra, Java
geliştiricileri tarafından geliştirilen sınıflardır.

Basit tipler ve referans tipleri olarak anılan tüm veri tipleri arasında, belirli kurallar dahilinde cas-
ting ve conversion mümkündür. Bu bağlamda, 4 çeşit veri tipi dönüşümü ortaya çıkmaktadır:

    Basit veri tipleri arasında conversion
    Basit veri tipleri arasında casting
    Referans tipleri arasında conversion
    Referans tipleri arasında casting
36   Bölüm 4




          Basit Tiplerde Conversion
          Basit veri tiplerinin dönüşümünde 3 tip conversion karşımıza çıkar, bunlar:

              Atama
              Metod çağırma
              Aritmetik yükseltme (arithmetic promotion)

          Basit Tiplerde Conversion: Atama
          Atama dönüşümü, bir değişkene orijinal değerinden farklı bir değer ataması yapıldığında gerçek-
          leşir.

          Örnek Uygulama 4.3:

                  int	i;
                 1	
                  double	d;
                 2	
                  i	=	10;
                 3	
                  d	=	i;
                 4	

          Örnek Uygulama 4.3’de tanımlanan i int, d ise double değişkenlerdir. double bir değişken
          tamsayı ifade saklayamayacağından, d = i ataması yapıldığında, d değişkeninin sakladığı de-
          ğer 10.000000... olacaktır.

          Ancak bazı atamalar yukarıda verdiğimiz örnekteki gibi geçerli ifadeler olmayacaktır.

          Örnek Uygulama 4.4:

                  double	d;
                 1	
                  short	s;
                 2	
                  d	=	1.2345;
                 3	
                  s	=	d;
                 4	

          Örnek Uygulama 4.4’te yer alan atama, double bir ifadenin short veri tipine atanması şeklinde-
          dir. short veri tipi double değerini saklayamaz. Bu kod işlenmeyecek, “Incompitable type for=.”
          hatasını verecektir.

          Daha büyük değer saklayan değişkenlerden daha küçük değer taşıyan değişkenlere dönüşüm bir
          şişedeki sıvıyı küçük bir bardağa taşımaya benzer ancak explicit casting kullanılmalıdır.

          Basit tiplerde atamanın genel kuralları şu şeklidedir:

              boolean bir veri tipi diğer veri tiplerine çevrilemez.
              Genişletme dönüşümü (widening conversion) sözkonusu ise, boolean olmayan (non-boole-
               an) bir veri tipi, boolean olmayan bir veri tipine dönüştürülebilir.
              Daraltma dönüşümü (narrowing conversion) sözkonusu ise boolean olmayan bir veri tipi,
               boolean olmayan bir veri tipine dönüştürülemez.
          Genişletme dönüşümü, daha küçük değerler saklayan veri tiplerinden daha geniş değerler sakla-
          yan veri tiplerine gerçekleştirilebilir. Bu durumda herhangi bir veri kaybı olmayacaktır. Genişletme
          Dönüşümü;

              byte veri tipinden; short, int, long, float veya double veri tiplerine,
              short veri tipinden; int, long, float veya double veri tiplerine,
              char veri tipinden; int, long, float veya double veri tiplerine,
                                                                                   Casting ve Conversion   37



    int veri tipinden; long, float veya double veri tiplerine,
    long veri tipinden; float veya double veri tiplerine,
    float veri tipinden; double veri tipine
gerçekleştirilebilir.

Şekil 4.1:

                        char

                                      int            long              float           double

     byte               short




Şekil 1’de belirtilen tüm dönüşümler veri kaybı yaşanmaksızın yapılan dönüşümlerdir. Yine şe-
kilde belirtilen ok yönü dışında gerçekleştirilecek dönüşümler ise daraltma dönüşümü (narrowing
conversion) olarak tanımlanır. Bu tip conversionlarda veri kaybı olabilir. Daraltma dönüşümü ise;

    byte veri tipinden; char veri tipine,
    short veri tipinden; byte veya char veri tiplerine,
    char veri tipinden; byte veya short veri tiplerine,
    int veri tipinden; byte, short veya char veri tiplerine,
    long veri tipinden; byte, short, char veya int veri tiplerine,
    float veri tipinden; byte, short, char, int veya long veri tiplerine,
    double veri tipinden; byte, short, char, int, long veya float veri tiplerine
gerçekleştirilebilir.

Java programlama dilinde ondalıklı sayısal değerler double, ondalıksız sayısal ifadeler inte-
ger veri tipindedir. Normal koşullarda, integer ve double değerlerin daha küçük değerler
tutan değişkenlere atanmasının derleyici hatasına sebep olacağını düşünebiliriz. Ancak Java bu
durumları kendi içinde esneterek ve atamayı hatasız olarak gerçekleştirir.

Örnek Uygulama 4.5:

        float	f	=	2.345;
       1	
        byte	b	=	3;
       2	
        short	s	=	5;
       3	
        char	c	=	7;
       4	

Örnek Uygulama 4.5’te belirtilen atamalar hatasız olarak gerçekleşecektir. Örnek Uygulama
4.6’de belirtilen kodun ikinci satırı ise sayısal ifade ataması yapılmadığından derlenmeyecektir.

Örnek Uygulama 4.6:

        int	i	=	15;
       1	
        byte	b	=	i;	
       2	
38   Bölüm 4




          Basit Tiplerde Conversion: Metod Çağırma
          Metod Çağırma dönüşümü, belirli bir veri tipinde argüman bekleyen bir metoda, farklı bir veri tipin-
          de argüman sağlandığında derleyicinin otomatik olarak gerçekleştirdiği dönüşümdür.

          Örnek Uygulama 4.7:

                 float	f;
                1	
                 double	d;
                2	
                 f	=	2.34567f;
                3	
                 d	=	Math.cos(f);
                4	

          Örnek Uygulama 4.7’de belirtilen Math sınıfına ait cos() metodu, veri tipi olarak double bir
          argüman beklemektedir. f değişkeninin float değeri cos() metodunda işlenmeden önce oto-
          matik olarak double veri tipine dönüştürülecektir.

          Metod çağırma dönüşümlerinde de atama dönüşümlerini belirleyen kurallar geçerlidir. Derleyici
          zamanında (compile time) genişletme dönüşümüne izin verilirken, daraltma dönüşümüne izin
          verilmez.

          Basit Tiplerde Conversion: Aritmetik Yükseltme
          Aritmetik yükseltme, aritmetik ifadeler kullanılarak işlem yapıldığında gerçekleşen dönüşüm tipi-
          dir.

          Örnek Uygulama 4.8:

                 short	s	=	5;
                1	
                 int	i	=	8;
                2	
                 float	f	=	13.2f;
                3	
                 double	d	=	13.2;	
                4	
                 if	(	s	–	i	<=	f	*	d)
                5	
                6          system.out.println( “İlk işlem küçük veya eşit”;
                 else
                7	
                8          system.out.println( “İlk işlem küçük veya eşit değil”;

          Örnek Uygulama 4.8, if bloğunun içinde aritmetik ifadeler ile işlenen değişkenler farklı veri tiple-
          rindedir. Derleyici, aritmetik işlemleri anlamlı bir biçimde gerçekleştirmek için gerekli dönüşümleri
          otomatik olarak gerçekleştirecektir. Bu dönüşümlerin tamamı daha önce belirttiğimiz genişletme
          dönüşümü olacaktır.

          Aritmetik yükseltme dönüşümü kuralları tekli operatörler (unary operators) ve ikili operatörler (bi-
          nary operators) için farklılaşmaktadır. Tekli operatörler tek bir işlenen (operand) üzerinde işlem
          yaparken, ikili operatörler iki işlenen üzerinde işlem yapmaktadır.

          Şekil 4.2:

           Tekli
                            +         -         ++         --                   ~
           operators

                            +         -          *         /         %          >>         >>>          <<
           Binary
           operators
                                      &          ^         |
                                                                                             Casting ve Conversion   39



Tekli operatörler için uygulanan dönüşüm kuralları aşağıdaki gibidir;

     Eğer kullanılan işlenenin veri tipi byte, short ya da char ise; int veri tipine dönüştürülür.
      (Eğer kullanılan operatör ++ ya da -- ise dönüşüm yapılmayacaktır)
     Yukarıda belirtilen dışındaki veri tiplerinde dönüşüm yapılmaz.
     İkili operatörler için uygulanan kurallar ise aşağıdaki şekilde belirlenmiştir.
     Eğer işlenenlerden birinin veri tipi double ise, diğer işlenen double veri tipine dönüştürü-
      lecektir.
     Eğer işlenenlerden birinin veri tipi float ise, diğer işlenen float veri tipine dönüştürülecek-
      tir.
     Eğer işlenenlerden birinin veri tipi long ise, diğer işlenen long veri tipine dönüştürülecek-
      tir.
     Yukarıda belirtilen dışındaki veri tiplerinde int veri tipine dönüştürülecektir.

Basit Tiplerde Casting
Şimdiye kadar ele aldığımız dönüşüm tipleri örtülü olarak gerçekleştirilen, Java’nın otomatik ola-
rak gerçekleştirdiği dönüşümlerdi. Bu dönüşümler, açıkça bir kod yazmamızı gerektirmeyen dö-
nüşümlerdir.

Casting ise, Java’ya bir dönüşümü yapmasını söylemektir. Veri tipleri arasındaki dönüşümü belir-
leyen, yazacağımız kod olacaktır.

Genişletme dönüşümü olarak belirttiğimiz dönüşümlerde casting’e ihtiyaç duyulmamakta, derleyi-
ci otomatik olarak yapmaktadır. Casting daha çok daraltma dönüşümü olarak bilinen dönüşümler-
de kullanılmaktadır. Bu dönüşümlerde veride kayıp riski bulunduğundan, derleyici otomatik olarak
yapmamakta, riskin alınarak dönüşümün sağlanması gerektiği yazılacak kod ile belirtilmelidir.

Örnek Uygulama 4.9:

         short	s	=	362;
        1	
         byte	b	=	s;
        2	
         system.out.println(“s	=	”	+	s	+	“,	b	=	”	+	b	)
        3	

Örnek Uygulama 4.9’da belirtilen ifade derlendiğinde, 2. satırda derleyici hatası verecektir. Çünkü
short veri tipinden daha dar bir veri tipi olan byte veri tipine atama yapılmak istenmektedir. Bu
dönüşüm Şekil 4.3’ te belirtilmiştir.

Şekil 4.3:

  0       0      0     0      0     0      0     1      0     1      1     0      1      0       1     0




                                               b = (byte)s




Bu durumda derleyici açıkça dönüşüm yapılması gerektiğini bildiren; Explicit cast needed to con-
vert short to byte uyarısı verecektir. Örtülü casting yaparsak aşağıdaki durum oluşacak ve veri
kaybı sözkonusu olacaktır.
40   Bölüm 4



          Örnek Uygulama 4.10:

                         short	s	=	362;
                        1	
                         byte	b	=	(byte)s;
                        2	
                         system.out.println(“b	=	”	+	b	)
                        3	

          b = 106 olarak yazılacaktır.

          Basit veri tiplerinin casting yapılmasında aşağıdaki kurallar geçerlidir.

                     Boolean olmayan herhangi bir veri tipi, boolean olmayan herhangi bir veri tipine dönüştü-
                      rülebilir.
                     Boolean bir veri tipi herhangi bir veri tipine, herhangi bir veri tipi boolean veri tipine dönüş-
                      türülemez.

          Referans Tiplerde Conversion
          Referans tipli değişkenleri de basit veri tipleri gibi atama, metod çağırma ve casting ile dönüştü-
          rülebilmektedir. Ancak eski ve yeni tipler arasındaki dönüşümlerde daha çok kombinasyon oldu-
          ğundan daha karmaşıktır.

          Referans tiplerinde conversion da basit tiplerde conversion gibi derleyici zamanında gerçekleş-
          mektedir. Daha sonra belirteceğimiz üzere object casting için ise bu geçerli değildir.

          Referans Tiplerde Conversion: Atama
          Referans tiplerde atama, bir nesne referans değerini farklı bir veri tipindeki değişkene atadığımız-
          da gerçekleşir. Genel notasyon olarak aşağıdaki biçimde uygulanmaktadır:

                        EskiTip	x	=	new	EskiTip();
                        YeniTip	y	=	x;

          Referans tiplerde conversion’da, eskitip ve yenitip üyeler (member) arasındaki dönüşüm kombi-
          nasyonları Şekil 4.4’te belirtilmiştir.

          Şekil 4.4:

                                                                    Eski Tip

                                            Sınıf (Class)           Arayüz (Interface)     Dizi (Array)

                                            Eskitip, Yenitip’in     Yenitip nesne
                        Sınıf                                                              Yenitip nesne olmalıdır.
           Yeni Tip




                                            altsınıfı olmalıdır.    olmalıdır.

                                                                    Eskitip, Yenitip’in
                                            Eskitip, yenitip’in
                        Arayüz                                      alt-arayüz’ü           Yenitip cloneable ya da
                                            arayüzünü
                        (Interface)                                 (subinterface)         serializable olmalıdır.
                                            implemente etmelidir.
                                                                    olmalıdır.

                                                                                           Eskitip, yenitip’in dizisine
                                            Derleyici hatası        Derleyici hatası
                        Dizi (Array)                                                       dönüştürülebilecek bir dizi
                                            oluşacaktır.            oluşacaktır.
                                                                                           olmalıdır.


          Tüm dönüşüm kurallarına uygulanmasa da, genel bir bakış açısı olarak, izin verilen referans tipi
          dönüşümleri, miras hiyerarşisinde (inheritance hierarchy) yukarı doğru olmaktadır. Yani, eskitip,
          yenitip’ten miraslanmalıdır.
                                                                                                   Casting ve Conversion   41



Genel kuralları aşağıdaki şekilde belirlenebilir:

          Bir arayüz sadece yine bir arayüze ya da nesneye dönüştürülebilir. Eğer yenitip bir arayüz ise,
           eskitip’in alt-arayüzü olmalıdır.
          Bir sınıf yine bir sınıfa ya da arayüze dönüştürülebilir. Bir sınıfa dönüştürüldüğünde, yenitip
           eskitip’in alt-sınıfı olmalıdır. Bir arayüze dönüştürüldüğünde, eski sınıf arayüzü implemente
           etmelidir.
          Bir dizi, sınıf nesnesine ya da cloneable veya serializable bir arayüze ya da diziye dönüştürü-
           lebilir. Sadece nesne referans tipinin dizisi bir diziye dönüştürülebilir ve eski eleman tipi yeni
           eleman tipine çevrilebilir olmalıdır.

Referans Tiplerde Csonversion: Metod Çağırma
Genel olarak referans tiplerde atama dönüşümünde tanımlanan kurallar bu dönüşüm tipinde de
geçerlidir. Bir süpersınıfa dönüşüme izin verilirken, altsınıfa dönüşüme izin verilmez.

Genel kuralları aşağıda belirtilmiştir.

          Bir arayüz sadece yine bir arayüze ya da nesneye dönüştürülebilir. Eğer yenitip bir arayüz ise,
           eskitip’in alt-arayüzü olmalıdır.
          Bir sınıf yine bir sınıfa ya da arayüze dönüştürülebilir. Bir sınıfa dönüştürüldüğünde, yenitip
           eskitipin alt-sınıfı olmalıdır. Bir arayüze dönüştürüldüğünde, eski sınıf arayüzü implemente
           etmelidir.
          Bir dizi, sınıf nesnesine ya da klonlanabilir veya serileştirilebilir bir arayüze ya da diziye dö-
           nüştürülebilir. Sadece referans tipinin dizisi bir diziye dönüştürülebilir ve eski eleman tipi yeni
           eleman tipine çevrilebilir olmalıdır.

Referans Tiplerin Çevrimi
Referans tiplerde çevrim daha önce ele aldığımız basit tiplerin çevrimine benzer. Atama ve metod
çağırma yöntemlerinde izin verilen tüm açık çevrimler (explicit casting) bu yöntemde de kullanı-
labilmektedir.
Referans tiplerin çevriminde derleyici zamanında olduğu gibi çalışma zamanında uygulanan ku-
rallar da bulunmaktadır. Bunu sebebi, referans tipli değişkenlere ilişkin bazı bilgilerin derleyici
zamanında henüz bilinmemesidir.
Referans tiplerin çevrimi için derleyici zamanı kuralları Şekil 4.5’ te belirtilmiştir.
Şekil 4.5:
                                                                         Eski Tip
                               Miras verebilir      Miras veremeyen
                                                                                Arayüz
                               sınıf (non-final     sınıf (final - sealed                          Dizi (array)
                                                                                (interface)
                               class)               class)

            Miras verebilir
                               Eskitip, yenitip’i   Eskitip, yenitip’i          Herzaman           Eskitip nesne
            sınıf (non-
                               genişletmelidir      genişletmelidir             geçerlidir         olmalıdır
            final class)

            Miras
Yeni Tip




                                                                                Yenitip arayüzü
            veremeyen          Eskitip, yenitip’i   Eskitip ve Yenitip aynı                        Derleyici hatası
                                                                                implemente
            sınıf (final -     genişletmelidir      sınıf olmalıdır.                               oluşacaktır
                                                                                etmelidir
            sealed class)
                                                    Eskitip, Yenitip’in
            Arayüz             Herzaman                                         Herzaman           Derleyici hatası
                                                    arayüzününü
            (interface)        geçerlidir                                       geçerlidir         oluşacaktır
                                                    implemente etmelidir
                                                                                                   Eskitip, yenitip’in
                               Yenitip nesne        Derleyici hatası            Derleyici hatası   dizisine
            Dizi (array)
                               olmalıdır            oluşacaktır                 oluşacaktır        dönüştürülebilecek
                                                                                                   bir dizi olmalıdır
42   Bölüm 4



          Eskitip ve Yenitip arasındaki dönüşümlerde derleyici zamanında geçerli kurallar aşağıda belirtil-
          miştir.

              Eskitip ve Yenitip dönüşümlerinde her ikisinin de sınıf olması halinde, bir sınıf diğerinin altsı-
               nıfı olmalıdır.
              Eskitip ve Yenitip’lerin her ikisi de dizi ise, her iki dizi de referans tipi barındırmalı ve eskitipin
               bir elemanının yenitipin bir elemanına çevrimi geçerli olmalıdır.
              Bir arayüz ile Miras verebilir sınıf (non-final class) arasında herzaman çevrim yapılabilir.
          Çalışma zamanında uygulanan kurallar ise;

              Eğer Yenitip bir sınıf ise, dönüştürülen ifadenin sınıfı ya Yenitip olmalıdır, ya da Yenitip’ten
               miras alınmalıdır.
              Eğer Yenitip bir arayüz ise, dönüştürülen ifadenin sınıfı Yenitip’i implemente etmelidir.
          olarak belirlenebilir.
5   Yapısal
    Programlama
5 Yapısal Programlama
• Yapısal Programlama Nedir?

• Nesne Yönelimli Programlamanın Temel
  Kavramları
                          Yapısal Programlama
Yapısal Programlama Nedir?
Yapısal programlamada uygulamanın akışı fonksiyonlara bölünerek her bir fonksiyonun belirli
bir işi gerçekleştirmesi sağlanır. Yazılımın amacı gerçek dünyadaki iş akışlarının bilgisayar orta-
mında yürütülmesi olduğu için, modellenmesi istenen kavramlar fonksiyonlar ve değişkenler kul-
lanılarak modellenmeye çalışılmaktadır. Gerçek dünyada fonksiyon ve değişken gibi kavramlar
yerine nesnelerin bulunmasından dolayı modelleme tam anlamıyla gerçekleştirilememektedir.

Nesne Yönelimli Programlamanin Temel Bileşenleri
Sınıf ve Nesne
Modellememiz gereken iş akışlarını yazılım ortamında temsil etmek için kullandığımız temel bile-
şen sınıflardır. Sınıf sadece bir modeldir, uygulama çalışırken fiziksel olarak oluşturulmayan, kod
üzerinde kalan soyut bir yapıdır. Nesne ise uygulamanın çalışması aşamasında fiziksel olarak
bilgisayarın belleğinde oluşan ve başka nesnelerle iletişim kurarak iş akışlarının gerçekleşmesini
sağlayan bir bileşendir. C# .Net dilinde olduğu gibi Java dilinde de yeni bir nesne oluşturmak için
new anahtar kelimesi kullanılır, new anahtar kelimesini kullandığımız her kod parçası uygulama-
nın çalışması sırasında bellek üzerinde yeni bir nesne oluşturur.
Nesne yönelimli programlamaya yeni başlayan yazılım geliştiriciler sınıf ve nesne kavramları ara-
sındaki farkı anlamakta zorluk çekebilir, bunun sebebi uygulamanın çalışma aşamasında sınıf
diye bir varlığın olmaması gibi gerçek hayatta da sınıf diye bir varlığın bulunmamasıdır.

Nitelikler (Attributes)
Bir sınıfın içinde bulunan ve o sınıftan oluşturulacak olan nesnelerin özelliklerini tutan yapılar-
dır. Sınıfların kodlanması sırasında değişkenler şeklinde oluşturulurlar ve sınıftan nesne örneği
oluşturulduğu anda bellek üzerinde oluşurlar. Gerçek hayattaki nesnelerin çeşitli niteliklere sahip
olması gibi yazılım ortamında oluşan nesneler de çeşitli niteliklere sahiptir.

Örnek Uygulama 5.1:
      1	public	class	Nokta
      2	{
      3		        private	int	x;
      4		        private	int	y;
      5	}	
Örnekte, nokta kavramının yazılım ortamındaki modeli olan Nokta sınıfı oluşturulmuştur ve bu
sınıftan oluşturulacak olan nesnelerin x ve y koordinatlarını temsil etmek için xvey nitelikleri ola-
caktır. xvey nitelikleri sınıfın içinde yer alsa da değerlerini Nokta sınıfından bir nesne oluştuktan
sonra ve oluşan nesne üzerinden alacaktır.

Davranışlar
Yazılım ortamında bellek üzerinde oluşan nesnelerin sergileyeceği davranışlar da nitelikler gibi
bu nesnenin modeli olan sınıf üzerinde bulunur. Davranışlar, sınıfların kodlanması sırasında me-
todlar şeklinde oluşturulur ve bir sınıfın içinde bulunan metodlar bu sınıftan oluşturulacak olan bü-
tün nesnelerin ortak davranışlarını belirler. Gerçek hayattaki nesnelerin çeşitli davranışlara sahip
olması gibi yazılım ortamındaki nesnelerin de çeşitli davranışları bulunur. Her bir nesnenin kendi
davranışını modelleyen metodlara örnek metodu(instance method) adı verilir.

Örnek Uygulama 5.2:

      1	public	class	Nokta
      2	{
   Bölüm 5




                3		       private	int	x;
                4		       private	int	y;
                5		       public	void	YerDegistir(int	yeniX,	int	yeniY)
                6		       {
                 	
                7	        x	=	yeniX;
                 	
                8	        y	=	yeniY;
                 }
                9	
                10}

          Örnek Uygulama 5.1’de oluşturduğumuz Nokta sınıfımıza YerDegistir davranışını ekledik.
          Bu metod sayesinde Nokta sınıfından oluşan bütün nesnelere iki boyutlu uzayda yer değiştirme
          kabiliyeti vermiş olduk. YerDegistir metodumuz iki tane tam sayı cinsinden parametre alır ve
          nesnemizin x ve y koordinat değerlerini yeni koordinat değerleriyle değiştirir.

          Nesnelere ait metodlar parametre olarak int, string gibi yerleşik tiplerden değişkenler alabile-
          cekleri gibi kendi sınıfı veya başka bir sınıf cinsinden nesneler de alabilir.

          Örnek Uygulama 5.3:

                1	public	class	Nokta
                2	{
                3		       private	int	x;
                4		       private	int	y;
                5		       public	void	YerDegistir(int	yeniX,	int	yeniY)
                6		       {
                 	
                7	        x	=	yeniX;
                 	
                8	        y	=	yeniY;
                 }
                9	
                10	       public	double	UzaklikHesapla(Nokta	ikinciNokta)
                11	       {
                12	    	     double	uzaklik	=	Math.sqrt(Math.pow(x	-	ikinciNokta.
                x,	2)	+	Math.pow(y	-	ikinciNokta.y,	2));
                13	       	       return	uzaklik;
                14	       }
                15}

          Herhangi bir nokta nesnesinin başka bir nokta nesnesi ile arasında olan uzaklığı bulmak için bir
          metod yazdık. UzaklikHesapla metodu parametre olarak bir Nokta nesnesi alıyor ve üzerinde
          çalışmakta olduğu nesneyle parametreden gelen nesne arasındaki uzaklığı double cinsinden
          hesaplayarak döndürüyor. Kare alma ve karekök hesaplama işlemleri için yerleşik Java sınfla-
          rından biri olan Math sınıfını kullandık. Metod içinde kullanılan x ve y, davranışın sahibi olan
          nesneye ait xvey değerleridir. Parametre olarak gelen ikinci nesneye ait xvey nitelikleri ise
          ikinciNokta.xveikinciNokta.y şeklinde kullanılmıştır.

          Bir sınıfın içinde aynı isimli birden fazla metod tanımlanabilir. Bu durumda tek şart tanımlanacak
          olan metodların parametre sayılarının veya parametre tiplerinin farklı olmasıdır, aynı tipten aynı
          sayıda parametre içeren aynı isimli birden fazla metod tanımlanırsa derleme hatası alırız. Bu iş-
          leme metodların aşırı yüklenmesi (overloading) adı verilir. Bu mekanizma C# dilindekine benzer
          bir mantıkla gerçekleştirilebilir.
                                                                                       Yapısal Programlama   



Örnek Uygulama 5.4:

      1	public	class	Nokta
      2	{
       private	int	x;
      3	
       private	int	y;
      4	
       public	void	YerDegistir(int	yeniX,	int	yeniY)
      5	
       {
      6	
       	
      7	        x	=	yeniX;
       	
      8	        y	=	yeniY;
       }
      9	
      10	       public	double	UzaklikHesapla(Nokta	ikinciNokta)
      11	       {
      12	       	        double	uzaklik	=	Math.sqrt(Math.pow(x	-	ikinciNokta.
      x,	2)
      		        	        	       +	Math.pow(y	-	ikinciNokta.y,	2));
      13	       	        return	uzaklik;
      14	       }
      15	    public	double	UzaklikHesapla(int	ikinciNoktaX,	int	
      ikinciNoktaY)
      16	       {
      17	    	     double	uzaklik	=	Math.sqrt(Math.pow(x	-	
      ikinciNoktaX,	2)
      		        	        	       +	Math.pow(y	-	ikinciNoktaY,	2));
      18	       	        return	uzaklik;
      19	       }
      20}
Son durumda, Nokta sınıfımızın içinde aynı işi yapan aynı isimli iki tane metod var. İlk yazdığımız
metod parametre olarak bir Nokta nesnesi ile çalışıyor, ikinci metod ise harici bir noktanın xvey
koordinat değerlerinin parametre olarak verilmesini bekliyor.

Sınıfların içinde bulunan metodlar yine aynı sınıfın içinde bulunan başka metodları da kullanabilir.
Nokta sınıfında yazdığımız UzaklikHesapla metodları içinde aynı algoritmayı iki kere yazdık.
Bunun yerine UzaklikHesapla metodlarından birinin diğer UzaklikHesapla metodunu kul-
lanarak hesaplama yapmasını aşağıdaki gibi sağlayabiliriz. Böylece gerçeklememiz gereken bir
algoritmayı veya iş mantığını bir kere gerçekleyerek koddan tasarruf ettiğimiz gibi uygulamamızı
olası değişimler için daha uygun hale getiririz.

Örnek Uygulama 5.5:

      1	public	class	Nokta
      2	{
      	
      	
      3		
      	         private	int	x;
      4		
      	         private	int	y;
      5		
      	         public	void	YerDegistir(int	yeniX,	int	yeniY)
      6		
      	         {
      7	
      		        x	=	yeniX;
   Bölüm 5




                	 8	       	       y	=	yeniY;
                	 9		      }
                	10		      public	double	UzaklikHesapla(Nokta	ikinciNokta)
                	 11	      {
                	 12	      	       return	UzaklikHesapla(ikinciNokta.x,	ikinciNokta.y);
                	 13	      }
                	 14	  public	double	UzaklikHesapla(int	ikinciNoktaX,	int	
                ikinciNoktaY)
                	 15	      {
                	 16	  	     double	uzaklik	=	Math.sqrt(Math.pow(x	-	
                ikinciNoktaX,	2)
                		         	       	      +	Math.pow(y	-	ikinciNoktaY,	2));
                	 17	      	       return	uzaklik;
                	 18	      }
                	19}	

          Yapıcı Metod (Constructor)
          Uygulama içinde nesnelerin oluşturulması aşamasında otomatik olarak çalışan metodlara kurucu
          veya yapıcı metodlar denir. Genelde nesnelerimizin içinde bulunan niteliklere ilk değerler atamak
          için kullanılır. Yapıcı metodlarla ilgili sınırlamalar aşağıdaki gibidir:

          1� Yapıcı metodlar yeni nesne oluşturulmasını sağlamaz, bir nesnenin oluşma aşamasında ça-
             lışır.
          2. Yapıcı metodların isimleri sınıfın ismiyle aynı olmak zorundadır.
          3� Yapıcı metodların geri dönüş değeri olamaz, geri dönüş değeri olan bir yapıcı metod tanımı
             yaparsak derleme hatası alırız.
          4. Bir sınıf içinde birden fazla yapıcı metod bulunabilir. Parametre tiplerinin veya sayılarının
             farklı olması birden fazla yapıcı metod tanımlanabilmesi için yeterlidir.
          5. Java dilinde de .Net ortamında olduğu gibi varsayılan, parametresiz bir yapıcı metod vardır.
             Sınıfımızın içinde parametreli veya parametresiz bir tane yapıcı metod oluşturduğumuzda
             varsayılan yapıcı metod geçersiz hale gelir.
          6. New anahtar kelimesi ile sınıftan nesne oluşturulmasına izin vermek istiyorsak yapıcı me-
             todları public olarak tanımlamamız gerekir. Sınıfın içinde bir tane yapıcı metod varsa ve bu
             metodun erişim tipi private ise, bu sınıftan nesne oluşturulamaz.
          Örnek Uygulama 5.6:

                1	public	class	Nokta
                2	{
                 private	int	x;
                3	
                 private	int	y;
                4	
                 public	Nokta()
                5	
                 {
                6	
                 	
                7	         x	=	0;
                 	
                8	         y	=	0;
                 }
                9	
                10}
                                                                                        Yapısal Programlama   



Nokta sınıfımıza parametresiz bir yapıcı metod ekleyerek yeni oluşan her nesnenin xvey koor-
dinatlarının sıfır değerine sahip olmasını yapıcı metod aracılığıyla sağladık. Sınıfımıza bir tane de
parametreli yapıcı metod ekleyelim.

Örnek Uygulama 5.7:
      1	public	class	Nokta
      2	{
       private	int	x;
      3	
       private	int	y;
      4	
       public	Nokta()
      5	
       {
      6	
       	
      7	         x	=	0;
       	
      8	         y	=	0;
       }
      9	
      10	        public	Nokta(int	x,	int	y)
      11	        {
      12	        	       this.x	=	x;
      13	        	       this.y	=	y;
      14	        }
      15}
Son durumda iki tane yapıcı metodumuz oldu. Parametresiz yapıcı metod kullanılarak oluşan
bütün nesnelerin xvey koordinatları sıfır değerini alıyor, parametreli yapıcı metodumuz ise nes-
nenin oluşması sırasında noktanın farklı koordinat değerlerine sahip olmasını sağlıyor.

Parametreli yapıcı metodumuzun gövdesinde yer alan this anahtar kelimesi, üzerinde çalışmak-
ta olduğumuz nesneyi temsil eder. Nesne özelinde değerlendirilebilen nitelik ve metodlara this
anahtar kelimesi ile ulaşabiliriz. Daha önceki örneklerde this anahtar kelimesini kullanmamıza
gerek kalmamıştı, çünkü xvey isimli birer tane değişken bulunuyordu. Son yazdığımız metodda
ise biri parametreden gelen, diğeri nesnenin sahip olduğu niteliği temsil eden iki tane x değişkeni
olduğundan bu değişkenleri biribirinden ayırabilmek için nesneden gelen x değişkeninin başına
this anahtar kelimesini ekliyoruz.

Yapıcı metodun parametrelerinden biri olan x değişkeni ile nesne üzerindeki niteliği temsil eden
x değişkeni arasında hiçbir organik bağ yoktur, farklı isimlere sahip olsalar da uygulama istendiği
şekilde çalışır. Aralarındaki ilişki yapıcı metodumuzun içinde yaptığımız değer ataması ile sınırlı-
dır. Parametreli yapıcı metodumuz Şekil 5.8’de belirtilen iki şekilde de yazılabilirdi:

Örnek Uygulama 5.8:

      1	public	Nokta(int	yeniX,	int	yeniY)
      2	{
       this.x	=	yeniX;
      3	
       this.y	=	yeniY;
      4	
      5	}
      6	public	Nokta(int	yeniX,	int	yeniY)
      7	{
       x	=	yeniX;
      8	
      9		        y	=	yeniY;
      10}
50   Bölüm 5



          Nokta sınıfının son halini ve bu sınıftan birkaç tane nesne oluşturan ana programı Şekil 5.9’daki
          gibi yazabiliriz:

          Örnek Uygulama 5.9:
                1	public	class	Nokta
                2	{
                 private	int	x;
                3	
                 private	int	y;
                4	
                 public	Nokta()
                5	
                 {
                6	
                 	
                7	        x	=	0;
                 	
                8	        y	=	0;
                 }
                9	
                10	       public	Nokta(int	x,	int	y)
                11	       {
                12	       	       this.x	=	x;
                13	       	       this.y	=	y;
                14	       }
                15	       public	void	YerDegistir(int	yeniX,	int	yeniY)
                16	       {
                17	       	       x	=	yeniX;
                18	       	       y	=	yeniY;
                19	       }
                20	       public	double	UzaklikHesapla(Nokta	ikinciNokta)
                21	       {
                22	       	       return	UzaklikHesapla(ikinciNokta.x,	ikinciNokta.y);
                23	       }
                24	    public	double	UzaklikHesapla(int	ikinciNoktaX,	int	
                ikinciNoktaY)
                25	       {
                26	    	     double	uzaklik	=	Math.sqrt(Math.pow(x	-	
                ikinciNoktaX,	2)
                		        	       	       +	Math.pow(y	-	ikinciNoktaY,	2));
                27	       	       return	uzaklik;
                28	       }
                29}


                30	public	class	AnaProgram
                31{
                32	       public	static	void	main(String[]	args)
                33	       {
                       // Parametresiz yapıcı metodla bir Nokta nesnesi
                oluşturuldu
                34	       	       Nokta	nokta1	=	new	Nokta();
                35	       	       nokta1.YerDegistir(3,	5);
                                                                                             Yapısal Programlama   51




      // Parametreli yapıcı metodla bir Nokta nesnesi oluşturuldu
      36	        	        Nokta	nokta2	=	new	Nokta(5,	5);
                 // nokta1 ve nokta2 nesneleri arasındaki uzaklık nokta1
      nesnesi
                 // üzerinden hesaplandı
      37	        	        double	uzaklik	=	nokta1.UzaklikHesapla(nokta2);
      38                  System.out.println(uzaklik); // Ekrana 2.0 değeri
      basıldı
                 // nokta1 ve nokta2 nesneleri arasındaki uzaklık nokta2
      nesnesi
                 // üzerinden hesaplandı
      39	        	        uzaklik	=	nokta2.UzaklikHesapla(nokta1);
      40                  System.out.println(uzaklik); // Ekrana 2.0 değeri
      basıldı
                 // nokta1 nesnesinin yeni koordinatları (4, 6) değerini
      aldı
      41	        	        nokta1.YerDegistir(4,	6);
             // nokta1 nesnesinin (5, 7) koordinatlarında bulunan
      noktaya uzaklığı
                 // hesaplandı
      42	        	        uzaklik	=	nokta1.UzaklikHesapla(5,	7);
      43                  System.out.println(uzaklik); // Ekrana 1.414 değeri
      basıldı
      44	        }
      45}


Nesne Yönelimli Programlamanın Temel Kavramları
Kapsülleme (Encapsulation)
Bir nesnenin içinde yer alan niteliklerin ve iş mantığının nesneyi kullanan kişiler tarafından gö-
rülmesinin veya değiştirilmesinin engellenmesine kapsülleme denir. Kapsüllemede temel amaç
nesneyi kullanacak kişilerin iş akışıyla ilgili gereksiz detaylarla uğraşmamasını sağlamak ve nes-
nelerin içinde bulunan hassas verilerin değiştirilmesini engellemektir.

Günlük hayatta düzenli olarak kullandığımız bir mönitör nesnesi üzerinden örnek verelim: Moni-
törümüzün içinde birçok elektronik devre elemanı olduğunu bilsek de bu devrelerin nasıl çalıştığı
hakkında çoğumuzun bir fikri bulunmamaktadır. Monitörün içinde bulunan elektronik elemanlar
ve bunların çalışma mantıkları son kullanıcıdan soyutlanmış durumdadır. Monitörün dışında yer
alan kılıfın bulunmadığını ve monitör üzerinde herhangi bir işlem yapmak için çeşitli devre ele-
manlarının değerlerini değiştirmek zorunda kaldığımızı düşünecek olursak bahsettiğimiz gereksiz
karmaşıklığın ne anlama geldiğini daha iyi anlayabiliriz. Bahsedilen durumda monitör gibi basit
bir nesneyi kullanmak için yoğun çaba harcamamız gerekeceği gibi yanlış bir hareketle içerideki
yapılara zarar vermemiz de ihtimal dahilinde olacaktır.

Monitörün kullanıcıyla etkileşim kurmak için düğmelerden oluşan bir iletişim arayüzüne sahip
olması gibi, yazılımsal olarak gerçeklediğimiz nesnelerimizin de kendilerini kullanacak yazılım-
cılarla aralarında bir iletişim arayüzü bulundurmaları kullanımı kolaylaştıracaktır. Sınıflarımızın
içinde bulunan niteliklerin ve metodların sadece ihtiyaç duyulduğu kadarının kullanıcıya açılması
kapsülleme mantığı çerçevesinde gerçeklenebilir.

Daha önce anlatıldığı gibi nitelikler ve metodların erişimi aşağıdaki gibi kısıtlanabilir:
52   Bölüm 5



          Şekil 5.1:
           Erişim tipi              Anlamı
           public                   Sınıfın içinden, dışından ve türetilmiş sınıflardan.
           protected                Sınıfın ve türetilmiş sınıfların içinden.
           private                  Sadece sınıfın içinden.

          Genel olarak sınıf içindeki bütün niteliklerin private veya protected olarak tanımlanması tav-
          siye edilmektedir. Sınıfı kullanacak olan yazılımcıların sınıf içinde bulunan niteliklere kendilerine
          sağlanan bağlantı noktaları üzerinden erişmesi getveset metodları yardımıyla sağlanabilir.

          Örnek Uygulama 5.10:
                1	public	class	BankaHesabi
                2	{
                 public	int	hesapNumarasi;
                3	
                 public	double	bakiye;
                4	
                 public	boolean	ParaCek(double	miktar)
                5	
                 {
                6	
                 	
                7	         if	(miktar	<=	this.bakiye)
                 	
                8	         {
                 	
                9	         	       this.bakiye	-=	miktar;
                10	        	       	         return	true;
                11	        	       }
                12	        	       else
                13	        	       {
                14	        	       	         return	false;
                15	        	       }
                16	        }
                17	        public	void	ParaYatir(double	miktar)
                18	        {
                19	        	       this.bakiye	+=	miktar;
                20	        }
                21}
                22public	class	AnaProgram
                23{
                24	        public	static	void	main(String[]	args)
                25	        {
                26	        	       BankaHesabi	hesap	=	new	BankaHesabi();
                27	        	       hesap.hesapNumarasi	=	12003345;
                28	        	       hesap.ParaYatir(1500);
                29	        	       hesap.ParaCek(500);
                30                 hesap.bakiye -= 1500;                  // iş akışının dışına çıkıldı
                31	        }
                32}
          Kodun açıklaması: BankaHesabi, hesap numarası ve bakiye verilerini tutan basit bir sınıf-
          tır. Para çekmek için ParaCek metodunun, para yatirmak içinse ParaYatir metodunun kulla-
          nılması öngörülmüştür. BankaHesabi sınıfı içindeki hesapNumarasivebakiye niteliklerinin
                                                                                  Yapısal Programlama   53



public olmasından dolayı, Main metodunda oluşturulan bir BankaHesabi nesnesinin bakiye
değeri ParaCek veya ParaYatir metodları kullanılmadan da değiştirilebilir. Bakiyenin yetersiz
olması durumunda bile istenen miktar hesaptan çekilebilmekte, bu nedenle iş akışının doğru ola-
rak gerçekleştirilmesi Main metodunu yazan kişiye bağlı olmaktadır.

Sınıfın aşağıdaki şekilde tasarlanması banka hesabıyla ilgili iş akışının tamamen BankaHesabi
sınıfı içinde yer almasını sağlamaktadır:

Örnek Uygulama 5.11:

      1	public	class	BankaHesabi
      2	{
       private	int	hesapNumarasi;
      3	
       private	double	bakiye;
      4	
       public	boolean	ParaCek(double	miktar)
      5	
       {
      6	
       	
      7	        if	(miktar	<=	this.bakiye)
       	
      8	        {
       	
      9	        	       this.bakiye	-=	miktar;
      10	       	       	       return	true;
      11	       	       }
      12	       	       else
      13	       	       {
      14	       	       	       return	false;
      15	       	       }
      16	       }
      17	       public	void	ParaYatir(double	miktar)
      18	       {
      19	       	       this.bakiye	+=	miktar;
      20	       }
      21	       public	int	getHesapNumarasi()
      22	       {
      23	       	       return	this.hesapNumarasi;
      24	       }
      25	       public	void	setHesapNumarasi(int	hesapNo)
      26	       {
      27	       	       this.hesapNumarasi	=	hesapNo;
      28	       }
      29	       public	double	getBakiye()
      30	       {
      31	       	       return	this.bakiye;
      32	       }
      33}


      34public	class	AnaProgram
      35{
      36	       public	static	void	main(String[]	args)
   Bölüm 5




                37	        {
                38	        	        BankaHesabi	hesap	=	new	BankaHesabi();
                39	        	        hesap.setHesapNumarasi(12003345);
                40	        hesap.ParaYatir(1500);
                41	        hesap.ParaCek(500);
                42	        //	hesap.bakiye	-=	1500;
                43		}
                44}

          Kodun açıklaması: BankaHesabi sınıfındaki hesapNumarasi ve bakiye niteliklerinin eri-
          şim kısıtları private olarak değiştirilmiştir. Böylece bu alanlara dışarıdan erişim engellenmiştir.
          hesapNumarasi niteliğinin değeri getHesapNumarasi metodu üzerinden, bakiye niteliğinin
          değeri getBakiye metodu üzerinden okunabilmektedir. hesapNumarasi niteliğine setHesap-
          Numarasi metodu aracılığıyla yeni bir değer atanabilmesine rağmen bakiye değeri sadece Pa-
          raCekveParaYatir metodları kullanılarak değiştirilebilmektedir. Böylece bakiye değişikliği iş-
          leminin arkasındaki iş mantığı sadece ilgili metodlar yardımıyla belirlenmekte ve sınıfı kullanacak
          olan yazılımcının bu konu üzerinde çalışmasına gerek kalmamaktadır. Ana programdaki yorum
          satırı haline getirilmiş olan kod parçası derleme hatası vermektedir. Bu derleme hatasının sebebi
          bakiye alanının private olarak tanımlanmış olmasıdır.

          .Net Platformu üzerinde bulunan Property kavramının Java Platformunda doğrudan bir karşılığı
          bulunmamaktadır. Bunun yerine niteliğin adının başına get veya set sözcüklerinin eklenmesiyle
          oluşturulan metodların kullanılması gelenekselleşmiştir.

          Kodun Tekrar Kullanımı
          Kodun tekrar kullanımı, daha önce yazılmış olan ve belirli bir işlemi gerçekleştiren kod bloklarının
          aynı projenin farklı bir yerinde veya başka bir projede kullanılmasıdır. Bu işlem yazılımın gerçek-
          lenmesi aşamasındaki kodlama maliyetlerini düşürdüğü gibi sistemde yapılacak değişikliklerin
          de daha düşük maliyetle gerçekleştirilmesini sağlar. Yapısal programlama teknolojilerinde kodun
          yeniden kullanımı kavramı bulunsa da, gerçeklenen işlevler fonksiyon bazında olduğundan iki
          farklı proje arasında kod aktarımı sınırlı kalır, genelde kodun önemli bir kısmının veya hepsinin
          yeniden yazılması gerekir. Nesne yönelimli programlama teknolojilerinde ise temel amaçlardan
          biri kodun yeniden kullanımını sağlayarak projelerin zaman ve iş gücü maliyetlerini mümkün
          olduğu kadar düşürmektir. Nesne yönelimli yaklaşımda kodun tekrar kullanımı sınıf bazında ger-
          çeklenir ve daha önce oluşturulmuş olan sınıflar aynı proje içinde veya farklı projelerde esnek
          olarak kullanılır.

          Nesne yönelimli dillerde kodun tekrar kullanımı birkaç farklı şekilde sağlanabilir:

          1� Daha önce oluşturulmuş sınıflardan oluşturulan nesneler uygulama içinde kullanılabilir.
          2. Daha önce oluşturulmuş sınıflardan oluşturulan nesneler yeni oluşturulan sınıfların içinde bu-
             lunabilir ve bir sınıf değişik tiplerde ve sayılarda nesne içerebilir. Bu ilişkiye composition adı
             verilir ve genel olarak “sahip olma” (has-a) ilişkisi olarak tanımlanır.
          3� Daha önce oluşturulmuş sınıflardan yeni sınıfların türetilmesi ile ile uygulamanın genişletilmesi
             sağlanır. Bu kavram kalıtım adını alır ve genel olarak “olma” (is-a) ilişkisi olarak tanımlanır.

          Kalıtım
          Kalıtım; bir sınıfın daha önce oluşturulmuş başka bir sınıftan türetilmesidir. Kalıtım sayesinde ön-
          ceden gerçeklenmiş özelliklerin ve davranışların yeniden gerçeklenmesine gerek kalmaz, kodun
          tekrar kullanımı sağlanmış olur. İki farklı iş kavramının modellenmesi sırasında aralarında kalıtım
          ilişkisi olduğuna karar vermek için türetilecek olan sınıfın, temel sınıfın sahip olduğu bütün özel-
          liklere sahip olduğundan emin olmak gerekir. En basit yaklaşımla, iki farklı kavram arasında olma
          (is-a) ilişkisi kurulabiliyorsa iki sınıf arasında kalıtım ilişkisi vardır. Kalıtım ilişkisi uygulamanın
                                                                                         Yapısal Programlama   



ihtiyaçlarına göre iki veya daha fazla sınıf arasında olmak üzere tasarlanabilir. .Net Platformunda
olduğu gibi Java Platformunda da çoklu kalıtım desteklenmez, bir sınıf sadece bir sınıftan türeti-
lebilir.

Örnek: Bir şirketteki çalışanları modellemek için bir yazılım tasarladığımızı varsayalım.

İlk aşamada bütün çalışanlarımızı Calisan adlı bir sınıf ile temsil edelim. Bu durumda bütün
çalışan nesnelerimiz aynı sınıftan oluşturulacaği için farklı çalışan tiplerine özel bilgilerin ve dav-
ranışların Calisan sınıfından oluşturulan nesnelerde saklanması mümkün olmaz.

Örnek Uygulama 5.12: Çalışan sınıfının ilk hali
      1	public	class	Calisan
      2	{
       private	String	ad;
      3	
       private	String	soyad;
      4	
       public	Calisan(String	ad,	String	soyad)
      5	
       {
      6	
       	
      7	         this.ad	=	ad;
       	
      8	         this.soyad	=	soyad;
       }
      9	
      10}
Tasarladığımız uygulamayı biraz daha geliştirerek farklı çalışan tiplerini temsil etmek üzere özel-
leşmiş çalışan sınıfları oluşturabiliriz. private erişim tipine sahip alanların erişim tipini protec-
ted olarak değiştirirsek bu niteliklere türetilmiş sınıflardan ulaşılmasını da sağlarız.

Örnek Uygulama 5.13:

      1	public	class	Calisan
      2	{
       protected	String	ad;
      3	
       protected	String	soyad;
      4	
      5
       public	Calisan(String	ad,	String	soyad)
      6	
       {
      7	
       	
      8	         this.ad	=	ad;
       	
      9	         this.soyad	=	soyad;
      10	        }
      11}


      12public	class	Muhendis	extends	Calisan
      13{
      14	        protected	String[]	projeler;
      15	        protected	String	departman;
      16	        protected	int	projeSayisi;
      17	        public	Muhendis(String	ad,	String	soyad,	String	departman)
      18	        {
      19	        	        super(ad,	soyad);
      20	        	        this.departman	=	departman;
   Bölüm 5




                21	        	       this.projeler	=	new	String[5];
                22	        	       this.projeSayisi	=	0;
                23	        }
                24	        public	void	ProjeEkle(String	proje)
                25	        {
                26	        	       projeler[projeSayisi]	=	proje;
                27	        	       projeSayisi++;
                28	        }
                29}

          Calisan sınıfında sadece niteliklerin erişim tipini protected olarak değiştirdik ve yeni ekle-
          nen Muhendis sınıfının Calisan sınıfından türemesini “extends” anahtar kelimesi ile sağladık.
          “extends” anahtar kelimesi, C# dilindeki “:” operatörünün karşılığıdır. Muhendis sınıfının içinde
          bulunan projeler adındaki string dizisi ile belirli bir mühendisin üzerinde çalıştığı projeleri tutu-
          yoruz ve ProjeEkle metodu yardımıyla belirli bir mühendisin projelerine ekleme yapabiliyoruz.

          Muhendis sınıfımızın yapıcı metodu ad, soyadvedepartman olmak üzere üç tane parametre
          alır. Departman parametresi Muhendis sınıfı içindeki departman niteliğine ilk değer vermek için
          kullanılırken ad ve soyad parametreleri “super” anahtar kelimesi yardımıyla temel sınıf olan
          Calisan sınıfının yapıcı metodunu çalıştırmak için kullanılır. Muhendis sınıfında super(ad,
          soyad) komutuyla Calisan sınıfının yapıcı metodunu çağırmazsak derleme hatası alırız. Bu-
          nun sebebi türetilmiş sınıflardan nesne oluşturulurken sırasıyla temel ve türetilmiş sınıfların yapıcı
          metodlarının çağrılmasıdır. Örnek Uygulama 5.14, temel ve türetilmiş sınıflarda yapıcı metodların
          çalışmasını göstermektedir:

          Örnek Uygulama 5.14:
                1	public	class	TemelSinif	
                2	{
                 public	TemelSinif()
                3	
                 {
                4	
                 	
                5	         System.out.println(“Temel sınıfın yapıcı metodu çalıştı”);
                 }
                6	
                7	}	


                8	public	class	TuretilmisSinif	extends	TemelSinif	
                9	{
                10	        public	TuretilmisSinif()
                11	        {
                12	    	           System.out.println(“Türetilmiş sınıfın yapıcı metodu
                çalıştı”);
                13	        }
                14}	


                15public	class	AnaProgram	
                16{
                17	        public	static	void	main(String[]	args)	
                18	        {
                                                                                      Yapısal Programlama   




      19	    	     TuretilmisSinif	turetilmisNesne	=	new	
      TuretilmisSinif();
      20	       }
      21}	

Program çalıştırıldığında ekranda çıkan mesajlar şu şekildedir:

      Temel sınıfın yapıcı metodu çalıştı
      Türetilmiş sınıfın yapıcı metodu çalıştı

Çalışan modelimizi biraz daha genişleterek mühendisleri branşlarına göre farklı sınıflara ayırırsak
ve bir Muhasebeci sınıfı eklersek sınıfların son hali aşağıdaki gibi olur.

Örnek Uygulama 5.15:

      1	public	class	Calisan
      2	{
       protected	String	ad;
      3	
       protected	String	soyad;
      4	
       public	Calisan(String	ad,	String	soyad)
      5	
       {
      6	
       	
      7	        this.ad	=	ad;
       	
      8	        this.soyad	=	soyad;
       }
      9	
      10}


      11public	class	Muhendis	extends	Calisan
      12{
      13	       protected	String[]	projeler;
      14	       protected	String	departman;
      15	       protected	int	projeSayisi;
      16	       public	Muhendis(String	ad,	String	soyad,	String	departman)
      17	       {
      18	       	        super(ad,	soyad);
      19	       	        this.departman	=	departman;
      20	       	        this.projeler	=	new	String[5];
      21	       	        this.projeSayisi	=	0;
      22	       }
      23	       public	void	ProjeEkle(String	proje)
      24	       {
      25	       	        projeler[projeSayisi]	=	proje;
      26	       	        projeSayisi++;
      27	       }
      28}	


      29public	class	BilgisayarMuhendisi	extends	Muhendis
      30{
      31	       protected	String[]	programlamaDilleri;
   Bölüm 5




               32	     protected	int	programlamaDiliSayisi;
               33	    public	BilgisayarMuhendisi(String	ad,	String	soyad,	String	
               departman)
               34	     {
               35	     super(ad,	soyad,	departman);
               36	     this.programlamaDilleri	=	new	String[5];
               37	     this.programlamaDiliSayisi	=	0;
               38	     }
               39	     public	void	ProgramlamaDiliEkle(String	programlamaDili)
               40	     {
               41	    programlamaDilleri[programlamaDiliSayisi]	=	
               programlamaDili;
               42	     programlamaDiliSayisi++;
               43		}
               44}


               45public	class	MakinaMuhendisi	extends	Muhendis
               46{
               47	     private	String[]	modellemeProgramlari;
               48	     private	int	modellemeProgramiSayisi;
               49	    public	MakinaMuhendisi(String	ad,	String	soyad,	String	
               departman)
               50	     {
               51	     	    super(ad,	soyad,	departman);
               52	     	    this.modellemeProgramlari	=	new	String[5];
               53	     	    this.modellemeProgramiSayisi	=	0;
               54	     }
               55	    public	void	ModellemeProgramiEkle(String	
               modellemeProgrami)
               56	     {
               57	    	     modellemeProgramlari[modellemeProgramiSayisi]	=	
               modellemeProgrami;
               58	     	    modellemeProgramiSayisi++;
               59	     }
               60}


               61public	class	Muhasebeci	extends	Calisan
               62{
               63	     private	String[]	muhasebeProgramlari;
               64	     private	int	muhasebeProgramiSayisi;
               65	     public	Muhasebeci(String	ad,	String	soyad)
               66	     {
               67	     	    super(ad,	soyad);
               68	     	    this.muhasebeProgramlari	=	new	String[5];
               69	     	    this.muhasebeProgramiSayisi	=	0;
                                                                                        Yapısal Programlama   




      70	        }
      71	        public	void	MuhasebeProgramiEkle(String	muhasebeProgrami)
      72	        {
      73	    	     muhasebeProgramlari[muhasebeProgramiSayisi]	=	
      muhasebeProgrami;
      74	        	       muhasebeProgramiSayisi++;
      75	        }
      76	        public	void	MuhasebeProgramiEkle(String	muhasebeProgrami)
      77	        {
      78	        	       if	(!muhasebeProgramlari.contains(muhasebeProgrami))
      79	        	       	        muhasebeProgramlari.add(muhasebeProgrami);
      80	        }
      81}

Çok Şekillilik (Polymorphism)
Çok şekillilik, bir nesnenin çalışma aşamasında hangi tipten olduğunu bilmesi ve kendi tipine
göre davranış sergilemesidir. Oluşturduğumuz iş modeli çerçevesinde bir müdür ve bu müdüre
bağlı çalışanlar bulunduğunu ve bütün çalışanların rapor verme kabiliyetine sahip olduğunu var-
sayalım. Müdür aynı anda bütün çalışanlardan kendisine haftalık rapor vermelerini istediğinde
aşağıdaki iki yöntemle istekte bulunabilir:

1� Yalçın Bey Bilgisayar Mühendisliği ile ilgili rapor göndersin, Erkut Bey muhasebecilikle ilgili
   rapor göndersin.
2. Bütün çalışanlar rapor göndersin.
3� Rapor isteme-gönderme mekanizmasının işlevsel olması için ikinci senaryonun kullanılması-
   nın daha mantıklı olduğunu söyleyebiliriz. Şirket müdürü bütün çalışanlarından rapor isterken
   tek tek yaptıkları işe göre rapor isteyecek olursa bunun gereksiz zaman kaybına yol açacağı
   rahatlıkla gözlenebiliyor.
Çok şekillilik, ikinci senaryomuzu gerçekleyen yapıdır. Gerçek hayattaki mühendislerin ve mu-
hasebecilerin hangi işi yaptıklarını bilmeleri gibi, nesne yönelimli yazılımda da nesneler çalışma
aşamasında hangi işi nasıl yaptıklarını bilirler ve ona göre davranırlar. Bu durumda rapor verme
davranışı farklı nesne tiplerine göre farklı şekillerde çalışabildiğinden çok şekilli bir davranıştır.

.Net ortamında metodların çok şekilliliği desteklemesi için “virtual” olarak tanımlanması gerekir,
Java ortamında ise metodlar varsayılan olarak çok şekilliliği destekler. Çok şekillilik yapısı sadece
kalıtım ilişkisi içinde olan sınıflar arasında kullanılabilir.

Örneğimizin çok şekilliliği destekleyen hali Örnek Uygulama 5.16’daki gibi olacaktır:

Örnek Uygulama 5.16:
      1	public	class	Calisan
      2	{
       protected	String	ad;
      3	
       protected	String	soyad;
      4	
       public	Calisan(String	ad,	String	soyad)
      5	
       {
      6	
       	
      7	         this.ad	=	ad;
       	
      8	         this.soyad	=	soyad;
       }
      9	
60   Bölüm 5




               10	     public	void	RaporVer()
               11	     {
               12	     	    System.out.println(“Ad:	“	+	ad	+	“	Soyad:	“	+	
               soyad);
               13	     }
               14}


               15public	class	Muhendis	extends	Calisan
               16{
               	 17	   protected	String[]	projeler;
               	 18	   protected	String	departman;
               	 19	   protected	int	projeSayisi;
               	 20	   public	Muhendis(String	ad,	String	soyad,	String	departman)
               	 21	   {
               	 22	   	    super(ad,	soyad);
               	 23	   	    this.departman	=	departman;
               	 24	   	    this.projeler	=	new	String[5];
               	 25	   	    this.projeSayisi	=	0;
               	 26	   }
               27	     public	void	ProjeEkle(String	proje)
               28	     {
               29	     	    projeler[projeSayisi]	=	proje;
               30	     	    projeSayisi++;
               31	     }
               32	     public	void	RaporVer()
               33	     {
               34	     	    super.RaporVer();
               35	     	    System.out.println(“Departman:	“	+	departman);
               36	     	    System.out.println(“Projeler:	“);
               37	     	    for	(int	i	=	0;	i	<	projeSayisi;	i++)
               38	     	    {
               39	     	    	     System.out.println(“\t”	+	projeler[i]);
               40	     	    }
               41	     }
               42}

               43public	class	BilgisayarMuhendisi	extends	Muhendis
               44{
               45	     protected	String[]	programlamaDilleri;
               46	     protected	int	programlamaDiliSayisi;
               47	    public	BilgisayarMuhendisi(String	ad,	String	soyad,	String	
               departman)
               48	     {
               49	     	    super(ad,	soyad,	departman);
               50	     	    this.programlamaDilleri	=	new	String[5];
                                                          Yapısal Programlama   61




51	    	     this.programlamaDiliSayisi	=	0;
52	    }
53	    public	void	ProgramlamaDiliEkle(String	programlamaDili)
54	    {
55	    	     programlamaDilleri[programlamaDiliSayisi]	=	
programlamaDili;
56	    	     programlamaDiliSayisi++;
57	    }
58	    public	void	RaporVer()
59	    {
60	    	     super.RaporVer();
61	    	     System.out.println(“Görev:	Bilgisayar	Mühendisi”);
62	    	     System.out.println(“Programlama	Dilleri:	“);
63	    	     for	(int	i	=	0;	i	<	this.programlamaDiliSayisi;	i++)
64	    	     {
65	    	     	     System.out.println(“\t”	+	
programlamaDilleri[i]	+	“	“);
66	    	     }
67	    }
68}


69public	class	MakinaMuhendisi	extends	Muhendis
70{
71	    private	String[]	modellemeProgramlari;
72	    private	int	modellemeProgramiSayisi;
73	    public	MakinaMuhendisi(String	ad,	String	soyad,	String	
departman)
74	    {
75	    	     super(ad,	soyad,	departman);
76	    	     this.modellemeProgramlari	=	new	String[5];
77	    	     this.modellemeProgramiSayisi	=	0;
78	    }
79	    public	void	ModellemeProgramiEkle(String	
modellemeProgrami)
80	    {
81	    	     modellemeProgramlari[modellemeProgramiSayisi]	=	
modellemeProgrami;
82	    	     modellemeProgramiSayisi++;
83	    }
84	    public	void	RaporVer()
85	    {
86	    	     super.RaporVer();
87	    	     System.out.println(“Görev:	Makina	Mühendisi”);
88           System.out.println(“Modelleme Programları: “);
89	    	     for	(int	i	=	0;	i	<	modellemeProgramiSayisi;	i++)
62   Bölüm 5




               90	    	     {
               91	    	     	     System.out.println(“\t”	+	
               modellemeProgramlari[i]	+	“	“);
               92	    	     }
               93	    }
               94}


               95public	class	Muhasebeci	extends	Calisan
               96{
               97	    private	String[]	muhasebeProgramlari;
               98	    private	int	muhasebeProgramiSayisi;
               99	    public	Muhasebeci(String	ad,	String	soyad)
               100	   {
               101	   	     super(ad,	soyad);
               102	   	     this.muhasebeProgramlari	=	new	String[5];
               103	   	     this.muhasebeProgramiSayisi	=	0;
               104	   }
               105	   public	void	MuhasebeProgramiEkle(String	muhasebeProgrami)
               		     {
               106	   	     muhasebeProgramlari[muhasebeProgramiSayisi]	=	
               muhasebeProgrami;
               107	   	     muhasebeProgramiSayisi++;
               108	   }
               109	   public	void	RaporVer()
               110	   {
               111	   	     super.RaporVer();
               112	   	     System.out.println(“Görev:	Muhasebeci”);
               113          System.out.println(“Muhasebe Programları: “);
               114	   	     for	(int	i	=	0;	i	<	muhasebeProgramiSayisi;	i++)
               115	   	     {
               116	   	     	     System.out.println(“\t”	+	
               muhasebeProgramlari[i]);
               117	   	     }
               118	   }
               119}


               120public	class	Mudur
               121{
               122	   private	Calisan[]	calisanlar;
               123	   private	int	calisanSayisi;
               124	   public	Mudur()
               125	   {
               126	   	     this.calisanlar	=	new	Calisan[5];
               127	   	     this.calisanSayisi	=	0;
               128	   }
                                                                     Yapısal Programlama   63




      129	       public	void	CalisanEkle(Calisan	calisan)
      130	       {
      131	       	        calisanlar[calisanSayisi]	=	calisan;
      132	       	        calisanSayisi++;
      133	       }
      134	       public	void	RaporIste()
      135	       {
      136	       	        for	(int	i	=	0;	i	<	calisanSayisi;	i++)
      137	       	        {
      138	       	        	        calisanlar[i].RaporVer();
      139	       	        	        System.out.println();
      140	       	        }
      141	       }
      142}


      143public	class	AnaProgram
      144{
      145	       public	static	void	main(String[]	args)
      146	       {
      147	   	     BilgisayarMuhendisi	blgMuh	=	new	BilgisayarMuhendisi
      (“Yalçın”, “Kaya”, “IT”);
      148	       	        blgMuh.ProgramlamaDiliEkle(“Java”);
      149	       	        blgMuh.ProgramlamaDiliEkle(“C#”);
      150	   	     MakinaMuhendisi	mknMuh	=	new	
      MakinaMuhendisi(“Hasan”, “Polat”, “Bakım”);
      151	       	        mknMuh.ModellemeProgramiEkle(“Katia”);
      152	   	            Muhasebeci	muhasebeci	=	new	Muhasebeci(“Erkut”,	
      “Kutlar”);


      153	       	        Mudur	genelMudur	=	new	Mudur();
      154	       	        genelMudur.CalisanEkle(blgMuh);
      155	       	        genelMudur.CalisanEkle(mknMuh);
      156	       	        genelMudur.CalisanEkle(muhasebeci);
      157	       	        genelMudur.RaporIste();
      158	       }
      159}

Program çalıştırıldığında aşağıdaki gibi bir çıktı üretir:

      Ad: Yalçın Soyad: Kaya
      Departman:	IT
      Projeler:	
      Görev:	Bilgisayar	Mühendisi
      Programlama	Dilleri:	
      	 Java	
      	 C#	
   Bölüm 5



                Ad:	Hasan	Soyad:	Polat
                Departman: Bakım
                Projeler:	
                Görev:	Makina	Mühendisi
                Modelleme Programları:
                	 Katia	


                Ad:	Erkut	Soyad:	Kutlar
                Görev:	Muhasebeci
                Muhasebe Programları:

          Mudur sınıfının içinde, çalışanları tutmak için Calisan sınıfı cinsinden bir dizi kullandık. Ana
          programda oluşturduğumuz üç tane farklı tipte çalışanı (bilgisayar mühendisi, makina mühendi-
          si, muhasebeci) müdür nesnemizin çalışanlarına ekledik. Mudur sınıfının RaporIste metodu
          butun çalışanlardan rapor istemek amacıyla yazıldı. Müdür nesnesinin RaporIste metodunu
          çalıştırdığımızda bütün çalışan nesnelerinin kendi tiplerine ait raporları oluşturduğunu görüyoruz.
          Raporların doğru bir şekilde oluşması RaporVer metodunun çok şekilli olduğunu gösterir. Müdür
          sınıfında bütün çalışan bilgilerinin Calisan sınıfından oluşan bir dizide tutulmasından dolayı
          derleme aşamasında çalışanların tipi belli değildir. Eğer RaporVer metodu çok şekilli olmasaydı,
          müdür nesnesinin RaporIste metodu çağrıldığında çalışanların hepsi derleme aşamasında ol-
          duğu gibi çalışma aşamasında da temel Calisan sınıfının raporunu oluşturacaktı.
6   Swing
6 Swing
• Swing’e Giriş

• Klavye Event’lerinin Yönetilmesi
                                          Swing
Java platformunun 1.0 versiyonunda görsel kullanıcı arayüzleri oluşturmak için AWT (Abstract
Windowing Toolkit) teknolojisi kullanılıyordu. AWT’nin temel amacı Java programlarının arayüz-
lerini işletim sisteminden bağımsız hale getirmek olsa da bu amaca ulaşılamadı. AWT paketinin
içinde bulunan bileşenler işletim sistemine bağımlı olduğundan farklı işletim sistemleri üzerinde
faklı görünümlere sahip olan programlar ortaya çıktı. Java platformunun 2.0 versiyonuyla birlikte
AWT paketinin üzerine Swing adı verilen yeni görsel programlama modeli de eklendi. Swing pa-
keti Java ile yazılmış olmasının da etkisiyle İşletim sisteminden bağımsız bir görsel programlama
modeli sunar. Yeni geliştirilen Java uygulamalarında Swing paketinin kullanılması uygulamanın
görsel arayüzünün güçlü olması için şarttır.

Bu bölümde Java platformunda bulunan Swing paketinin genel özellikleri ve bu paketin içinde
bulunan temel arayüz kontrolleri anlatılacaktır. Swing bu bölümde anlatılanlarla sınırlı değildir,
özellikle karmaşık kullanıcı etkileşimi gerektiren Java uygulamalarının geliştirebilmesi için Swing
teknolojisinin detaylı olarak incelenmesi gerekir.


Swing’e Giriş
.Net platformunda Windows uygulamaları geliştirirken kullandığımız kontrollerin benzerleri Java
platformunda da vardır. Swing kontrolleri çeşitli olayları (event) tetikleyerek uygulama arayüzüy-
le kullanıcının etkileşim halinde olmasına olanak tanır. Uygulamada kullanılan kontroller çeşitli
container’lar (saklayıcı) yardimiyla gruplanabilir. Java platformuyla işletim sistemi üzerinde ça-
lışan uygulamalar oluşturmak için uygulamanın görsel arayüzünü temsil edecek sınıfın JFrame
sınıfından türetilmesi gerekir. JFrame sınıfının içinde bulunan ve yeni oluşturulan sınıflara ka-
lıtımla aktarılan getContentPane metodu kullanılarak uygulamada bulunan kontrolleri içeren
Container nesnesine erişilir. Menü kontrolleri dışındaki bütün kontroller Container nesnesi
içinde bulunur ve Container nesnesi hiçbir zaman null (boş) değer almaz.

Container nesnesinin setLayout metodu uygulama arayüzünde kullanılacak yerleşim
düzenini(layout) belirlemek için kullanılır. Layout seçenekleri ilerleyen sayfalarda anlatılacaktır.
Boş bir arayüz oluşturan Java kodu Örnek Uygulama 6.1’de verilmiştir:

Örnek Uygulama 6.1:

      1	import	java.awt.Container;
      2	import	java.awt.FlowLayout;
      3	import	javax.swing.JFrame;
      4	public	class	IlkOrnek	extends	JFrame	
      5	{
       public	IlkOrnek()
      6	
       {
      7	
      8         super(“İlk Örnek”);
       	
      9	        Container	container	=	getContentPane();
      10	       	        container.setLayout(new	FlowLayout());
      11	       	        setSize(200,	200);
      12	       setVisible(true);
      13}
      14public	static	void	main(String[]	args)	
      15{
      16	       IlkOrnek	test	=	new	IlkOrnek();
      17	       test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   Bölüm 6




                    18}
                    19}

          Kodun açıklaması:IlkOrnek isimli sınıfımız JFrame sınıfından türetilmiştir. Yapıcı metod için-
          de  JFrame sınıfının yapıcı metodu super(“İlk Örnek”) kod bloğuyla çalıştırılır, oluşan ekranın
          başlığında “İlk Örnek” metni bulunur. Container nesnesi getContentPane metodu ile yukarı-
          da açıklandığı gibi alınır. Forma başka kontroller de ekleyecek olursak bu kontrolleri Container
          nesnesinin içine veya Container nesnesinin içinde bulunan bir nesneye eklememiz gerekir. Uy-
          gulamanın çalışması sırasında formun görünür hale gelmesi için boyutunu vermemiz ve setVi-
                                                sible metodunu kullanarak formu görünür hale getirmemiz
                                                gereklidir. Main metodunun içinde, yazdığımız sınıftan bir
                                                nesne oluşturarak formun oluşmasını sağlarız. JFrame sı-
                                                nıfından türetilmiş olan arayüzün kullanıcı tarafından kapa-
                                                tılması durumunda uygulamanın sonlandırılmasının sağlan-
                                                ması için test.setDefaultCloseOperation(JFrame.
                                                EXIT_ON_CLOSE); kod bloğunu Main metoduna ekleriz.
                                                Bu satırı eklemezsek, uygulama kapatıldığında varsayılan
                                                işlem olarak form görünmez hale gelindiği halde uygulama
                                                kapanmaz. Swing ile ilgili bütün örneklerde yukarıda verilen
                                                kodu kullanacağız.

                                               Uygulama çalıştırıldığında oluşan arayüz Şekil 1’deki gibi-
          Şekil 1                              dir.

          JButton
          .Net platformundaki Button kontrolünün karşılığı Java platformundaki JButton kontrolüdür. Te-
          mel olarak üzerinde bir metin yazılı olabilen ve kullanıcı tarafından üzerine tıklandığında event
          oluşturan bir yapıya sahiptir. Form üzerinde bir buton oluşturmak için JButton sınıfından bir
          nesne yaratılır ve Container nesnesine eklenir. JButton sınıfının yapıcı metodu butonun üze-
          rinde görüntülenecek metni parametre olarak alır. JButton nesnesi oluşturan ve formun üzerine
          ekleyen kod Örnek Uygulama 6.2’de gösterilmiştir.

          Örnek Uygulama 6.2:

                    1	import	java.awt.Container;
                    2	import	java.awt.FlowLayout;
                    3	import	javax.swing.JButton;
                    4import	javax.swing.JFrame;
                    5	public	class	JButtonTest	extends	JFrame	
                    6	{
                     private	JButton	btnTest;
                    7	
                     public	JButtonTest()
                    8	
                     {
                    9	
                    10            super(“JButton Örneği”);
                    11	    	      Container	container	=	getContentPane();
                    12	    	      container.setLayout(new	FlowLayout());	                   	
                    13            btnTest = new JButton(“Örnek Buton”);
                    14	    	      container.add(btnTest);		
                    15	    	      setSize(200,	200);
                    16	    	      setVisible(true);
                    17	    }
                                                                                               Swing   




      18	       public	static	void	main(String[]	args)	
      19	       {
      20	       	       JButtonTest	test	=	new	JButtonTest();
      21	       	       test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      22	       }
      23}

Kodun açıklaması: Formu oluşturan kod bloklarından farklı olarak bir adet JButton nesnesi
oluşturan ve Container nesnesine ekleyen kod satırları yukarıdadır. JButton sınıfının yapıcı
metoduna parametre olarak butonun üzerinde bulunmasını
istediğimiz metni veririz. Container nesnesinin add me-
todu herhangi bir kontrolün Container içine eklenmesini
sağlar. Uygulama çalıştırıldığında Şekil 2’deki gibi bir arayüz
oluşur.
Oluşturduğumuz butona henüz bir event eklemediğimiz için
butonun herhangi bir işlevi yoktur.

JLabel
JLabel kontrolü, .Net ortamındaki Label kontrolünün kar-
şılığıdır. Uygulama üzerinde metin görüntülemek istediğimiz
noktalarda kullanılır. Bir JLabel kontrolünün uygulama üze-
rinde görünür hale gelmesi için bir JLabel nesnesi oluştu-    Şekil 2
rup Container nesnesine eklememiz yeterlidir. Örnek kod
Örnek Uygulama 6.3’de verilmiştir.

Örnek Uygulama 6.3:

      1	import	java.awt.Container;
      2	import	java.awt.FlowLayout;
      3	import	javax.swing.JFrame;
      4	import	javax.swing.JLabel;
      5	public	class	JLabelTest	extends	JFrame
      6	{
       private	JLabel	lblTest;
      7	
       public	JLabelTest()
      8	
       {
      9	
      10                super(“JLabel Kullanımı”);
      11	       	       Container	container	=	getContentPane();
      12	       	       container.setLayout(new	FlowLayout());
      13                lblTest = new JLabel(“JLabel Örneği”);
      14	       	       container.add(lblTest);		
      15	       	       setSize(200,	200);
      16	       	       setVisible(true);
      17	       }
      18	       public	static	void	main(String[]	args)	
      19	       {
      20	       	       JLabelTest	test	=	new	JLabelTest();
      21	       	       test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      22	       }
      23}
70   Bölüm 6



          Kodun açıklaması: lblTest adındaki JLabel nesnesin yapıcı metoduna parametre olarak
          üzerinde görüntülenecek metin verilmiştir. Container nesnesinin add metodu kullanılarak JLa-
          bel nesnesinin form üzerinde görüntülenmesi sağlanmıştır. Label üzerindeki metni uygulama-
                                              nın çalışma aşamasında değiştirmek için setText metodu,
                                              label üzerindeki metni almak için getText metodu kul-
                                              lanılır. Bu iki metodun kullanımıyla ilgili örneği daha sonra
                                              vereceğiz. Uygulama çalıştırıldığı zaman Şekil 3’de olduğu
                                              gibi görünür.

                                              JTextField
                                              JTextField kontrolü, .Net ortamındaki TextBox kontrolü-
                                              lün Java ortamındaki karşılığıdır. Kullanıcı tarafından girile-
                                              cek metin türünden bilgileri uygulamaya aktarmak amacıyla
                                              kullanılır. Bir JTextField kontrolünün uygulama üzerinde
                                              görünür hale gelmesi için bir JTextField nesnesi oluştu-
          Şekil 3                             rup Container nesnesine eklememiz yeterlidir. Örnek kod,
                                              Örnek Uygulama 6.4’te verilmiştir.

          Örnek Uygulama 6.4:

                    1	import	java.awt.Container;
                    2	import	java.awt.FlowLayout;
                    3	import	javax.swing.JFrame;
                    4	import	javax.swing.JLabel;
                    5	import	javax.swing.JTextField;
                    6	public	class	JTextFieldTest	extends	JFrame
                    7	{
                     private	JTextField	txtTest;
                    8	
                     public	JTextFieldTest()
                    9	
                    10	    {
                    11            super(“JTextField Kullanımı”);
                    12	    	      Container	container	=	getContentPane();
                    13	    	      container.setLayout(new	FlowLayout());
                    14            txtTest = new JTextField(“JTextField Örneği”);
                    15	    	      container.add(txtTest);		
                    16	    	      setSize(200,	200);
                    17	    	      setVisible(true);
                    18	    }
                    19	    public	static	void	main(String[]	args)	
                    20	    {
                    21	    	      JTextFieldTest	test	=	new	JTextFieldTest();
                    22	    	      test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    23	    }
                    24}

          Kodun açıklaması: txtTest adındaki JTextField nesnesin yapıcı metoduna parametre ola-
          rak üzerinde görüntülenecek metin verilmiştir. Container nesnesinin add metodu kullanılarak
          JTextField nesnesinin form üzerinde görüntülenmesi sağlanmıştır. JTextField üzerindeki
          metni uygulamanın çalışma aşamasında değiştirmek için setText metodu, label üzerindeki
                                                                                                           Swing   71



metni almak için getText metodu kullanılır. Bu iki metodun kullanımıyla ilgili örneği daha sonra
vereceğiz. Uygulama çalıştırıldığı zaman Şekil 4’teki gibi görünür.




                                 Şekil 4


Event Handling Mekanizması
Kullanıcıların Swing kontrolleri aracılığıyla uygulamayla iletişim kurması sonucunda çeşitli
event’ler (olaylar) oluşur. Bu event’leri kontrol etmek (handle) için .Net ortamından farklı olarak
event sınıfları kullanmamız gerekir. Java ortamında herşeyi sınıflar halinde kullanmak gibi bir
amaç olduğundan event handling mekanizması .Net ortamındakinden farklıdır. Net uygulama-
larında herhangi bir event için bir tane metod yazmak yeterli olurken Java’da bu işlem için harici
veya dahili (inner class) bir sınıf yazarak çeşitli event tipleri için özelleşmiş event interface’lerini
implemente etmemiz gerekir. Herhangi bir event birden fazla Swing kontrolü tarafından kulla-
nılabilir, boyle bir kullanımda event’in hangi kontrol üzerinden oluştuğunu öğrenmek için event
parametreleri kullanılır. JLabel, JTextFieldveJButton kontrolleriyle birlikte event mekaniz-
masini örnek kodu, Örnek Uygulama 6.5 üzerinden inceleyelim:

Örnek Uygulama 6.5:
      1	import	java.awt.Container;
      2	import	java.awt.FlowLayout;
      3	import	java.awt.event.ActionEvent;
      4	import	java.awt.event.ActionListener;
      5	import	javax.swing.JButton;
      6	import	javax.swing.JFrame;
      7	import	javax.swing.JLabel;
      8	import	javax.swing.JTextField;
      9	public	class	EventMekanizmasi	extends	JFrame
      10{
      11	        private	JLabel	lblGoruntule;
      12	        private	JTextField	txtGiris;
      13	        private	JButton	btnGoruntule;
      14	        public	EventMekanizmasi()
      15	        {
      16                  super(“Event Mekanizması”);
      17	        	        Container	container	=	getContentPane();
      18	        	        container.setLayout(new	FlowLayout());
      19	        	        txtGiris	=	new	JTextField(“JTextField”);
72   Bölüm 6




                20	       	       container.add(txtGiris);
                21	       	       btnGoruntule	=	new	JButton(“Görüntüle”);
                22	       	       container.add(btnGoruntule);
                23	       	       btnGoruntule.addActionListener(new	ButtonHandler());
                24	       	       lblGoruntule	=	new	JLabel(“JLabel”);
                25	       	       container.add(lblGoruntule);	 	
                26	       	       setSize(400,	200);
                27	       	       setVisible(true);
                28	       }
                29	       private	class	ButtonHandler	implements	ActionListener
                30	       {
                31	       	       public	void	actionPerformed(ActionEvent	e)	
                32	       	       {
                33	       	       	        lblGoruntule.setText(txtGiris.getText());
                34	       	       }
                35	       }
                36	       public	static	void	main(String[]	args)	
                37	       {
                38	       	       EventMekanizmasi	test	=	new	EventMekanizmasi();
                39	       	       test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                40	       }
                41}

          Kodun açıklaması: EventMekanizmasi sınıfının yapıcı metodunda daha önce yaptığımız gibi
          JLabel, JTextFieldveJButton nesnelerini oluşturduk ve Container nesnesine ekledik.

          EventMekanizmasi sınıfının içindeki private erişim tipine sahip ButtonHandler sınıfının
          ActionListener interface’ini implemente etmesi, bu sınıfın içinde actionPerformed me-
          todunun yazılmasını zorunlu kılar. Bu metod, Action cinsinden bir event oluştuğunda çalışır.
          JButton nesnesi üzerinde çalıştırdığımız addActionListener metodunu buton ile event’i
          ilişkilendirmek için kullandık, bu durumda buton kullanıcı tarafından tıklandığında ButtonHand-
          ler sınıfındaki actionPerformed metodu çalışacaktır. actionPerformed metodunun içinde
          txtGiris nesnesinin getText metodunu kullanarak kullanıcı tarafından girilen metni alıp lbl-
          Goruntule nesnesinin setText metodu ile JLabel kontrolünün metnine atıyoruz.

          Aynı işlevi, event handler sınıfını dahili olarak tanımlayarak da gerçekleyebiliriz. Event handler
          sınıfının dahili olarak gerçeklenmesini gösteren kod bloğu Örnek Uygulama 6.6’daki gibidir.

          Örnek Uygulama 6.6:

                1	import	java.awt.Container;
                2	import	java.awt.FlowLayout;
                3	import	java.awt.event.ActionEvent;
                4	import	java.awt.event.ActionListener;
                5	import	javax.swing.JButton;
                6	import	javax.swing.JFrame;
                7	import	javax.swing.JLabel;
                8	import	javax.swing.JTextField;
                9	public	class	EventMekanizmasi	extends	JFrame
                                                                                                      Swing   73




      10{
      11	       private	JLabel	lblGoruntule;
      12	       private	JTextField	txtGiris;
      13	       private	JButton	btnGoruntule;
      14	       public	EventMekanizmasi()
      15	       {
      16                 super(“Event Mekanizması”);
      17	       	        Container	container	=	getContentPane();
      18	       	        container.setLayout(new	FlowLayout());	                   	
      19	       	        txtGiris	=	new	JTextField(“JTextField”);
      20	       	        container.add(txtGiris);
      21	       	        btnGoruntule	=	new	JButton(“Görüntüle”);
      22	       	        container.add(btnGoruntule);
      23	       	        btnGoruntule.addActionListener
      24	       	        (
      25	       	        	       new	ActionListener()
      26	       	        	       {
      27	     	          	       	       public	void	actionPerformed(ActionEvent	
      event)	
      28	       	        	       	       {	       	       	        	
      29	       lblGoruntule.setText(txtGiris.getText());
      30	       	        	       	       }
      31	       	        	       }
      32	       	        );
      33	       	        lblGoruntule	=	new	JLabel(“JLabel”);
      34	       container.add(lblGoruntule);
      35		      setSize(400,	200);
      36		      setVisible(true);
      37	}
      38	public	static	void	main(String[]	args)	
      39	{
      40		      EventMekanizmasi	test	=	new	EventMekanizmasi();
      41		      test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      42	}
      43}

Her iki kod bloğu da aynı şekilde çalışır. Kullanıcının metin kutusuna yazdığı metin butona tıklan-
dıktan sonra label üzerinde görüntülenir. Uygulama çalıştırıldığında butona tıklamadan önce ve
sonraki görünümler Şekil 5 ve Şekil 6’daki gibidir.
   Bölüm 6




               Şekil 5                                      Şekil 6


          JTextArea
          JTextArea kontrolü, .Net ortamındaki RichTextBox kontrolünün karşılığıdır. JTextField
          kontrolünden daha geniş kullanım kabiliyetlerine sahiptir ve birden fazla satırdan oluşan metinle-
          rin girilmesine olanak verir. Append metodu yardımıyla üzerine metin eklemesi yapılabilir. Girilen
          metnin kontrolün boyutlarından büyük olması durumunda bir alt satıra geçmek için setLineWrap
          metodu kullanılır. JTextArea kontrolünün örnek kullanımı Örnek Uygulama 6.7’de verilmiştir.

          Örnek Uygulama 6.7:
                     1	import	java.awt.Container;
                     2	import	java.awt.FlowLayout;
                     3	import	javax.swing.JFrame;
                     4	import	javax.swing.JTextArea;	
                     5	public	class	JTextAreaTest	extends	JFrame	
                     6	{
                      private	JTextArea	txtArea;
                     7	
                      public	JTextAreaTest()
                     8	
                      {
                     9	
                     10           super(“JTextArea Kullanımı”);
                     11	    	     Container	container	=	getContentPane();
                     12	    	     container.setLayout(new	FlowLayout());
                     13           txtArea = new JTextArea(“JTextArea                alanına birden
                     fazla satirdan oluşan metin girilebilir.”);
                     14	    	     txtArea.append(“\nYeni	metin	eklenebilir”);
                     15	    	     txtArea.setLineWrap(true);
                     16	    	     txtArea.setSize(150,	150);
                     17	    	     container.add(txtArea);
                     18	    	     setSize(200,	200);
                     19	    	     setVisible(true);
                     20	    }
                     21	    public	static	void	main(String[]	args)
                     22	    {
                     23	    	     JTextAreaTest	test	=	new	JTextAreaTest();
                     24	    	     test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                     25	    }
                     26}
                                                                                                   Swing   



Kodun açıklaması: JTextArea nesnesini oluşturulup Container nesnesine ekledikten sonra
append metodu ile üzerine yeni metin ekledik. Append metodunun içinde kullandığımız “\n” ka-
rakteri metnin bir alt satıra geçmesini sağlar. setLineWrap(true) komutuyla metnin kontrolün
genişliğinden fazla yer kaplaması durumunda otomatik olarak bir alt satıra geçmesi sağlanmıştır.
setSize metodu ile kontrolün x ve y boyutu 150 olarak atanmıştır. Uygulama çalıştırıldığında
Şekil 7’deki gibi bir arayüz oluşur.

JOptionPane
JOptionPane sınıfı, .Net ortamında bulunan MessageBox
sınıfının Java karşılığıdır. MessageBox.Show() metoduna
benzer bir şekilde çalışan birçok statik metod içerir. Arayü-
zün çalışma mantığı içinde çeşitli mesajları kullanıcıya gös-
termek ve onay almak amacıyla kullanılır. Gösterilen onay
kutusu uygulamayı oluşturan formun dışında ayrı bir pence-
re içinde oluşur. Bir JOptionPane onay kutusunu kullanı-
cının karşısına çıkartan ve kullanıcının onay durumuna göre
bir tane JOptionPane mesaj diyaloğu gösteren kod Örnek
Uygulama 6.8’de verilmiştir.                                    Şekil 7

Örnek Uygulama 6.8:
      1	import	java.awt.Container;
      2	import	java.awt.FlowLayout;
      3	import	java.awt.event.ActionEvent;
      4	import	java.awt.event.ActionListener;
      5	import	javax.swing.JButton;
      6	import	javax.swing.JFrame;
      7	import	javax.swing.JOptionPane;	
      8	public	class	JOptionPaneTest	extends	JFrame	
      9	{
      10	       private	JButton	btnOnay;
      11	       public	JOptionPaneTest()
      12	       {
      13	       	       Super(“JOptionPane”);
      14	       	       Container	container	=	getContentPane();
      15	       	       container.setLayout(new	FlowLayout());
      16	       	       btnOnay	=	new	JButton(“Onay	al”);
      17	       	       btnOnay.addActionListener(new	ButtonHandler());
      18	       	       container.add(btnOnay);
      19	       	       setSize(200,	200);
      20	       	       setVisible(true);
      21	       }
      22	       private	class	ButtonHandler	implements	ActionListener
      23	       {
      24	       	       public	void	actionPerformed(ActionEvent	event)	
      25	       	       {
      26	    	     	     int	secim	=	JOptionPane.
      showConfirmDialog(null, “Seçiminizi onaylıyor musunuz?”, “Onay
      ekranı”, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_
      MESSAGE);
   Bölüm 6




                  27	           	          	            if(secim	==	JOptionPane.YES_OPTION)
                  28	    	     	     	     JOptionPane.showMessageDialog(null,	
                  “Onaylandı”, “Onay”, JOptionPane.INFORMATION_MESSAGE);
                  29	           	          	            else	if(secim	==	JOptionPane.NO_OPTION)
                  30	    	     	     	     JOptionPane.showMessageDialog(null,	
                  “Onaylanmadı”, “Red”, JOptionPane.ERROR_MESSAGE);
                  31	           	          	            else
                  32	    	     	     	     JOptionPane.showMessageDialog(null,	
                  “Onaylanmadı”, “İptal”, JOptionPane.WARNING_MESSAGE);
                  33	           	          }
                  34	           }
                  35	           public	static	void	main(String[]	args)	
                  36	           {
                  37	           	          JOptionPaneTest	test	=	new	JOptionPaneTest();
                  38	           	          test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  39	           }
                  40}

          Kodun açıklaması: Formun üzerine bir tane buton ekledik ve bu buton için ActionListener               
          interface’ini implemente eden ButtonHandler adında bir event sınıfı yazdık. Kullanıcı tara-
          fından butona tıklanması durumunda actionPerformed metodu çalışır ve kullanıcıya JOp-
          tionPane.showConfirmDialog metodu yardımıyla onay verip vermediği sorulur. Bu statik
          metodun ikinci parametresi onay kutusunda görüntülenmesini istediğimiz metin, üçüncü para-
          metresi ise onay kutusunun başlığını oluşturan metindir. Dördüncü parametrede onay kutusunda
          hangi butonların görüntülenmesini istediğimizi belirttik. Yaptığımız örnekte Yes, No ve Cancel
          butonlarının görüntülenmesini istedik. Kullanıcının herhangi birşeyi onaylamasını istediğimiz için
          soru işareti şeklinde bir resim kullanmak duruma uygun olduğundan beşinci parametrede soru
          mesajı seçeneğini seçtik. Java’daki birçok metod parametresinde olduğu gibi JOptionPane.
          showConfirmDialog metodunun parametrelerinde de sınıfın üzerinde bulunan değerleri kulla-
          nabildiğimiz gibi istersek bu değerlerin tam sayı karşılıklarını da kullanabiliriz. Metodun geri dönüş
          değerinin tam sayı(int) olduğuna dikkat edelim. Bu geri dönüş değerini secim isimli bir tam sayı
          değişkenine atarak bir sonraki aşamada seçime göre bir işlem yapılmasını sağlayabiliriz.

          Sonraki aşamada, onay durumuna göre değişen bir simgeye, başlık metnine ve mesaj kutusu
          metnine sahip bir mesaj kutusunu kullanıcıya gösteriyoruz.

          Uygulama çalıştırıldığında görünen arayüz, butona tıklandığı zaman görüntülenen onay kutusu
          ve çeşitli seçimlere göre görüntülenen mesaj kutuları Şekil 8, Şekil 9, Şekil 10, Şekil 11 ve Şekil
          12’de gösterildiği gibidir.




               Şekil 8: Programın ilk çalışması.                  Şekil 9: Onay ekranı.


                                                                 

                                         
                                                                                                            Swing   




      Şekil 10: Yes butonuna tıklandı.                                    Şekil 11: No butonuna tıklandı.




                                         Şekil 12: İptal butonuna tıklandı.


JCheckBox
JCheckBox sınıfı, .Net platformunda bulunan CheckBox sınıfının Java ortamındaki karşılığıdır.
Seçili durumda olabilen küçük bir kutudan ve yanında bulunan bir Label’dan oluşan JCheck-
Box, kullanıcının temel açık/kapalı seçimi yapmasını sağlayan basit bir arayüz kontrolüdür. Be-
lirli bir zamanda nesnenin seçili olup olmadığı kontrol edilebilir, seçim değiştiğinde bir event’in
tetiklenmesi sağlanabilir, seçili olma durumu değiştirilebilir. JCheckBox kontrolünün kullanımını
gösteren kod bloğu Örnek Uygulama 6.9’da verilmiştir.

Örnek Uygulama 6.9:

      1	import	java.awt.Container;
      2	import	java.awt.FlowLayout;
      3	import	java.awt.GridLayout;
      4	import	java.awt.event.ActionEvent;
      5	import	java.awt.event.ActionListener;
      6	import	java.awt.event.ItemEvent;
      7	import	java.awt.event.ItemListener;
      8	import	javax.swing.JButton;
      9	import	javax.swing.JCheckBox;
      10	import	javax.swing.JFrame;
      11	import	javax.swing.JLabel;
      12	import	javax.swing.JOptionPane;
      13	import	javax.swing.JTextField;
      14	public	class	JCheckBoxTest	extends	JFrame
      15	{
      16		          private	JCheckBox	chkKabul;
      17		          private	JLabel	lblAd;
      18		          private	JLabel	lblSoyad;
      19		          private	JTextField	txtAd;
      20		          private	JTextField	txtSoyad;
      21		          private	JButton	btnKaydet;
      22		          public	JCheckBoxTest()
      23		          {
      24                       super(“Kullanıcı kayıt formu”);
      25		          	          Container	container	=	getContentPane();
   Bölüm 6




               26		   	      container.setLayout(new	FlowLayout());
               27		   	      lblAd	=	new	JLabel(“Ad:							“);
               28		   	      container.add(lblAd);
               29		   	      txtAd	=	new	JTextField(10);
               30		   	      container.add(txtAd);
               31		   	      lblSoyad	=	new	JLabel(“Soyad:	“);
               32		   	      container.add(lblSoyad);
               33		   	      txtSoyad	=	new	JTextField(10);
               34		   	      container.add(txtSoyad);
               35		   	      btnKaydet	=	new	JButton(“Kaydet”);
               36		   	      btnKaydet.setEnabled(false);
               37		   	      btnKaydet.addActionListener
               38		   	      (
               39		   	      	    new	ActionListener()
               40		   	      	    {
               41		    	     	    	     public	void	actionPerformed(ActionEvent	
               event)	
               42		   	      	    	     {
               43		   	     	     	     	     JOptionPane.
               showMessageDialog(null,	“Ad:	“	+	txtAd.getText()	+	“\nSoyad:	“	+	
               txtSoyad.getText());
               44		   	      	    	     }
               45		   	      	    }
               46		   	      );
               47		   		     container.add(btnKaydet);
               48            chkKabul = new JCheckBox(“Sözleşmeyi kabul
               ediyorum”);
               49		   	      chkKabul.addItemListener
               50		   	      (
               51		   	      	    new	ItemListener()
               52		   	      	    {
               53		    	     	    	     public	void	itemStateChanged(ItemEvent	
               event)	
               54		   	      	    	     {
               55		   	      	    	     	     if(chkKabul.isSelected()	==	true)
               56		   	      	    	     	     	      btnKaydet.setEnabled(true);
               57		   	      	    	     	     else
               58		   	      	    	     	     	      btnKaydet.setEnabled(false);
               59		   	      	    	     }
               60		   	      	    }
               61		   	      );
               62		   	      container.add(chkKabul);
               63		   	      setSize(200,	150);
               64		   	      setVisible(true);		
               65		   }
                                                                                                         Swing   




      66		         public	static	void	main(String[]	args)	
      67		         {
      68		         	           JCheckBoxTest	test	=	new	JCheckBoxTest();
      69		         	           test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      70		         }
      71	}

Kodun açıklaması: İki tane JLabel, iki tane JTextField, bir tane JButton ve bir tane JC-
heckBox nesnesi oluşturularak Container nesnesine eklendi. JCheckBox nesnesi üzerinde
çalıştırılan addItemListener metodu ile, bu nesnenin durumunun değişmesi halinde tetikle-
necek olan event handler’i oluşturuldu. Yazdığımız koda göre, uygulama ilk çalıştırıldığında bu-
ton aktif değildir. Kullanıcı ad ve soyad bilgilerini girdikten sonra sözleşmeyi kabul ettiğini belir-
ten JCheckBox’ı işaretlediğinde (checkbox’ı seçili hale getirdiğinde) JCheckBox nesnesinin
uzerindeki ItemListener metodu çalışır ve buton aktif hale gelir. Benzer bir şekilde kullanıcı
CheckBox üzerindeki seçimi iptal ederse buton aktiflik özelliğini yitirir. Kullanıcı gereken bilgileri
girdikten sonra Kaydet butonuna tıkladığında ad ve soyad bilgileri bir mesaj kutusu (JOption-
Pane) yardımıyla ekranda görüntülenir. Uygulama çalıştırıldığında görünen arayüz Şekil 13, Şekil
14 ve Şekil 15’teki gibidir:




         Şekil 13: Buton aktif değil.                                     Şekil 14: Buton aktif.




                                    Şekil 15: Kaydet butonuna tıklandı.



JRadioButton
JRadioButton bileşeni, .Net ortamındaki RadioButton kontrolünün Java platformundaki kar-
şılığıdır. Birden fazla seçeneğe sahip bir veri kümesi arasından birinin seçilmesi gereken durum-
larda kullanılır. .Net ortamındaki RadioButton kontrolünden farklı olarak arayüz üzerinde aynı
anda birden fazla JRadioButton kontrolü seçili durumda bulunabilir. Bu durumu önlemek için,
arayüz üzerindeki ilişkili JRadioButton kontrolleri bir tane ButtonGroup nesnesi kullanıla-
rak gruplandırılır. JRadioButton kontrolü üzerindeki seçim durumundaki değişiklik JCheckBox
kontrolü gibi ItemListener interface’i ile kontrol edilebilir. İki tane JRadioButton kontrolü ile
bir tane ButtonGroup kontrolü içeren ve JRadioButton nesneleri üzerindeki seçim durumu-
nun değişikliğini takip eden kod bloğu Örnek Uygulama 6.10’da gösterilmiştir.

Örnek Uygulama 6.10:
      1	import	java.awt.Container;
      2	import	java.awt.FlowLayout;
80   Bölüm 6




               3	import	java.awt.event.ItemEvent;
               4	import	java.awt.event.ItemListener;
               5	import	javax.swing.ButtonGroup;
               6	import	javax.swing.JFrame;
               7	import	javax.swing.JOptionPane;
               8	import	javax.swing.JRadioButton;
               9	import	javax.swing.plaf.basic.BasicComboBoxUI.ItemHandler;
               10	public	class	JRadioButtonTest	extends	JFrame	
               11	{
               12		   private	JRadioButton	rbErkek;
               13		   private	JRadioButton	rbKadin;
               14		   private	ButtonGroup	grpRadio;
               15		   public	JRadioButtonTest()
               16		   {
               17            super(“JRadioButton örneği”);
               18		   	      Container	container	=	getContentPane();
               19		   	      container.setLayout(new	FlowLayout());
               20		   		     rbErkek	=	new	JRadioButton(“Erkek”,	true);
               21		   	      rbErkek.addItemListener(new	RadioButtonHandler());
               22		   	      container.add(rbErkek);
               23            rbKadin = new JRadioButton(“Kadın”, false);
               24		   	      rbKadin.addItemListener(new	RadioButtonHandler());
               25		   	      container.add(rbKadin);
               26            // JRadioButton nesnelerini gruplandırmak için
               ButtonGroup   kullanılır
               27		   	      grpRadio	=	new	ButtonGroup();
               28		   	      grpRadio.add(rbErkek);
               29		   	      grpRadio.add(rbKadin);
               30		   	      setSize(200,	100);
               31		   	      setVisible(true);
               32		   }
               33		   private	class	RadioButtonHandler	implements	ItemListener
               34		   {
               35		   	      public	void	itemStateChanged(ItemEvent	event)	
               36		   	      {
               37		   	      	     if(event.getStateChange()	==	ItemEvent.
               SELECTED)
               38		   	      	     {
               39		   	     	     	     JOptionPane.showMessageDialog(null,	
               ((JRadioButton)event.getSource()).getText());
               40		   	      	     }
               41		   	      }
               42		   }
               43		   public	static	void	main(String[]	args)	
               44		   {
                                                                                                         Swing   81




      45		         	           JRadioButtonTest	test	=	new	JRadioButtonTest();
      46		         	           test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      47		         }
      48	}

Kodun açıklaması: JRadioButtonTest sınıfının yapıcı metodunda iki tane JRadioButton,
bir tane ButtonGroup nesnesi oluşturduk. JRadioButton nesnelerini oluştururken kullandığı-
mız yapıcı metodun ikinci parametresi mantıksal değer alır ve uygulama ilk çalıştığında JRadi-
oButton nesnesinin seçili durumda olup olmayacağını belirtir. Uygulama ilk çalıştığında Erkek
değerine sahip JRadioButton nesnesi seçili durumdadır. İki JRadioButton nesnesi için de
aynı event handler sınıfını kullanacağımız için private bir iç sınıf oluşturduk. ItemStateChan-
ged event handler metodu JRadioButton nesnelerinden birinin seçili olma durumu değiştiğinde
çalışır. Metodun başında kullandığımız if mekanizmasıyla sadece seçili hale gelen nesnelerle
ilgilendiğimizi belirttik ve JRadioButton kontrollerinden biri seçili hale geçtiğinde bu nesne-
nin text özelliğini mesaj kutusu kullanarak kullanıcıya gösterdik. Eğer ButtonGroup nesnesini
kullanmasaydık aynı anda birden fazla JRadioButton kontrolü seçili durumda bulunabilecekti.
ButtonGroup nesnesinin olması ve olmaması durumlarında uygulamanın davranışı Şekil 16,
Şekil 17 ve Şekil 18’de gösterilmiştir.




                                       Şekil 16: ButtonGroup nesnesi kullanılmadığında
                                       herhangi bir zamanda iki JRadioButton bir arada
                                       seçilebilir.




      Şekil 17: ButtonGroup nesnesi kullanıldı.                      Şekil 18: rbErkek seçili durumda.


JComboBox
JComboBox kontrolü, .Net ortamındaki ComboBox kontrolü gibi bir veri kümesi üzerinden bir tane
eleman seçmek amacıyla kullanılır. .Net ortamındaki ComboBox kontrolü seçme, metin cinsinden
veri girişi, otomatik tamamlama gibi amaçlar için kullanılabildiği halde JComboBox kontrolü sade-
ce veri seçmek amacıyla kullanılabilir, aynı anda birden fazla elemanın seçilmesine izin verilmez.
Temel amacı gereği bir arada kullanılan JRadioButton nesnelerine benzese de çalışma zama-
nında dinamik veri bağlama kolaylığından dolayı bu kontrolden ayrılır. JComboBox kontrolüne
veri bağlanması ve seçili elemanın değişmesi durumunda oluşan event’in kullanılması aşağıdaki
kod üzerinde gösterilmiştir.

Örnek Uygulama 6.11:

      1	import	java.awt.Container;
      2	import	java.awt.FlowLayout;
      3	import	java.awt.event.ActionEvent;
      4	import	java.awt.event.ActionListener;
      5	import	javax.swing.JComboBox;
82   Bölüm 6




                6	import	javax.swing.JFrame;
                7	import	javax.swing.JLabel;
                8	import	javax.swing.JOptionPane;
                9	public	class	JComboBoxTest	extends	JFrame	
                10	{
                11	       	private	JLabel	lblOgrenimDurumu;
                12	       	private	JComboBox	cmbOgrenimDurumu;
                13	       	public	JComboBoxTest()
                14	       	{
                15                super(“JComboBox örneği”);
                16		      	       Container	container	=	getContentPane();
                17		      	       container.setLayout(new	FlowLayout());
                18                lblOgrenimDurumu = new JLabel(“Öğrenim durumunuzu
                seçin”);
                19		      	       container.add(lblOgrenimDurumu);
                20           String[] ogrenimDurumlari = {“İlkokul”, “Ortaokul”,
                “Lise”,	“Üniversite”,	“Yüksek	lisans”,	“Doktora”};
                21		      	       cmbOgrenimDurumu	=	new	JComboBox(ogrenimDurumlari);
                22		      	       cmbOgrenimDurumu.addActionListener
                23		      	       (
                24		      	       	       	       new	ActionListener()
                25		      	       	       	       {
                26		   	     	            	       	       public	void	actionPerformed(Action
                Event	event)
                27		      	       	       	       	       {
                28		   	     	     	     	     	     JOptionPane.
                showMessageDialog(null,	cmbOgrenimDurumu.getSelectedItem().
                toString());
                29		      	       	       	       	       }
                30		      	       	       	       }
                31		      	       );
                32		      	       container.add(cmbOgrenimDurumu);
                33		      	       setSize(200,	100);
                34		      	       setVisible(true);
                35		      }
                36		      public	static	void	main(String[]	args)	
                37		      {
                38		      	       JComboBoxTest	test	=	new	JComboBoxTest();
                39		      	       test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                40		      }
                41	}

          Kodun açıklaması: Uygulama içinde bir tane JLabel ve bir tane JComboBox nesnesi tanımla-
          dık. Öğrenim durumlarını tutan bir string dizisi oluşturarak JComboBox nesnesinin yapıcı meto-
          duna parametre olarak verdik. JComboBox nesnesi oluşurken yapıcı metoduna parametre olarak
          verdiğimiz string dizisini veri kaynağı olarak kullanır. JComboBox nesnesinin seçili elemanı de-
                                                                                                          Swing   83



ğiştiğinde çalışmak üzere bir ActionListener event handler metodu tanımladık. Uygulama ilk
çalıştığında ilk elemanın seçili durumda olduğu ve event handler metodunun uygulamanın ilk ça-
lışması sırasında tetiklenmediği gözlenebilir. Bu aşamadan sonra seçili eleman değiştiği zaman
event handler metodu tetiklenir ve seçilmiş olan elemanın sahip olduğu metni bir JOptionPane
mesaj kutusu aracılığıyla kullanıcıya gösterir. Uygulamanın ihtiyacına göre birden fazla JCombo-
Box nesnesinin aynı event handler metodunu kullanması sağlanabilir, bu durumda ActionLis-
tener interface’ini implement eden bir sınıf oluşturmak gerekir. Ayrıca bir JComboBox nesnesi-
nin seçili elemanının değişmesiyle başka bir JComboBox nesnesinin veri kümesinin değişmesi de
sağlanabilir. İlerleyen kısımlarda bu durumla ilgili bir örnek yapacağız.

Uygulama ilk çalıştığında ve seçili eleman değiştiğinde Şekil 19 ve Şekil 20’deki gibi bir görünüm
oluşur:




      Şekil 19                                           Şekil 20: Seçili eleman değişti.


JList
.Net ortamındaki ListBox kontrolünün Java platformundaki karşılığıdır. Belirli bir veri kümesi
üzerinden bir veya daha çok sayıda eleman seçmek amacıyla kullanılır. JComboBox kontrolünde
olduğu gibi sahip olduğu veri kümesi uygulamanın çalışması sırasında değiştirilebilir. Uygulama-
nın gereksinimlerine bağlı olarak bir tane, belirli bir aralıkta olmak üzere birden fazla veya belirli
bir aralıkta bulunma şartı bulunmadan birden fazla elemanın seçili olmasına izin verilebilir. Belirli
bir aralıkta olmak üzere birden fazla elemanın seçilmesi sağlanırsa kullanıcı, klavyedeki shift
tuşuyla birlikte mouse imlecini kullanarak aralık şeklinde seçim yapabilir. Belirli bir aralıkta bulun-
ma şartı olmadan seçim yapılabilecekse kullanıcı, klavyedeki ctrl tuşuyla birlikte mouse imlecini
kullanabilir. Gereksinime göre JComboBox nesnesinde olduğu gibi ActionListener interface’i
kullanılarak seçili elemanların değişmesi izlenebilir ve kontrol edilebilir.

JList nesnesinin oluşturulması ve kullanımı aşağıdaki Örnek Uygulama 6.12’de gösterilmiştir.

Örnek Uygulama 6.12:

        1	import	java.awt.Container;
        2	import	java.awt.FlowLayout;
        3	import	java.awt.event.ActionEvent;
        4	import	java.awt.event.ActionListener;
        5	import	javax.swing.JButton;
        6	import	javax.swing.JFrame;
        7	import	javax.swing.JLabel;
        8	import	javax.swing.JList;
        8	import	javax.swing.JScrollPane;
        10	import	javax.swing.JTextArea;
        11	import	javax.swing.ListSelectionModel;
        12	public	class	JListTest	extends	JFrame	
        13	{
        14		     private	JLabel	lblIlgiAlanlari;
        15		     private	JList	lstIlgiAlanlari;
   Bölüm 6




               16		   private	JScrollPane	scrIlgiAlanlari;
               17		   private	JTextArea	txtSonuc;
               18		   private	JButton	btnGoster;
               19		   public	JListTest()
               20		   {
               21            super(“JListBox örneği”);
               22		   	      Container	container	=	getContentPane();
               23		   	      container.setLayout(new	FlowLayout());
               24            lblIlgiAlanlari = new JLabel(“İlgi alanlarınızı
               seçin”);
               25		   	      container.add(lblIlgiAlanlari);
               26		   	     String[]	ilgiAlanlari	=	new	String[]{“Spor”,	
               “Müzik”,	“Edebiyat”,	“Tiyatro”,	“Resim”,	“Sinema”};
               27		   	      lstIlgiAlanlari	=	new	JList(ilgiAlanlari);
               28					 //lstIlgiAlanlari.setSelectionMode(ListSelectionModel.
               SINGLE_
               SELECTION);
               29						//lstIlgiAlanlari.setSelectionMode(ListSelectionModel.
               SINGLE_
               INTERVAL_SELECTION);
               30	    	     	      lstIlgiAlanlari.setSelectionMode(ListSelection
               Model.MULTIPLE_
               INTERVAL_SELECTION);
               31		   	      lstIlgiAlanlari.setVisibleRowCount(4);
               32		   	      scrIlgiAlanlari	=	new	JScrollPane(lstIlgiAlanlari);
               33		   	      container.add(scrIlgiAlanlari);
               34		   	      btnGoster	=	new	JButton(“Göster”);
               35		   	      btnGoster.addActionListener
               36		   	      (
               37		   	      	     new	ActionListener()
               38		   	      	     {
               39		   	      	     	    public	void	actionPerformed(ActionEvent	
               event)
               40		   	      	     	    {
               41		   	      	     	    	     txtSonuc.setText(“”);
               42				 	     	     	     	     Object[]	seciliElemanlar	=	
               lstIlgiAlanlari.getSelectedValues();
               43		   	     	      	    	     for	(Object	eleman	:	
               seciliElemanlar)	
               44		   	      	     	    	     {
               45		   	     	      	    	     	     txtSonuc.append(eleman.
               toString()	+	“\n”);
               46		   	      	     	    	     }	
               47		   	      	     	    }
               48		   	      	     }
               49		   	      );
                                                                                                         Swing   




      50		        	          container.add(btnGoster);
      51		        	          txtSonuc	=	new	JTextArea();
      52		        	          container.add(txtSonuc);
      53		        	          setSize(200,	200);
      54		        	          setVisible(true);
      55		        }
      56		        public	static	void	main(String[]	args)	
      57		        {
      58		        	          JListTest	test	=	new	JListTest();
      59		        	          test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      60		        }
      61	}

Kodun açıklaması: Uygulamada ilgi alanlarını görüntülemek için bir tane JList nesnesi ve
bu nesneye scroll özelliği vermek için bir tane JScrollPane nesnesi kullandık. Kullanıcının bir
veya birkaç tane seçebileceği ilgi alanı veri kümesini tutmak için kullanılan string dizisi JList
nesnesinin yapıcı metoduna parametre olarak verildi. Jlist nesnesinin sahip olduğu setSe-
lectionMode metodu, JList üzerinde aynı anda birden fazla elemanın seçilmesine izin verilip
verilmeyeceğini belirler. Tek bir elemanın seçilmesine izin vermek isteseydik SINGLE_SELEC-
TION seçeneğini, belirli bir aralıkta olmak üzere birden fazla elemanın seçilmesine izin vermek
isteseydik SINGLE_INTERVAL_SELECTION seçeneğini kullanacaktık. Kullandığımız yapıda ise
belirli bir aralığa dahil olan veya olmayan birden fazla eleman seçilebilir. JList nesnesi varsa-
yılan olarak sahip olduğu bütün elemanları alt alta gösterir. Eleman sayısı arttıkça nesne uygu-
lama arayüzü üzerinde fazla yer kaplamaya başlayacağından scroll özelliğine ihtiyaç duyulabilir.
JList nesnesinin kendine ait bir scroll özelliği olmadığı halde JScrollPane bileşeni kullanıla-
rak JList nesnesine scroll özelliği verilebilir. Koda dikkat edilirse JList nesnesinin doğrudan
Container nesnesine eklenmediği görülebilir. JList nesnesi JScrollPane nesnesine, JSc-
rollPane nesnesi ise Container nesnesine eklenmiştir. JList nesnesinin setVisible-
RowCount metodu scroll işleminden önce görüntülenecek eleman sayısını belirlemek amacıyla
kullanılır. Örnek uygulamada, dört tane elemanın görünür halde olmasına izin verilmiştir, diğer
elemanlara ancak scroll işlemiyle ulaşılabilir.
Örnek uygulamada, JList nesnesi üzerinde kullanıcının seçtiği elemanların değeri butona basıl-
dıktan sonra JTextArea nesnesine yazılır. Butona her tıklandığında JTextArea bileşenin text
özelliği boş string değeri almaktadır, bunun sebebi sadece butona tıklandığı anda seçili olan
elemanların değerlerini görüntülemek istememizdir.
Uygulama çalıştırıldığında ve butona tıklandığında Şekil 21 ve Şekil 22’de olduğu gibi görünür.




       Şekil 21: Uygulama çalıştırıldığında JTextArea   Şekil 22: Üç tane eleman seçildi ve Göster bu-
       nesnesi görünmüyor.                              tonuna tıklandı.
   Bölüm 6



          JList kontrolü sıklıkla kullanılabilecek bir kontrol olduğu için, birçok uygulamada karşımıza çıka-
          bilecek bir arayüz oluşturalım ve iki tane JList kontrolü arasında veri aktarımı yapalım.

          Örnek Uygulama 6.13:

                1	import	java.awt.Container;
                2	import	java.awt.FlowLayout;
                3	import	java.awt.event.ActionEvent;
                4	import	java.awt.event.ActionListener;
                5	import	javax.swing.DefaultListModel;
                6	import	javax.swing.JButton;
                7	import	javax.swing.JFrame;
                8	import	javax.swing.JList;
                9	import	javax.swing.ListSelectionModel;
                10	public	class	VeriAktarimi	extends	JFrame	
                11	{
                12		      private	JList	lstIlgiAlanlari;
                13		      private	JList	lstSecilmisIlgiAlanlari;
                14		      private	JButton	btnEkle;
                15		      private	JButton	btnCikar;
                16		      private	DefaultListModel	modelElemanlar;
                17		      private	DefaultListModel	modelSeciliElemanlar;
                18		      public	VeriAktarimi()
                19		      {
                20                 super(“JListBox nesneleri arasında veri aktarımı”);
                21		      	        Container	container	=	getContentPane();
                22		      	        container.setLayout(new	FlowLayout());
                23		      	        modelElemanlar	=	new	DefaultListModel();
                24		      	        modelSeciliElemanlar	=	new	DefaultListModel();
                25		      	        modelElemanlar.addElement(“Spor”);
                26		      	        modelElemanlar.addElement(“Müzik”);
                27		      	        modelElemanlar.addElement(“Edebiyat”);
                28		      	        modelElemanlar.addElement(“Tiyatro”);
                29		      	        modelElemanlar.addElement(“Resim”);
                30		      	        modelElemanlar.addElement(“Sinema”);
                31		      	        lstIlgiAlanlari	=	new	JList(modelElemanlar);
                32		   	           lstIlgiAlanlari.setSelectionMode(ListSelectionModel.
                MULTIPLE_
                INTERVAL_SELECTION);
                33		      	        container.add(lstIlgiAlanlari);
                34		      	        btnCikar	=	new	JButton(“<<<<”);
                35		      	        btnCikar.setEnabled(false);
                36		      	        btnCikar.addActionListener
                37		      	        (
                38		      	        	       new	ActionListener()
                39		      	        	       {
                                                                    Swing   




40		   	     	      	    public	void	actionPerformed(ActionEvent	
event)
41		    	    	      	    {
42		   	     	     	     	     Object[]	seciliElemanlar	=	
lstSecilmisIlgiAlanlari.getSelectedValues();
43		   	     	      	    	     for	(Object	eleman	:	
seciliElemanlar)	
44		    	    	      	    	     {
45		   	     	     	     	     	     modelSeciliElemanlar.
removeElement(eleman.toString());
46		   	     	     	     	     	     modelElemanlar.
addElement(eleman.toString());
47		    	    	      	    	     }	
48		    	    	      	    	     if(modelSeciliElemanlar.getSize()	
==	0)
49		    	    	      	    	     {
50		    	    	      	    	     	     btnCikar.setEnabled(false);
51		    	    	      	    	     }
52		    	    	      	    	     if(modelElemanlar.getSize()	!=	0)
53		    	    	      	    	     {
54		    	    	      	    	     	     btnEkle.setEnabled(true);
55		    	    	      	    	     }
56		    	    	      	    }
57		    	    	      }
58		    	    );
59		    	    container.add(btnCikar);
60		    	    btnEkle	=	new	JButton(“>>>>”);
61		    	    btnEkle.addActionListener
62		    	    (
63		    	    	      new	ActionListener()
64		    	    	      {
65		   	     	      	    public	void	actionPerformed(ActionEvent	
event)
66		    	    	      	    {
67		   	     	     	     	     Object[]	seciliElemanlar	=	
lstIlgiAlanlari.getSelectedValues();
68		   	     	      	    	     for	(Object	eleman	:	
seciliElemanlar)	
69		    	    	      	    	     {
70		   	     	     	     	     	     modelElemanlar.
removeElement(eleman.toString());
71		   	     	     	     	     	     modelSeciliElemanlar.
addElement(eleman.toString());
72		    	    	      	    	     }	
73		    	    	      	    	     if(modelElemanlar.getSize()	==	0)
74		    	    	      	    	     {
   Bölüm 6




                75		      	        	       	        	       	       btnEkle.setEnabled(false);
                76		      	        	       	        	       }
                77		      	        	       	        	       if(modelSeciliElemanlar.getSize()	
                !=	0)
                78		      	        	       	        	       {
                79		      	        	       	        	       	       btnCikar.setEnabled(true);
                80		      	        	       	        	       }
                81		      	        	       	        }
                82		      	        	       }
                83		      	        );
                84		      	        container.add(btnEkle);
                85		   	           lstSecilmisIlgiAlanlari	=	new	JList(modelSeciliElema
                nlar);
                86		      	        lstIlgiAlanlari.setSize(100,	100);
                87		      	        container.add(lstSecilmisIlgiAlanlari);
                88		      	        setSize(200,	200);
                89		      	        setVisible(true);
                90		      }
                91		      public	static	void	main(String[]	args)	
                92		      {
                93		      	        VeriAktarimi	test	=	new	VeriAktarimi();
                94		      	        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                95		      }
                96	}

          Kodun açıklaması: Uygulamada iki tane JList kontrolü ile iki tane JButton kontrolü kullan-
          dık. Bir önceki örnekte JList kontrolüne veri kaynağı olarak bir string dizisi verdiğimiz halde
          bu örnekte DefaultListModel nesnesinden yararlandık. Bunun sebebi, DefaultListModel
          bileşeninin uygulamanın çalışması sırasında veri ekleme ve çıkartma işlemlerini desteklemesidir.
          Uygulama ilk çalıştığı sırada bütün ilgi alanları sol tarafta bulunan JList bileşenin içinde bulunur
          ve sol tarafa veri aktarmayı sağlayan buton aktif değildir. Bir veya birden fazla ilgi alanı seçilip
          sağ tarafa veri aktarmayı sağlayan butona tıklandığında, seçili elemanlar modelElemanlar nes-
          nesinden removeElement metodu yardımıyla çıkartılır modelSeciliElemanlar nesnesine
          addElement metodu yardımıyla eklenir. Bu işlemler JButton nesneleri için yazılan ve Action-
          Listener interface’ini implement eden metodlar içinde gerçeklenir. Sol taraftaki JList bileşenin
          içinde eleman kalmadığında sola aktarma işlemini gerçekleyen buton aktif olmaktan çıkar. JList
          nesnelerine veri kaynağı olarak bağladığımız DefaultListModel nesnelerini event handler
          metodları içinde tekrar bağlamaya gerek olmadığına dikkat edelim, bu durum kullandığımız nes-
          nelerin referans tipinde olmasından kaynaklanır. DefaultListModel nesnelerinin barındırdığı
          veriler değiştiğinde otomatik olarak JList görünümleri de değişir.

          Uygulama çeşitli çalışma aşamalarında Şekil 23, Şekil 24 ve Şekil 25’te olduğu gibi görünür:
                                                                                                                               Swing   




   Şekil 23: Üç tane eleman seçili durumda, henüz            Şekil 24: Sağ tarafa aktarma işlemi yapıldıktan sonra iki buton
   butona tıklanmış.                                         da aktif.




                               Şekil 25: Sol taraftaki bütün veriler sağ tarafa geçmiş, sağa ak-
                               tarma butonu kullanılamıyor.

Mouse Event’lerinin Yönetilmesi:
Fare hareketleri ile tetiklenen event yapıları MouseListener ve MouseMotionListener interface’lerinin
implement edilmesiyle kontrol edilebilir. Bu interface’lerin içinde bulunan metodlar şu şekildedir:

MouseListener

mousePressed: Fare butonlarından birine basıldığı anda tetiklenir.

mouseClicked: Fare butonlarından birine basılıp bırakıldığında tetiklenir.

mouseReleased: Fare butonlarından birine basıldıktan sonra bırakıldığında tetiklenir.

mouseEntered: Fare imleci bir bileşenin alanına girdiğinde tetiklenir.

mouseExited: Fare imleci bir bileşenin alanını terk ettiğinde tetiklenir.

MouseMotionListener:

mouseDragged: Fare imleci bir bileşenin üzerindeyken butonlardan birine basılarak mouse ha-
reket ettirildiğinde tetiklenir.

mouseMoved: Fare imleci bir bileşenin üzerindeyken fare hareket ettirildiğinde tetiklenir.

Fare ile ilgili event’leri kontrol eden bütün metodlar parametre olarak bir MouseEvent nesnesi
alırlar. Fare imlecinin x ve y koordinatları, hangi butona kaç kere basıldığı gibi bilgiler bu nesne
aracılığıyla alınır. Mouse event’leri herhangi bir bileşen için kaydedilebilir ve bu bileşen üzerinde
herhangi bir fare hareketi olduğunda ilgili event metodu tetiklenir. Interface mantığından dolayı
MouseListener ve MouseMotionListener interface’lerinden herhangi biri implement edildiğinde bu
interface’in içinde bulunan bütün metodlar implement edilmek zorundadır. Kullanılmayacak olan
metodların tanımları yapılarak içleri boş bırakılır.

Mouse event’lerini kontrol etmek amacıyla oluşturduğumuz uygulamanın kodları aşağıdaki gibi-
dir.
90   Bölüm 6




                import	java.awt.Container;
               1	
                import	java.awt.FlowLayout;
               2	
                import	java.awt.event.MouseEvent;
               3	
                import	java.awt.event.MouseListener;
               4	
                import	javax.swing.JFrame;
               5	
                import	javax.swing.JLabel;
               6	
                import	javax.swing.JTextArea;
               7	
                public	class	MouseYonetimi	extends	JFrame	
               8	
                {
               9	
               10	    	     private	JTextArea	txtContainerEvent;
               11	    	     private	JTextArea	txtLabelEvent;
               12	    	     private	JLabel	lblAlan;
               13	    	     public	MouseYonetimi()
               14	    	     {
               15	    	     	     super(“Mouse	yönetimi”);
               16	    	     	     Container	container	=	getContentPane();
               17	    	     	     container.setLayout(new	FlowLayout());
               18	    	     	     container.addMouseListener(new	
               ContainerMouseListenerHandler());
               19                 lblAlan = new JLabel(“Mouse imlecini bu alanın
               üzerine	getirin”);
               20	    	     	     lblAlan.addMouseListener(new	
               JLabelMouseListenerHandler());
               21	    	     	     container.add(lblAlan);
               22	    	     	     txtContainerEvent	=	new	JTextArea();
               23	    	     	     container.add(txtContainerEvent);
               24	    	     	     txtLabelEvent	=	new	JTextArea();
               25	    	     	     container.add(txtLabelEvent);
               26	    	     	     setSize(200,	200);
               27	    	     	     setVisible(true);
               28	    	     }
               29	    	     private	class	ContainerMouseListenerHandler	
               implements	MouseListener
               30	    	     {
               31	    	     	     public	void	mouseClicked(MouseEvent	event)	
               32	    	     	     {	
               33	    	     	     	     txtContainerEvent.
               append(ButonAdiAl(event.getButton())	+	“	butona	“	+	event.
               getClickCount() + “ kez basıldı ve bırakıldı\n”);
               34	    	     	     }
               35	    	     	     public	void	mousePressed(MouseEvent	event)	
               36	    	     	     {
               37	    	     	     	     txtContainerEvent.
               append(ButonAdiAl(event.getButton())	+	“	butona	(“	+	event.getX()	
               + “,” + event.getY() + “) noktasında basıldı\n”);
               38	    	     	     }
                                                                     Swing   91




39	    	     	     public	void	mouseReleased(MouseEvent	event)	
40	    	     	     {
41	    	     	     	     txtContainerEvent.
append(ButonAdiAl(event.getButton()) + “ buton bırakıldı\n”);
42	    	     	     }
43	    	     	     public	void	mouseEntered(MouseEvent	event)	
44	    	     	     {	
45	    	     	     }
46	    	     	     public	void	mouseExited(MouseEvent	event)	
47	    	     	     {	
18	    	     	     }
49	    	     }
50	    	      private	class	JLabelMouseListenerHandler	implements	
MouseListener
51	    	     {
52	    	     	     public	void	mouseEntered(MouseEvent	event)	
53	    	     	     {
54	    	     	     	     txtLabelEvent.append(“Mouse	imleci	
JLabel	bölgesine	girdi\n”);
55	    	     	     }
56	    	     	     public	void	mouseExited(MouseEvent	event)	
57	    	     	     {
58	    	     	     	     txtLabelEvent.append(“Mouse	imleci	
JLabel bölgesinden çıktı\n”);
59	    	     	     }
60	    	     	     public	void	mouseClicked(MouseEvent	event)	
61	    	     	     {	
62	    	     	     }
63	    	     	     public	void	mousePressed(MouseEvent	event)	
64	    	     	     {
65	    	     	     }
66	    	     	     public	void	mouseReleased(MouseEvent	event)	
67	    	     	     {	
68	    	     	     }
69	    	     }
70	    	     public	static	String	ButonAdiAl(int	butonNumarasi)
71	    	     {
72	    	     	     String	butonAdi	=	“”;
73	    	     	     if(butonNumarasi	==	MouseEvent.BUTTON1)
74	    	     	     {
75	    	     	     	     butonAdi	=	“Sol”;
76	    	     	     }
77	    	     	     else	if(butonNumarasi	==	MouseEvent.BUTTON2)
78	    	     	     {
79	    	     	     	     butonAdi	=	“Orta”;
92   Bölüm 6




                80	       	       	        }
                81	       	       	        else	if(butonNumarasi	==	MouseEvent.BUTTON3)
                82	       	       	        {
                83                                 butonAdi = “Sağ”;
                84	       	       	        }
                85	       	       	        return	butonAdi;
                86	       	       }
                87	       	       public	static	void	main(String[]	args)	
                88	       	       {
                89	       	       	        MouseYonetimi	test	=	new	MouseYonetimi();
                90	     	         	        test.setDefaultCloseOperation(JFrame.EXIT_ON_
                CLOSE);
                91	       	       }
                92	       }

          Kodun açıklaması: Container nesnesi ve JLabel nesnesi için birer tane event handler sınıfı
          oluşturduk. İki sınıf da MouseListener interface’ini implement ediyor. Kullanılmayan metodların
          gövdelerini boş bırakarak interface yapısından kaynaklanan derleme hatalarını önlemiş olduk.
          Uygulamada kullanılan statik ButonAdiAl metodu, tıklanan butonun numarasını alarak butona
          bir isim vererek döndürür. Örneğin sol fare butonuna tıklandığında buton kodu olarak “1” değeri
          oluşur, ButonAdiAl metodunu kullanarak “Sol” değeri döndürülür.

          Container nesnesinin ilişkili olduğu ContainerMouseListenerHandler sınıfının içinde bulu-
          nan metodlar aşağıdaki işlevlere sahiptir:

          mousePressed: Fare butonlarından biriyle formun üzerine tıklandığında hangi butona basıldığı
          ve tıklanan pozisyonun x ve y değerleri JTextArea bileşenine eklenir.

          mouseReleased: Tıklandıktan sonra bırakılan mouse butonunun adı JTextArea bileşenine ek-
          lenir.

          mouseClicked: Tıklandıktan sonra bırakılan fare butonunun adı ve tıklanma sayısı JTextArea
          bileşenine eklenir.

          JLabel nesnesinin ilişkili olduğu JLabelMouseListenerHandler sınıfının içinde bulunan me-
          todlar aşağıdaki işlevlere sahiptir:

          mouseEntered: Fare imleci JLabel kontrolünün üzerine geldiğinde ikinci JTextArea nesnesine
          bu bilgi yazılır.

          mouseExited: Fare imleci JLabel kontrolünün bölgesinden çıktığında ikinci JTextArea nesnesine
          bu bilgi yazılır.

          Uygulama çalıştırıldıktan sonra mouse ile JLabel kontrolünün bölgesine girilip çıkıldığında ve
          form üzerine farklı fare butonlarıyla çeşitli seferlerde tıklandığında, uygulama arayüzü aşağıdaki
          gibi bir görünüm alır.
                                                                                                        Swing   93




Java ortamının event altyapısı interface’ler üzerine kurulu olduğu için, içinde birden fazla metod
tanımı bulunan interface’lerin kullanılması durumunda gereksiz metodlar da implement edilmek
zorundadır. Bu durumun önüne geçmek için Adapter sınıfları oluşturulmuştur. Adapter sınıfları
ilgili interface’lerin bütün metodlarını gövdeleri boş olacak şekilde implement eder. Yeni oluşturu-
lan event handler sınıfları Adapter sınıflarından türetilirse sadece gerekli event metodları override
edilebilir. Mouse event’lerinin kontrol edilmesi için MouseAdapter sınıfının temel sınıf olarak kul-
lanıldığı bir uygulamanın kodları aşağıdadır.

       import	java.awt.Container;
      1	
       import	java.awt.FlowLayout;
      2	
       import	java.awt.event.MouseAdapter;
      3	
       import	java.awt.event.MouseEvent;
      4	
       import	javax.swing.JFrame;
      5	
       import	javax.swing.JTextArea;
      6	
       public	class	MouseAdapterTest	extends	JFrame	
      7	
       {
      8	
       	
      9	         private	JTextArea	txtContainerEvent;
      10	        	       public	MouseAdapterTest()
      11	        	       {
      12	        	       	        super(“Mouse	yönetimi”);
      13	        	       	        Container	container	=	getContentPane();
      14	        	       	        container.setLayout(new	FlowLayout());
      15	    	     	     container.addMouseListener(new	
      ContainerMouseHandler());
   Bölüm 6




                16	        	       	        txtContainerEvent	=	new	JTextArea();
                17	        	       	        container.add(txtContainerEvent);
                18	        	       	        setSize(200,	200);
                19	        	       	        setVisible(true);
                20	        	       }
                21	    	     private	class	ContainerMouseHandler	extends	
                MouseAdapter
                22	        	       {
                23	        	       	        public	void	mouseClicked(MouseEvent	event)	
                24	        	       	        {	
                25	    	     	     	      txtContainerEvent.append(event.
                getButton() + “ numaralı butona “ + event.getClickCount() + “ kez
                basıldı ve bırakıldı\n”);
                26	        	       	        }
                27	        	       }
                28	        	       public	static	void	main(String[]	args)	
                29	        	       {
                30	    	     	      MouseAdapterTest	test	=	new	
                MouseAdapterTest();
                31	     	          	        test.setDefaultCloseOperation(JFrame.EXIT_ON_
                CLOSE);
                32	        	       }
                33	        }

          Uygulama çalıştırılıp formun üzerine çeşitli mouse butonlarıyla tıklanırsa arayüz aşağıdaki gibi bir
          görünüme sahip olur.




          Klavye Event’lerinin Yönetilmesi
          Kullanıcının klavye ile etkileşimi sonucunda oluşan event’ler KeyListener interface’ini implement
          eden sınıfların oluşturulması ile kontrol edilir. KeyListener interface’inin içinde aşağıdaki metodlar
          bulunur:

          keyPressed: Klavyedeki herhangi bir tuşa basıldığında tetiklenir.
                                                                                                    Swing   



keyTyped: Aksiyon tuşu olmayan tuşlardan herhangi birine basıldığında tetiklenir. Aksiyon tuşları
ok tuşları, home, end, scroll lock gibi işlevsel özellikleri olan tuşlardır.

keyReleased: Herhangi bir buton bırakıldıktan sonra, yani keyTyped veya keyPressed event’inden
sonra tetiklenir.

Klavye event’lerinin kullanımını gösteren uygulamayı oluşturan kodlar aşağıda verilmiştir.


       import	java.awt.Container;
      1	
       import	java.awt.FlowLayout;
      2	
       import	java.awt.event.KeyEvent;
      3	
       import	java.awt.event.KeyListener;
      4	
       import	javax.swing.JFrame;
      5	
       import	javax.swing.JTextArea;
      6	
       public	class	KeyboardEventTest	extends	JFrame
      7	
       {
      8	
       	
      9	        private	JTextArea	txtContainerEvent;
      10	       	       public	KeyboardEventTest()
      11	       	       {
      12	       	       	       super(“Klavye	yönetimi”);
      13	       	       	       Container	container	=	getContentPane();
      14	       	       	       container.setLayout(new	FlowLayout());
      15	       	       	       txtContainerEvent	=	new	JTextArea();
      16	       	       	       txtContainerEvent.setEnabled(false);
      17	       	       	       container.add(txtContainerEvent);
      18	    	     	     this.addKeyListener(new	
      KeyboardEventHandler());
      19	       	       	       setSize(200,	200);
      20	       	       	       setVisible(true);
      21	       	       }
      22	    	          private	class	KeyboardEventHandler	implements	
      KeyListener
      23	       	       {
      24	       	       	       public	void	keyPressed(KeyEvent	event)	
      25	       	       	       {
      26	    	     	     	     txtContainerEvent.append(“keyPressed\
      tDeğer: “ + event.getKeyText(event.getKeyCode()) + “\n”);
      27	       	       	       }
      28	       	       	       public	void	keyReleased(KeyEvent	event)	
      29	       	       	       {
      30	    	          	       	        txtContainerEvent.append(“keyReleased\t\
      n\n”);
      31	       	       	       }
      32	       	       	       public	void	keyTyped(KeyEvent	event)	
      33	       	       	       {
      34	    	     	     	     txtContainerEvent.append(“keyTyped\
      tDeğer: “ + event.getKeyChar() + “\n”);
   Bölüm 6




                35	         	      	        }
                36	         	      }
                37	         	      public	static	void	main(String[]	args)	
                38	         	      {
                39	    	     	     KeyboardEventTest	test	=	new	
                KeyboardEventTest();
                40	     	          	        test.setDefaultCloseOperation(JFrame.EXIT_ON_
                CLOSE);
                41	         	      }
                42	         }

          Kodun açıklaması: Kullanıcı klavyedeki herhangi bir tuşa bastığında keyPressed event’i tetik-
          lenir. Basılan tuş aksiyon tuşu değilse keyTyped event’i de tetiklenir. Basılan tuş ne olursa olsun
          keyReleased event handler metodu en son çalışır. keyPressed ve keyTyped event handler me-
          todları; çalışan event’in adını ve basılan tuşa karşılık gelen karakter değerini JTextArea bileşenine
          ekler. keyReleased event handler metodu ise tuşun bırakıldığını belirtir, hangi tuş üzerine işlem
          yapıldığını bildirmez. Uygulama çalıştırıldıktan sonra sırasıyla q, home, F2, 7, alt, ctrl tuşlarına
          basılırsa arayüz aşağıdaki gibi bir görünüme kavuşur.




          Layout Yönetimi
          Swing tabanlı arayüzler içeren Java uygulamalarında arayüze eklenen bileşenlerin form üzerin-
          deki görünümleri layout yapılarıyla şekillendirilir.

          FlowLayout: Bu görünümde arayüze eklenen bileşenler soldan sağa doğru eklendikleri sırada
          görüntülenirler. Bütün örneklerimizde FlowLayout görünümünü kullandık. Dört tane JButton nes-
          nesiyle bir tane JTextArea nesnesini FlowLayout biçiminde düzenlenmiş bir Swing arayüzüne
          ekleyelim. Uygulamanın kodları aşağıda verilmiştir.


                 import	java.awt.Container;
                1	
                 import	java.awt.FlowLayout;
                2	
                 import	javax.swing.JButton;
                3	
                                                                                                       Swing   




       import	javax.swing.JFrame;
      4	
       import	javax.swing.JTextArea;
      5	
       public	class	FlowLayoutTest	extends	JFrame	
      6	
       {
      7	
       	
      8	        public	FlowLayoutTest()
       	
      9	        {
      10	       	        	       super(“BorderLayout”);
      11	       	        	       Container	container	=	getContentPane();
      12	       	        	       FlowLayout	layout	=	new	FlowLayout();
      13	       	        	       container.setLayout(layout);
      14	       	        	       JButton	btn1	=	new	JButton(“1.	Buton”);
      15	       	        	       container.add(btn1);
      16	       	        	       JButton	btn2	=	new	JButton(“2.	Buton”);
      17	       	        	       container.add(btn2);
      18	       	        	       JButton	btn3	=	new	JButton(“3.	Buton”);
      19	       	        	       container.add(btn3);
      20	       	        	       JButton	btn4	=	new	JButton(“4.	Buton”);
      21	       	        	       container.add(btn4);
      22                         JTextArea txt = new JTextArea(“Metin alanı”);
      23	       	        	       container.add(txt);
      24	       	        	       setSize(300,	200);
      25	       	        	       setVisible(true);
      26	       	        }
      27	       	        public	static	void	main(String[]	args)	
      28	       	        {
      29	       	        	       FlowLayoutTest	test	=	new	FlowLayoutTest();
      30	     	          	       test.setDefaultCloseOperation(JFrame.EXIT_ON_
      CLOSE);
      31	       	        }
      32	       }

Bileşenler formun üzerine soldan sağa doğru eklenmiştir. Çalışma sırasında formun boyutu de-
ğiştirilirse arayüz kontrollerinin form üzerindeki yerleri de değişecektir. Formun iki farklı boyutu
için arayüzün görünümü aşağıda verilmiştir.




BorderLayout: JFrame sınıfından türeyen sınıfların varsayılan layout görünümüdür. Uygulama
arayüzü kuzey, güney, doğu, batı ve merkez olmak üzere beş parçaya ayrılır. Uygulamaya kon-
   Bölüm 6



          trol ekleme aşamasında hangi bölgeye ekleneceği belirtilir. Dört tane JButton nesnesi ile bir tane
          JTextBox nesnesi içeren bir arayüzü BorderLayout biçiminde oluşturalım.
                import	java.awt.BorderLayout;
                import	java.awt.Container;
                import	javax.swing.JButton;
                import	javax.swing.JFrame;
                import	javax.swing.JTextArea;
                 public	class	BorderLayoutTest	extends	JFrame	
                1	
                 {
                2	
                 	
                3	        public	BorderLayoutTest()
                 	
                4	        {
                 	
                5	        	       super(“BorderLayout”);
                 	
                6	        	       Container	container	=	getContentPane();
                 	
                7	        	       BorderLayout	layout	=	new	BorderLayout(10,	10);
                 	
                8	        	       container.setLayout(layout);
                 	
                9	        	       JButton	btnNorth	=	new	JButton(“Kuzey”);
                10	       	       	        container.add(btnNorth,	BorderLayout.NORTH);
                11	       	       	        JButton	btnSouth	=	new	JButton(“Güney”);
                12	       	       	        container.add(btnSouth,	BorderLayout.SOUTH);
                13                         JButton btnEast = new JButton(“Doğu”);
                14	       	       	        container.add(btnEast,	BorderLayout.EAST);
                15                         JButton btnWest = new JButton(“Batı”);
                16	       	       	        container.add(btnWest,	BorderLayout.WEST);
                17	    	          	        JTextArea	txtCenter	=	new	JTextArea(“Merkez	
                bölge”);
                18	       	       	        container.add(txtCenter,	BorderLayout.CENTER);
                19	       	       	        setSize(300,	200);
                20	       	       	        setVisible(true);
                21	       	       }
                22	       	       public	static	void	main(String[]	args)	
                23	       	       {
                24	    	     	      BorderLayoutTest	test	=	new	
                BorderLayoutTest();
                25	     	         	        test.setDefaultCloseOperation(JFrame.EXIT_ON_
                CLOSE);
                26	       	       }
                27	       }
          JButton kontrolleri arayüzün kuzey, güney, doğu ve batı bölgelerine, JTextArea bileşeni ise mer-
          kez bölgesine eklenmiştir. Uygulama çalıştırıldığında aşağıdaki gibi görünür.
                                                                                                     Swing   




GridLayout: GridLayout biçimi, container’ı satırlar ve sütunlardan oluşan bir grid şeklinde düzen-
ler. GridLayout şeklinde düzenlenmiş bir arayüzdeki bütün bileşenlerin boyutu aynı olur. GridLa-
yout biçiminde düzenlenmiş bir Swing arayüzünü aşağıdaki kod bloğuyla oluşturabiliriz.
       import	java.awt.Container;
      1	
       import	java.awt.GridLayout;
      2	
       import	javax.swing.JButton;
      3	
       import	javax.swing.JFrame;
      4	
       import	javax.swing.JTextArea;
      5	
       public	class	GridLayoutTest	extends	JFrame	
      6	
       {
      7	
       	
      8	        public	GridLayoutTest()
       	
      9	        {
      10	       	       	        super(“GridLayout”);
      11	       	       	        Container	container	=	getContentPane();
      12	       	       	        GridLayout	layout	=	new	GridLayout(2,	3);
      13	       	       	        container.setLayout(layout);
      14	       	       	        JButton	btn1	=	new	JButton(“1.	Buton”);
      15	       	       	        container.add(btn1);
      16	       	       	        JButton	btn2	=	new	JButton(“2.	Buton”);
      17	       	       	        container.add(btn2);
      18	       	       	        JButton	btn3	=	new	JButton(“3.	Buton”);
      19	       	       	        container.add(btn3);
      20	       	       	        JButton	btn4	=	new	JButton(“4.	Buton”);
      21	       	       	        container.add(btn4);
      22                         JTextArea txt = new JTextArea(“Metin alanı”);
      23	       	       	        container.add(txt);
      24	       	       	        setSize(300,	200);
      25	       	       	        setVisible(true);
      26	       	       }
      27	       	       public	static	void	main(String[]	args)	
      28	       	       {
      29	       	       	        GridLayoutTest	test	=	new	GridLayoutTest();
      30	     	         	        test.setDefaultCloseOperation(JFrame.EXIT_ON_
      CLOSE);
      31	     	         }
      32	       }
100   Bölüm 6



           Uygulama çalıştırıldığında aşağıdaki gibi bir arayüz oluşur:




           Bunların dışında daha az kullanılan BoxLayout, CardLayout ve GridBagLayout görünümleri de
           vardır.
7   JDBC
7 JDBC
• Veritabanı Bağlantısının Kurulması

• Veri Değiştirme Komutları (insert, update,
  delete)

• Veri Sorgulama Komutları (Select)

• Parametreli SQL İfadelerinin Çalıştırılması

• Stored Procedure’lerin Çalıştırılması
                                            JDBC
Java uygulamaları üzerinden veri kaynaklarını bulmak ve bulunan kaynaklara bağlanarak bu kay-
naklar üzerinde çeşitli sorguları çalıştırmak için JDBC adı verilen Java API’si kullanılır. JDBC,
.Net ortamındaki ADO.Net yapısının Java platformundaki karşılığıdır. JDBC, platform bağımsız-
lığını sağlayabilmek için, ortamdaki veri kaynaklarına bağlanmak amacıyla kullanılan sürücüleri
çalışma zamanında tespit edebilen bir sürücü yönetim sistemine(Driver Manager) sahiptir. Veri
kaynaklarına bağlanmadan önce sürücülerin yüklenmesini sağlamak için Class.forName()
metodu gereken parametreler kullanılarak çağrılır.

ODBC sürücüsüne sahip olan veri kaynaklarına bağlanmak için JDBC-ODBC köprüsü kullanılır.
Sürücüler bulunduktan sonra ODBC üzerinde kayıtlı bulunan herhangi bir veri kaynağına bağla-
nılabilir. Windows tabanlı işletim sistemleri üzerinde bulunan bir veritabanı yönetim sistemi yazılı-
mındaki bir veritabanına bağlanmak için, bu veritabanının ODBC kaynaklarına eklenmesi gerekir.
Bu işlem denetim masasında veya yönetimsel araçlarda bulunan veri kaynakları (ODBC) seçene-
neği kullanılarak gerçekleştirilebilir.

Bilgisayarımızda bulunan Microsoft SQL Server 2005 veritabanı sunucusu üzerinde dört tablodan
oluşan AlisveriSitesi adında bir veritabanı oluşturarak uygulamalarımızı bu veritabanı üzerinde
çalıştıralım. AlisverisSitesi veritabanını oluşturmak ve sahip olduğu tabloları oluşturmak için kul-
lanılacak SQL ifadeleri ve veritabanının diyagramı Şekil 1’de gösterilmiştir.




       Şekil 1


Örnek Uygulama 7.1:

      1	create	database	AlisverisSitesi
      2	use	AlisverisSitesi
      3	create	table	Urun
      4	(
      5			       urunID	int	primary	key	identity(1,	1),
      6			       urunAdi	varchar(20),
      7			       fiyat	money
      8	)


      9	create	table	Musteri
104   Bölüm 7




                 10	(
                 11		       musteriID	int	primary	key	identity(1,	1),
                 12		       ad	varchar(20),
                 13		       soyad	varchar(30),
                 14	)


                 15	create	table	Siparis
                 16	(
                 17		       siparisID	int	primary	key	identity(1,	1),
                 18		       musteriID	int	foreign	key	references	Musteri(musteriID),
                 19		       siparisTarihi	smalldatetime
                 20	)


                 21	create	table	SiparisDetay
                 22	(
                 23		       siparisID	int	foreign	key	references	Siparis(siparisID),
                 24		       urunID	int	foreign	key	references	Urun(urunID),
                 25		       miktar	int
                 26	)

           Veritabanımızı oluşturduktan sonra denetim masasından veya yönetimsel araçlardan veri kay-
           nakları (ODBC) ayarlarını açalım. Java üzerinden herhangi bir veri kaynağına bağlanmadan önce
           kullanacağımız veritabanı sunucusunu ve veritabanını System DSN menüsünden kayıt edeceğiz.
           System DSN menüsü ilk açıldığında Şekil 2’dekine benzer bir görünüme sahip olacaktır.




                        Şekil 2


           Yeni bir veri kaynağı eklemek için Add butonuna tıklayalım. Karşımıza çıkan pencerede, bağlan-
           mak istediğimiz veri kaynağını seçtikten sonra Finish butonuna tıklayarak veri kaynağımızla ilgili
                                                                                                    JDBC   105



ek bilgiler istenir. Microsoft SQL Server veritabanı sunucusu kullandığımız için en altta bulunan
SQL Server seçeneğini seçmeliyiz.




             Şekil 3


Bir sonraki pencerede, veri kaynağımıza vereceğimiz ismi ve kullanılacak veritabanı sunucusu-
nun adını veya adresini yazdıktan sonra Next butonuna tıklayalım. Veri kaynağı ile ilgili ayarlar
Şekil 4’te görülebilir.




         Şekil 4

Veritabanı sunucumuz belirlendikten sonra, bu sunucuya bağlanmak için kullanılacak olan kimlik
bilgilerinin girileceği ekran karşımıza çıkar. SQL Server veritabanı sunucusuna bağlanmak için
Windows Authentication veya SQL Authentication kullanabiliriz. Windows Authentication kullan-
mamız durumunda kullanıcı adı ve şifre bilgileri istenmez, veritabanı sunucusuna bağlanmak
için sisteme giriş yapmış olan Windows kullanıcı hesabı kullanılır. Bahsedilen ayarlar Şekil 5’te
görülebilir.
106   Bölüm 7




                    Şekil 5

           SQL Server 2005 veritabanı sunucusuna bağlanmak için Windows NT Authentication modunu
           seçtikten sonra Next butonuna tıklayın. AlisverisSitesi adını verdiğimiz sürücüyle bağlanılacak
           olan varsayılan veritabanını en üstteki change default database to checkbox’ı yardımıyla belirle-
           yebiliriz. AlisverisSitesi veritabanını varsayılan veritabanı olarak seçtikten sonra Next butonuna
           ve bir sonraki pencerede Finish butonuna tıklayın. Son üç aşamada karşımıza çıkan ekran gö-
           rüntüleri aşağıdadır.




                        Şekil 6
                                                                                                   JDBC   107




         Şekil 7

Finish butonuna tıkladıktan sonra ODBC veri kaynağının başarıyla eklendiğini belirten bir mesaj
aldık. ODBC kaynağı eklendikten sonra Şekil 8’de gösterilen Test Data Source butonuna tıklaya-
rak veritabanı bağlantımızın doğru çalışıp çalışmadığını kontrol edin. Şekil 9’da görülen mesaj,
veri kaynağına başarıyla bağlandığımızı gösterir.




                     Şekil 8
108   Bölüm 7




                                 Şekil 9


           Veritabanı Bağlantısının Kurulması
           Veritabanına bağlanmak için kullanılacak ODBC kaynağını işletim sistemine ekledikten sonra
           Java ortamı üzerinden AlisverisSitesi veritabanına bağlanmaya çalışalım. Veri kaynağına bağlan-
           mak için aşağıdaki adımların gerçekleşmesi gerekir:

           1� İşletim sistemi üzerinde bulunan JDBC sürücüsünün Class.forName() metodu yardımıyla
              bulunması.
           2. DriverManager sınıfında bulunan getConnection() metodu ile veritabanı bağlantısının
              sağlanması.
           Class.forName metodunun uygulamada kullanılabilmesi için, bu metodu çağıran metodun
           ClassNotFoundException tipinden hata fırlatabilmesi gerekir. Benzer bir şekilde DriverMa-
           nager.getConnection() metodunu çağıran metodun SQLException tipinden hata fırlatabil-
           mesi gerekir. İki metod çağrısını da uygulamanın main metodundan yapacağımız için main meto-
           dumuz bu iki hatayı da fırlatabilecek şekişlde oluşturulur. Aşağıdaki kodu yazıp çalıştırdığımızda
           herhangi bir mesaj almazsak ODBC kaynağına bağlantı kurmayı başardık demektir.

           Örnek Uygulama 7.2:

                 1	import	java.sql.Connection;
                 2	import	java.sql.DriverManager;
                 3 import java.sql.SQLException;
                 4	public	class	VeritabaniBaglantisi	
                 5	{
                 6			   public	static	void	main(String[]	args)	throws	
                 ClassNotFoundException, SQLException
                 7			      {
                 8			      	        try	
                 9			      	        {
                 10		      	        	       Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);
                 11		   	     	     Connection	baglanti	=	DriverManager.
                 getConnection(“jdbc:odbc:AlisverisSites1i”);
                                                                                                         JDBC   109




      12		       	       }	
      13		       	       catch	(Exception	e)	
      14		       	       {
      15		       	       	        System.out.println(e.getMessage());
      16		       	       }
      17		       }
      18	}

Eğer bağlantı kurma aşamasında SQLException veya ClassNotFoundException oluşursa
aşağıdaki iki hata mesajından birini alırız.

      [Microsoft][ODBC Driver Manager] Data source name not found and no
      default driver specified

      sun.jdbc.ODBC.JdbcOdbcDriver

JDBC altyapısı kullanılarak veritabanı sunucularının desteklediği komutlar çalıştırılabilir. SQL
Server veritabanı sunucusu üzerinde veri değiştirme komutları (insert, update, delete), veri
tanım komutları(create, alter, drop) ve sorgu komutları (select) çalıştırılarak uygulamanın
ihtiyaçlarına göre bir veri erişim altyapısı oluşturulması sağlanabilir.

Veri kaynağı üzerinde çalıştırılacak ifadeler, Connection nesnesi aracılığıyla oluşturulur. Conne-
ction nesnesinin createStatement() metodu ile oluşturulan Statement nesnesi veritabanına
SQL ifadelerini göndermek amacıyla kullanılır. Statement nesnesi oluştuktan sonra, bu nesnenin
sahip olduğu executeXxx metodları ile SQL ifadeleri veritabanı sunucusu üzerinde çalıştırılır.
Connection nesnesini sahip olduğı metodlarla Statement tipinden başka tiplerde ifadeler de oluş-
turulabilir. (Örneğin BLOB, XML..)


Veri Değiştirme Komutları (insert, update, delete)
JDBC kütüphanesi kullanılarak veritabanı üzerinde insert, update, delete gibi veri ile ala-
kalı komutlar çalıştırmak için genellikle Statement nesnesinin executeUpdate komutları kullanılır.
executeUpdate komutları, veritabanı üzerinde çalıştırılan ifadeden etkilenen kayıt sayısını tam
sayı değeri olarak döndürür ve ADO.Net mimarisinde bulunan Command nesnesinin Execute-
NonQuery metoduna benzerlik gösterir.

Örnek Uygulama 7.3’de verdiğimiz kod bloğunda veritabanına üç tane müşteri ve beş tane ürün
eklenmektedir. Tablolarda bulunan xxxID alanları identity olarak tanımlandığından, değerleri oto-
matik olarak ve birer birer artarak verilir. Bu sebepten dolayı insert ifadesinin içinde xxxID alanla-
rının bulunması hata oluşmasına neden olur.

Örnek Uygulama 7.3:

      1	import	java.sql.Connection;
      2	import	java.sql.DriverManager;
      3 import java.sql.SQLException;
      4	import	java.sql.Statement;
      5	public	class	VeritabaniBaglantisi	
      6	{
      7			   public	static	void	main(String[]	args)	throws	
      ClassNotFoundException, SQLException
      8			       {
      9			       	       try	
110   Bölüm 7



                 10		       	       {
                 11		       	       	        Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);
                 12		   	     	     Connection	dbConnection	=	DriverManager.
                 getConnection(“jdbc:odbc:AlisverisSitesi”);
                 13		   	     	     Statement	staInsert	=	dbConnection.
                 createStatement();
                 14		   	     	     staInsert.executeUpdate(“INSERT	INTO	
                 Musteri(ad, soyad) VALUES (‘Yalçın’, ‘Kaya’)”);
                 15		   	     	     staInsert.executeUpdate(“INSERT	INTO	
                 Musteri(ad,	soyad)	VALUES	(‘Erkut’,	‘Kutlar’)”);
                 16		   	     	     staInsert.executeUpdate(“INSERT	INTO	
                 Musteri(ad,	soyad)	VALUES	(‘Hasan’,	‘Polat’)”);
                 17		   	     	     staInsert.executeUpdate(“INSERT	INTO	
                 Urun(urunAdi,	fiyat)	VALUES	(‘1GB	Ram’,	40)”);
                 18		   	     	     staInsert.executeUpdate(“INSERT	INTO	
                 Urun(urunAdi,	fiyat)	VALUES	(‘3	GHz	CPU’,	80)”);
                 19		   	     	     staInsert.executeUpdate(“INSERT	INTO	
                 Urun(urunAdi,	fiyat)	VALUES	(‘2	GB	USB	Bellek’,	30)”);
                 20		   	     	     staInsert.executeUpdate(“INSERT	INTO	
                 Urun(urunAdi, fiyat) VALUES (‘256 MB Ekran Kartı’, 20)”);
                 21		   	     	     staInsert.executeUpdate(“INSERT	INTO	
                 Urun(urunAdi,	fiyat)	VALUES	(‘DVD	Writer’,	45)”);
                 22		       	       	        staInsert.close();
                 23		       	       }	
                 24		       	       catch	(Exception	e)	
                 25		       	       {
                 26		       	       	        System.out.println(e.getLocalizedMessage());
                 27		       	       }
                 28		       }
                 29	}

           Kodun açıklaması: JDBC sürücüsü çalışma zamanında bulunduktan sonra daha önce oluştu-
           rulan AlisverisSitesi isimli ODBC kaynağı aracılığıyla AlisverisSitesi veritabanı üzerinde insert
           ifadeleri çalıştırıldı. Statement nesnesinin işi bittikten sonra kapatılması, alınan sistem ve verita-
           banı kaynaklarının geri verilmesini sağlar. Uygulamanın çalışması aşamasında bir hata oluşmaz-
           sa arayüz üzerinde herhangi bir mesaj oluşmaz. Gerçek bir uygulamada ürün ve müşteri bilgileri
           Java kodunun içinde girilmez, web veya işletim sistemi ortamında çalışan bir kullanıcı arayüzü
           aracılığıyla kullanıcıdan alınır. İlerleyen sayfalarda, Swing görsel programlama kütüphanesini kul-
           lanarak benzer bir uygulama geliştireceğiz.

           Veri Sorgulama Komutları (Select)
           Select komutunun Java ortamından veritabanı sunucusu üzerinde çalıştırılması için benzer nes-
           neler oluşturulur. İşletim sistemi üzerinde bulunan JDBC sürücüsüne ulaşıldıktan sonra ODBC
           kaynağına bağlanılır, bu bağlantı üzerinden Statement nesnesi oluşturulur ve Statement nesne-
           sinin executeXxx komutlarından biri çalıştırılır. Veritabanından tek bir tam sayı değişkeni yerine
           birden fazla satır ve sütündan oluşabilen bir değer kümesi döndüğünden, select ifadelerinin
           çalıştırılması insert, update, delete ifadelerinin çalıştırılmasından farklıdır. executeXxx ko-
           mutları select ifadelerini veritabanına göndermek için kullanıldığında geriye bir sonuç kümesi
           (result set) döndürür. Bu sonuç kümesi veri kaynağına bağlı olarak çalışan tek yönlü bir işaretçi
                                                                                                 JDBC   111



yapısıdır ve ADO.Net yapısında bulunan xxxDataReader sınıflarının Java ortamındaki karşılı-
ğıdır. Sonuç kümesi alındıktan sonra kümenin sonuna gelene kadar okuma işlemi tekrar edilir ve
bu işlem döngüler aracılığıyla gerçekleştirilir.
AlisverisSitesi veritabanında bulunan Urun tablosundaki verileri okuyalım:

Örnek Uygulama 7.4:

      1	import	java.sql.Connection;
      2	import	java.sql.DriverManager;
      3	import	java.sql.ResultSet;
      4 import java.sql.SQLException;
      5	import	java.sql.Statement;
      6	public	class	Urunler	
      7	{
      8			   public	static	void	main(String[]	args)	throws	
      ClassNotFoundException, SQLException
      9			      {
      10		      	       try	
      11		      	       {
      12		      	       	       Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);
      13		   	     	     Connection	dbConnection	=	DriverManager.
      getConnection(“jdbc:odbc:AlisverisSitesi”);
      14		   	     	     Statement	staSelect	=	dbConnection.
      createStatement();
      15		   	     	     ResultSet	resultSet	=	staSelect.
      executeQuery(“SELECT urunID, urunAdi, fiyat FROM Urun”);
      16		      	       	       while(resultSet.next())
      17		      	       	       {
      18		   	     	     	               System.out.print(resultSet.
      getInt(“urunID”));
      19		   	     	     	     System.out.print(“\t”	+	resultSet.
      getString(“urunAdi”)	+	“\t\t”);
      20		   	     	     	               System.out.println(resultSet.
      getDouble(“fiyat”));
      21		      	       	       }
      22		      	       	       staSelect.close();
      23		      	       }	
      		        catch	(Exception	e)	
      		        {
      		        	       System.out.println(e.getLocalizedMessage());
      		        }
      	}
      }

Kodun açıklaması: Daha önceki uygulamada yaptığımız gibi JDBC sürücüsünü bulduktan sonra
ODBC veri kaynağına bağlantıyı kurduk ve bağlantı üzerinden Statement nesnesini oluşturduk.
executeUpdate() metodu yerine executeQuery() metodunu yazdığımızda geri dönüş ti-
pinin ResultSet olduğunu görürür. Bu durum, veritabanı sunucusu üzerinde çalışan ifadenin bir
değer kümesi döndürebileceğini gösterir. executeQuery metoduna parametre olarak “SELECT
112   Bölüm 7



           urunID, urunAdi, fiyat from Urun” şeklindeki SQL ifadesini yazdığımızdan dolayı exe-
           cuteQuery metodu Urun tablosundaki bütün verileri sorgulayarak ResultSet cinsinden bir nesne
           oluşturur ve bu nesnenin veri kaynağına doğrudan bağlı olmasını sağlar. Bu noktadan sonra veri
           kaynağına bağlı durumda olan ResultSet nesnesi ile veriler üzerine tek yönlü ve salt okunur bir
           biçimde gezebilirir.

           Uygulama çalıştığı zaman Örnek Uygulama 7.5’teki gibi bir çıktı alınır:

           Örnek Uygulama 7.5:

                  1GB	Ram	
                 1	                  	       	        40.0
                  3	GHz	CPU	
                 2	                  	       	        80.0
                  2	GB	USB	Bellek	
                 3	                          	        30.0
                  256	MB	Ekran	Karti	
                 4	                                   20.0
                  DVD	Writer	 	
                 5	                          	        45.0


           Parametreli SQL İfadelerinin Çalıştırılması
           JDBC kütüphanesi komutlarını kullanarak parametreli SQL ifadeleri de çalıştırılabilir. ADO.Net
           kütüphanesi kullanılarak çalıştırılan SQL sorgularında “@” karakteri ile başlayan parametrelerin
           tanımlanması gibi JDBC mimarisinde “?” karakteri ile parametreler oluşturulur. ADO.Net’te oldu-
           ğu gibi parametre adının belirtilmesine gerek yoktur, parametreler sırayla eklenirse sorgu doğru
           şekilde çalışır. Parametresiz SQL ifadelerinin çalıştırılması için Statement nesnesi kullanılmasına
           karşın parametreli SQL ifadelerinin çalıştırılması için PreparedStatement nesnesi kullanılır.
           Daha önce bahsettiğimiz gibi veritabanına gönderilen ve sorguların sınırlandırılmasını sağlayan
           veriler kullanıcı arayüzünden alınabilir. Kullanıcı tarafından veri girişinin yapıldığı durumlarda kötü
           niyetli kullanıcıların sisteme zarar vermesini engellemek için parametrik sorguların oluştulması
           gerekir.

           Bir SQL ifadesinin parametreli olarak Java ortamında çalıştırılmasını ve sorgu sonucunda dönen
           değer kümesinin ekranda gösterilmesini sağlayan kod Örnek Uygulama-7.6’da gösterilmiştir.

           Örnek Uygulama 7.6:

                 1	import	java.sql.Connection;
                 2	import	java.sql.DriverManager;
                 3	import	java.sql.PreparedStatement;
                 4	import	java.sql.ResultSet;
                 5 import java.sql.SQLException;
                 6	public	class	ParametreliSqlSorgusu	
                 7	{
                 8	public	static	void	main(String[]	args)	throws	
                 ClassNotFoundException, SQLException
                 9	{
                 9	Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);
                 10	Connection	dbConnection	=	DriverManager.getConnection(“jdbc:
                 odbc:AlisverisSitesi”);
                 11	PreparedStatement	statement	=	dbConnection.
                 prepareStatement(“SELECT * FROM Urun WHERE fiyat > ? AND fiyat <
                 ?”);
                 12	statement.setDouble(1,	20);
                 13	statement.setDouble(2,	60);
                                                                                                        JDBC   113



      14 ResultSet resultSet = statement.executeQuery();
      15	while(resultSet.next())
      16	{
      17	System.out.println(resultSet.getInt(“urunID”)	+	“	
      “	+	resultSet.getString(“urunAdi”)	+	“	“	+	resultSet.
      getDouble(“fiyat”));	
      18	}
      19	statement.close();
      20	}
      21	}

Kodun Açıklaması: Select ifadesi iki tane parametre ile sınırlandırılarak belirli bir fiyat aralı-
ğındaki ürünlerin getirilmesi sağlanmıştır. PreparedStatement nesnesi, Connection nesnesi
tarafından oluşturulur. Select ifadesinin içinde bulunan “?” karakterleri parametrelerin bulunaca-
ğı yerlerdir ve bu parametre değerleri PreparedStatement nesnesinin setXxx metodları ile
verilir. Örneğimizde iki tane fiyat parametresine değer vermek amacıyla PreparedStatement
nesnesinin setDouble metodunu kullandık. setXxx metodlarının ilk parametresi, veritabanına
gönderilecek sorgunun içinde bulunan parametresinin indeksini belirtir. “SELECT * FROM Urun
WHERE fiyat > ? AND fiyat < ?” sorgusunda ilk parametre değerini 20, ikinci parametre
değerini 60 olarak verdik. Bu aşamadan sonra, parametresiz ifadelerin çalıştırılmasında yaptı-
ğımız gibi PreparedStatement nesnesinin executeXxx metodlarından birini çalıştırarak ça-
lıştırılacak ifadeyi veritabanı sunucusuna göndeririz. Örnekte Select ifadesi kullandığımız için,
dönen veri kümesini ResultSet nesnesi aracılığıyla aldık ve ekrana bastık. Uygulama çalıştırıldı-
ğında oluşan ekran çıktısı Örnek Uygulama 7.7’deki gibidir:

Örnek Uygulama 7.7:

      1	1GB	Ram	40.0
      3	2	GB	USB	Bellek	30.0
      5	DVD	Writer	45.0

Stored Procedure’lerin Çalıştırılması
Stored procedure’ler veritabanı sunucuları üzerinde bulunan ve farklı veritabanı yönetim sistemi
yazılımlarında farklı biçimlerde oluşturulan prosedürel programlama yapılarıdır. Genelde iş man-
tığının bir bölümünün uygulamadan alınıp veritabanı sunucusuna aktarılması amacıyla kullanılır-
lar. Stored procedure yapıları parametre kullanılarak çalıştırıldığı için ve yetkilendirme seviyeleri
veritabanı tablolarından farklı olarak ayarlanabildiği için uygulama güvenliğinin arttırılmasını da
sağlar. JDBC kütüphanesi ile stored procedure’leri çalıştırmak için Connection nesnesi üzerinden
bir CallableStatement nesnesi oluşturulur.

Örnek veritabanımızda bulunan ürün ve müşteri tablolarına veri eklemek amacıyla kullanmak için
iki tane stored procedure oluşturalım.

Örnek Uygulama 7.8:

      1	CREATE	PROC	insUrun
      2	@urunAdi	VARCHAR(20),
      3	@fiyat	MONEY
      4	AS
      5	INSERT	INTO	Urun	(urunAdi,	fiyat)
      6	VALUES	(@urunAdi,	@fiyat)
      7	GO
114   Bölüm 7



                 8		CREATE	PROC	insMusteri
                 9		@ad	VARCHAR(20),
                 10	@soyad	VARCHAR(30)
                 11	AS
                 12	INSERT	INTO	Musteri	(ad,	soyad)
                 13	VALUES	(@ad,	@soyad)
                 14	GO

           Örnek Uygulama 7.8’de verdiğimiz SQL ifadeleri ile oluşturulan stored procedure’leri çalıştırmak
           için aşağıdaki gibi bir Java uygulaması oluşturabiliriz.

           Örnek Uygulama 7.9:

                 1	import	java.sql.CallableStatement;
                 2	import	java.sql.Connection;
                 3	import	java.sql.DriverManager;
                 4 import java.sql.SQLException;
                 5	public	class	StoredProcedure	
                 6	{
                 7			   public	static	void	main(String[]	args)	throws	
                 ClassNotFoundException, SQLException
                 8			      {
                 9			      	       try	
                 10		      	       {
                 11		      	       	       Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);
                 12		   	     	     Connection	dbConnection	=	DriverManager.
                 getConnection(“jdbc:odbc:AlisverisSitesi”);
                 13		   	     	     CallableStatement	staInsertUrun	=	
                 dbConnection.prepareCall(“{call insUrun(?, ?)}”);
                 14		   	          	       staInsertUrun.setString(1,	“Toshiba	M70	
                 Notebook”);
                 15		      	       	       staInsertUrun.setDouble(2,	1200);
                 16		      	       	       int	rowCount	=	staInsertUrun.executeUpdate();
                 17		      	       	       if(rowCount	==	0)
                 18		      	       	       {
                 19		      	       	       	       System.out.println(“Ürün	eklenemedi”);
                 20		      	       	       }
                 21		      	       	       else
                 22		      	       	       {
                 23		      	       	       	       System.out.println(“Ürün	eklendi”);
                 24		      	       	       }
                 25		   	     	     CallableStatement	staInsertMusteri	=	
                 dbConnection.prepareCall(“{call insMusteri(?, ?)}”);
                 26		      	       	       staInsertMusteri.setString(1,	“Ahmet”);
                 27		      	       	       staInsertMusteri.setString(2,	“Balaban”);
                 28		      	       	       rowCount	=	staInsertUrun.executeUpdate();
                 29		      	       	       if(rowCount	==	0)
                                                                                                      JDBC   115



30                       {

31                               System.out.println(“Müşteri eklenemedi”);

32                       }

33                       else

34                       {

35                               System.out.println(“Müşteri eklendi”);

36                       }

37                       staInsertUrun.close();

38                       staInsertMusteri.close();

39              }

40              catch(Exception e)

41              {

42                       System.out.println(e.getMessage());

43              }

44      }

45 }


Kodun Açıklaması: Veritabanı bağlantısının sağlanması için gereken ayarları yaptıktan sonra
stored procedure çalıştırmak için Connection nesnesi üzerinden iki tane CallableState-
ment nesnesi oluşturduk. Bu nesnelerden biri insUrun stored procedure’ünün çalıştırılması için,
diğeri insMusteri stored procedure’ünün çalıştırılması için gerekli. Stored procedure çağrısının
yapılması için “{call sp_name(?, ..)}” ifadesi kullanılır. Bu ifadede sp_name metni yerine
çalıştırılacak stored procedure’ün adı yazılır. Stored procedure’ü çalıştırmak için gereken para-
metreler daha önce yaptığımız gibi Statement nesnelerinin setXxx metodları kullanılarak verilir.
insMusteri prosedürünü çalıştırmak için müşterinin ad ve soyad değerlerini, insUrun prose-
dürünü çalıştırmak için ürünün ad ve fiyat değerlerini parametre olarak verdikten sonra ifadeleri
executeUpdate metodu ile çalıştırdık ve etkilenen kayıt sayısını kontrol ederek ürün ve müşteri
verilerinin veritabanına eklenip eklenmediği bilgisini ekrana bastık. Uygulama çalıştırıldığı zaman
Örnek Uygulama 7.10’da olduğu gibi bir çıktı alınırsa ürün ve müşteri bilgilerini başarıyla ekledik
demektir.

Örnek Uygulama 7.10:

       1	Ürün	eklendi
       2 Müşteri eklendi

Veritabanı Erişimi için Bileşen Oluşturulması:
Veritabanı sunucuları üzerinde çalıştırılacak metodlar merkezi bir package altında toplanırsa,
veritabanı sunucusu üzerinde herhangi bir değişiklik olması durumunda karşılaşılacak bakım
maliyeti düşürülebilir. Bunun yanında uygulamanın geliştirilmesi aşamasında veritabanı konfigü-
rasyonu ve çeşitli komutların veritabanı sunucusu üzerinde çalıştırılması daha kolay bir şekilde
gerçekleştirilebilir. Bu amaçla kullanılabilecek temel bir veri erişim bileşeni oluşturalım.
116   Bölüm 7



           Şimdiye kadar kullandığımız veritabanı erişim yöntemlerini bir sınıf altında toplayabiliriz. Oluştura-
           cağımız bileşenin farklı veritabanı tabloları ile kullanılabilmesi ve geri dönüş değerlerini temel veri
           tipleri şeklinde döndürebilmesi gerekir. Alt yapıda kullanılan veritabanı sunucusunun değişmesi
           riskinin olduğu senaryolarda, veritabanı sistemine bağımlı olmayan veri tiplerinin kullanılması bü-
           yük avantaj sağlayacaktır.

           Veri erişim bileşeninin kodu aşağıda verilmiştir. Bileşen ayrı bir Java paketi (package) şeklinde
           oluşturulmuştur ve bu bileşeni başka bir yerde kullanmak için import anahtar kelimesi ile uygula-
           maya eklemek gerekir.

           Örnek Uygulama 7.11:

                 1	package	dbAccess;
                 2	import	java.sql.Connection;
                 3	import	java.sql.DriverManager;
                 4	import	java.sql.PreparedStatement;
                 5	import	java.sql.ResultSet;
                 6	import	java.sql.ResultSetMetaData;
                 7 import java.sql.SQLException;
                 8	import	java.sql.Statement;
                 9	import	java.util.ArrayList;
                 10	public	class	DbConnection	
                 11	{
                 12		       private	Connection	connection;
                 13     public DbConnection() throws SQLException,
                 ClassNotFoundException
                 14		       {
                 15		       	        Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);
                 16		   	     connection	=	DriverManager.getConnection(“jdbc:odbc:
                 AlisverisSitesi”);
                 17		       }
                 18     public int NonQuery(String commandText) throws
                 SQLException
                 19		       {
                 20                  Statement stNonQuery = connection.createStatement();
                 21                  int rowCount = stNonQuery.executeUpdate(commandText)
                 ;
                 22                  stNonQuery.close();
                 23		       	        return	rowCount;
                 24		       }
                 25     public int NonQuery(String commandText, Object[]
                 parameterValues) throws SQLException
                 26		       {
                 27           PreparedStatement pstNonQuery = connection.prepareSt
                 atement(commandText);
                 28		   	     for	(int	parameterIndex	=	0;	parameterIndex	<	
                 parameterValues.length;	parameterIndex++)	
                 29		       	        {
                                                                    JDBC   117



30                 pstNonQuery.setObject(parameterIndex + 1,
parameterValues[parameterIndex]);
31		   	     }
32           int rowCount = pstNonQuery.executeUpdate();
33           pstNonQuery.close();
34		   	     return	rowCount;
35		   }
36		   public	ArrayList	ReturnArrayList(String	commandText)	
throws SQLException
37		   {
38		   	     ArrayList	result	=	new	ArrayList();
39           Statement stQuery = connection.createStatement();
40           ResultSet resultSet = stQuery.executeQuery(commandTe
xt);
41		   	     ResultSetMetaData	metaData	=	resultSet.
getMetaData();
42		   	     int	columnCount	=	metaData.getColumnCount();
43		   	     while(resultSet.next())
44		   	     {
45		   	     	     String[]	row	=	new	String[columnCount];
46		   	     	     for(int	columnIndex	=	0;	columnIndex	<	
columnCount;	columnIndex++)
47		   	     	     {
48		   	     	     	     row[columnIndex]	=	resultSet.
getString(columnIndex	+	1).toString();
49		   	     	     }
50		   	     	     result.add(row);
51		   	     }
52           stQuery.close();
53		   	     return	result;
54		   }
55		   public	ArrayList	ReturnArrayList(String	commandText,	
Object[] parameterValues) throws SQLException
56		   {
57		   	     ArrayList	result	=	new	ArrayList();
58           PreparedStatement pstQuery = connection.prepareState
ment(commandText);
59		   	     for	(int	parameterIndex	=	0;	parameterIndex	<	
parameterValues.length;	parameterIndex++)	
60		   	     {
61                 pstQuery.setObject(parameterIndex + 1, paramet
erValues[parameterIndex]);
62		   	     }
63           ResultSet resultSet = pstQuery.executeQuery();
64		   	     ResultSetMetaData	metaData	=	resultSet.
getMetaData();
118   Bölüm 7



                 65		      	        int	columnCount	=	metaData.getColumnCount();
                 66		      	        while(resultSet.next())
                 67		      	        {
                 68		      	        	       String[]	row	=	new	String[columnCount];
                 69		   	     	     for(int	columnIndex	=	0;	columnIndex	<	
                 columnCount;	columnIndex++)
                 70		      	        	       {
                 71	    	     	     	     row[columnIndex]	=	resultSet.
                 getString(columnIndex	+	1).toString();
                 71		      		       	       }
                 72		      	        	       result.add(row);
                 73		      	        }
                 74                 pstQuery.close();
                 75		      	        return	result;
                 76		      }
                 77	}

           Kodun açıklaması: Veri erişim mantığını uygulamadan ayırmak için dbAccess isimli bir packa-
           ge içinde DbConnection isimli bir sınıf oluşturduk. Geri dönüşsüz sorguları çalıştırmak için iki
           tane metod ve değer kümesi döndüren sorguları çalıştırmak için iki tane metod yazdık. İki işlev
           için de ikişer tane metod yazmamızın sebebi SQL ifadelerini çalıştırırken parametre eklenmesine
           olan sağlamaktır. Sınıfta bulunan nitelikleri ve metodları kısaca açıklayalım:

           Connection	 connection: Veritabanına bağlanmak amacıyla kullanılan nesne. Bütün State-
           ment nesneleri Connection nesnesi tarafından oluşturulur.

           DbConnection():DbConnection sınıfının yapıcı metodu. JDBC sürücüsünü bulmak ve Con-
           nection nesnesine ilk değerini vermek için kullanılır.

           int NonQuery(String commandText): Parametresiz ve veri kümesi döndürmeyen SQL ifa-
           delerinin çalıştırılması amacıyla kullanılır. commandText parametresi ile, çalıştırılacak olan SQL
           ifadesi alınır. Statement nesnesi oluşturulduktan sonra executeUpdate komutu çalıştırılacak
           işlemden etkilenen kayıt sayısı veritabanı sunucusundan alınır ve döndürülür.

           int NonQuery(String commandText, Object[] parameterValues): Veritabanı üze-
           rinde çalıştırılacak olan SQL ifadesi commandText parametresi ile, sorgunun içinde bulunan
           parametrelerin değerleri Object dizisi cinsinden parameterValues parametresiyle alınır. Con-
           nection nesnesi üzerinden PreparedStatement nesnesi oluşturulduktan sonra parameter-
           Values dizisinin eleman sayısı kadar parametre setValue(Object) metodu ile PreparedS-
           tatement nesnesine eklenir . SQL ifadesi çalıştırıldıktan sonra veritabanında etkilenen kayıt
           sayısı geri döndürülür.

           ArrayList	ReturnArrayList(String	commandText): Veritabanı üzerine çalıştırılan Se-
           lect ifadesinin sonucunda dönen değer kümesi ResultSet nesnesi üzerinden alınır. ResultSet-
           MetaData nesnesi, veritabanından dönen sonuç kümesinin sütun sayını almak için kullanılır.
           Veritabanından dönen değerleri uygulamaya göndermek için ArrayList nesnesi kullanılmıştır.
           ArrayList nesnesinin her bir kaydı, veritabanından gelen bir satır veriyi içerir. Bir veri satırını
           tutmak için String dizisi kullanılmıştır ve String dizisinin eleman sayısı ResultSetMetaDa-
           ta nesnesinden alınan sütun sayısına göre belirlenir. ResultSet nesnesinin içindeki kayıt sayısı
           kadar String dizisi oluşturulur ve ArrayList’e eklenir. resultSet.getString() metodu
           columnIndex+1 parametresiyle çalıştırılır. Bunun sebebi, .Net ortamından farklı olarak para-
           metre ve sütun indekslerinin 1 değerinden başlamasıdır.
                                                                                             JDBC   119



ArrayList	 ReturnArrayList(String	 commandText,	 Object[]	 paramaterValu-
es): Parametreli select ifadelerinin çalıştırılması için bu metod kullanılır. parameterValues
Object dizisi aracılığıyla select ifadesinin parametre değerleri alınır ve PreparedStatement
nesnesine setObject() metodu yardımıyla eklenir. Bir önceki metod yapısında olduğu gibi
ArrayList nesnesi oluşturulur. ArrayList nesnesinin her bir kaydı veritabanından gelen bir
satırı tutan String dizisinden oluşur.

Örnek Uygulama 7.12:

      1 import java.sql.SQLException;
      2	import	java.util.ArrayList;
      3	import	dbAccess.DbConnection;
      4	public	class	VeriErisimi	
      5	{
      6			   public	static	void	main(String[]	args)	throws	
      ClassNotFoundException, SQLException
      7			     {
      8			     	       DbConnection	connection	=	new	DbConnection();
      9                // Yeni bir ürün veritabanına kaydediliyor
      10           int rowCount = connection.NonQuery(“INSERT INTO Urun
      (urunAdi, fiyat) VALUES (‘HP 870cxi Yazıcı’, ‘70’)”);
      11		     	       if(rowCount	!=	0)
      12		     	       {
      13		     	       	       System.out.println(“Ürün	kaydedildi”);
      14		     	       }
      15		     	       else
      16		     	       {
      17		     	       	       System.out.println(“Ürün	kaydedilemedi”);
      18		     	       }
      19               // Yeni bir müşteri veritabanına kaydediliyor
      20		     	       Object[]	musteriInsertParameters	=	new	Object[2];
      21		     	       musteriInsertParameters[0]	=	“Veli”;
      22		     	       musteriInsertParameters[1]	=	“Karaman”;
      23           rowCount = connection.NonQuery(“INSERT INTO Musteri
      (ad, soyad) VALUES (?, ?)”, musteriInsertParameters);
      24		     	       if(rowCount	!=	0)
      25		     	       {
      26                       System.out.println(“Müşteri kaydedildi”);
      27		     	       }
      28		     	       else
      29		     	       {
      30                       System.out.println(“Müşteri kaydedilemedi”);
      31		     	       }
      32		     	       System.out.println();
      33           // Veritabanından belirli bir fiyat aralığındaki
      ürün bilgileri çekilip ekrana basıldı
      34		     	       Object[]	urunSelectParameters	=	new	Object[2];
120   Bölüm 7



                 35		      	       urunSelectParameters[0]	=	30;
                 36		      	       urunSelectParameters[1]	=	60;
                 37		   	     ArrayList	arrUrun	=	connection.
                 ReturnArrayList(“SELECT * FROM Urun WHERE Fiyat BETWEEN ? AND ?”,
                 urunSelectParameters);
                 38		      	       for	(Object	object	:	arrUrun)	
                 39		      	       {
                 40		      	       	       String[]	urun	=	(String[])object;
                 41		      	       	       for(int	i	=	0;	i	<	urun.length;	i++)
                 42		      	       	       {
                 43		      	       	       	       System.out.print(urun[i]	+	“\t”);
                 44		      	       	       }
                 45		      	       	       System.out.println();
                 46		      	       }
                 47		      	       System.out.println();
                 48           // Veritabanından bütün müşteri bilgileri çekilip
                 ekrana basıldı
                 49		   	     ArrayList	arrMusteri	=	connection.
                 ReturnArrayList(“SELECT	*	FROM	Musteri”);
                 50		   	     for	(Object	object	:	arrMusteri)	
                 51		   	     {
                 52		   	     	     String[]	musteri	=	(String[])object;
                 53		   	     	     for(int	i	=	0;	i	<	musteri.length;	i++)
                 54		   	     	     {
                 55		   	     	     	     System.out.print(musteri[i]	+	“\t”);
                 56		   	     	     }
                 57		   	     	     System.out.println();
                 58		   	     }
                 59		      }
                 60	}

           Uygulamada; müşteri kaydı eklenmesi için parametreli NonQuery metodu, ürün kaydı eklen-
           mesi için parametresiz NonQuery metodu, belirli bir fiyat aralığındaki ürünlerin çekilmesi için
           parametreli ReturnArrayList metodu, bütün müşteri bilgilerinin çekilmesi için parametresiz
           ReturnArrayList metodu kullanılmıştır. Uygulama çalıştırıldığında aşağıdaki gibi bir ekran
           çıktısı alınır.

           Örnek Uygulama 7.13:

                 Ürün	kaydedildi
                 Müşteri kaydedildi


                  1GB	Ram	
                 1	                	       40.0000	
                  2	GB	USB	Bellek	
                 2	                        30.0000	
                  DVD	Writer	 	
                 3	                        45.0000	


                 1 Yalçin          Kaya
                 2	Erkut		         Kutlar	
                 3	Hasan		         Polat	
                 4	Veli			         Karaman												
8   JSP
8 JSP
• JSP Teknolojisinde Kullanılan Etiketler

• JSP Direktifleri

• JSP Script Etiketleri

• Form Verilerinin Kullanılması

• Durum Yönetimi
                                             JSP
Java platformunu kullanarak web uygulamaları geliştirmek için JSP (Java Server Pages) tekno-
lojisi kullanılır. JSP, .Net ortamının web geliştirme teknolojisi olan ASP.Net mimarisinin Java or-
tamındaki karşılığıdır. ASP.Net uygulamaları geliştirirken kullanılan code-behind mimarisini JSP
ortamında doğrudan bir karşılığı olmadığından Java kodları ile HTML kodları aynı sayfanın içinde
bulunur. JSP uygulamalarında iş mantığını web sayfalarından ayırmak ve uygulamaları bileşen-
lere bölmek için Java tabanlı Servlet mimarisi kullanılılır. Bu bölümde JSP uygulaması geliştirme
ve Servlet bileşenleri oluşturmayı öğreneceğiz.

JSP uygulamalarını ve Servlet bileşenlerini çalıştırmak için aşağıdaki adresten Apache Tomcat
sunucusunun işletim sisteminize uygun olan versiyonunu indirebilirsiniz. http://tomcat.apache.
org/download-60.cgi

http://apache.karegen.com/tomcat/tomcat-6/v6.0.14/bin/apache-tomcat-6.0.14.exe

Windows binary formatında indirilen Tomcat sunucusunun kurulumu aşağıda adım adım göste-
rilmiştir.

Kurulum standart Windows uygulaması kurulum biçimindedir.




Uygulamayı kurmadan önce sözleşmenin kabul edilmesi gerekir.
124   Bölüm 8



           Examples seçeneği işaretlenirse JSP ve Servlet bileşenleriyle ilgili örnek uygulamalar yerel ağ
           üzerinde çalıştırılabilir.




           Kurulum için standart dizinden farklı bir dizin de seçilebilir. Uygulamalarda kullanılan Tomcat,
           standart dizine kurulmuştur.




           Kurulumun bu aşamasında Tomcat sunucusunun çalışacağı port numarasının belirlenir ve admin
           kullanıcısı için şifre oluşturulur. Bilgisayarınızın 8080 numaralı portunu kullanan başka bir uygu-
           lama yoksa Tomcat sunucusunun 8080 portunu kullanmasını sağlayabilirsiniz. Uygulamalarda
           kullanılan Tomcat sunucusu 8080 portu üzerinde çalışmaktadır. Admin kullanıcısının şifresinin
           boş bırakılması genel olarak tavsiye edilmez. Özellikle üzerinde aktif bir biçimde kullanılan uy-
           gulamalar çalışan bir sunucunun admin şifresinin boş olması uygulamalarda ve sistemde ciddi
           güvenlik açıklarına neden olur.
                                                                                                    JSP   125




Tomcat sunucusu çalışmak Java platformunun 5.0 sürümüne ihtiyaç duyduğundan JRE 5.0 uy-
gulamasının yeri belirtilmelidir. Java motoru standart olarak kurulmuşsa bu dizin otomatik olarak
belirlenir, aksi takdirde bilgisayar üzerindeki yerinin manuel olarak belirtilmesi gerekir.




Tomcat sunucusunun kurulumu tamamlandı. “Run Apache Tomcat” seçeneği işaretli olarak bıra-
kırsa Tomcat sunucusuna ait Windows servisi çalışır.
126   Bölüm 8



           Tomcat kurulumu başarılı olduysa ve ilişkili Windows servisi çalıştırıldıysa bilgisayarın sağ alt
           köşesinde Tomcat’e ait ikon belirir. Tomcat Windows servisi ile ilgili ayarlar bu ikona çift tık-
           landıktan sonra çıkan pencerede yapılabilir. Tomcat Windows servisi varsayılan olarak manuel
           çalıştırılacak şekilde ayarlanır. İşletim sisteminin her açılışında Tomcat servisinin otomatik olarak
           başlaması için servisin Şekil 8’deki gibi ayarlanması gerekir.

           Tomcat servisinin bilgisayarın her açılışında otomatik olarak çalışması için “Startup Type” seçe-
           neği “Automatic” olarak değiştirilir.




           Tomcat sunucusunun kurulumu sırasında farklı bir dizin belirtmediyseniz C:\Program Files\Apa-
           che Software Foundation\Tomcat 6.0 dizinine kurulacaktır. Bu dizinin altındaki webapps dizininin
           altında bulunan ROOT dizini JSP uygulamalarının barındırıldığı standart dizindir. Tomcat konfigü-
           rasyonunu değiştirmek için Tomcat ana dizininin altındaki conf dizininde bulunan konfigürasyon
           dosyaları kullanılabilir.

           Webapps dizininin altında bulunan ROOT dizininin içinde yeni bir dizin oluşturalım ve adını Il-
           kOrnek olarak değiştirelim. Tomcat sunucumuza http://localhost:8080 adresinden, IlkOrnek adı-
           nı verdiğimiz web uygulamamıza ise http://localhost:8080/IlkOrnek adresi üzerinden ulaşabiliriz.
           Uygulamamız henüz bir JSP sayfasına sahip olmadığı için web tarayacısı üzerinden bu adrese
           ulaşmaya çalışırsak hata mesajı alırız.

           Notepad veya benzer bir metin editörü kullanarak IlkOrnek dizininin içinde boş bir metin dosyası
           oluşturalım ve adını ilkornek.jsp olarak değiştirelim. Dosyanın uzantısının .jsp olması gerektiğini
           unutmamalıyız. Örnek Uygulama 8.1’deki kod bloğunu bu dosyanın içine yazarak dosyayı kay-
           dedelim.

           Örnek Uygulama 8.1:

                  	<%
                 1	
                  	out.println(“Ilk	Ornek”);
                 2	
                  	%>	
                 3	

           Tomcat kurulumu başarılı bir şekilde tamamlandıysa web tarayıcısının adres kısmına http://lo-
           calhost:8080/IlkOrnek/ilkornek.jsp yazıp enter tuşuna bastığımızda Şekil-9’daki gibi bir sayfanın
           açılması gerekir.
                                                                                                      JSP   127




             Şekil 9

Erişmeye çalıştığımız JSP sayfasının adının küçük-büyük harf duyarlı olduğuna dikkat edelim.
http://localhost:8080/IlkOrnek/ilkornek.jsp sayfası yerine http://localhost:8080/IlkOrnek/IlkOrnek.
jsp sayfasına ulaşmaya çalışırsak Şekil 10’daki gibi bir hata mesajı alırız.




             Şekil 10: Küçük-büyük harf duyarlılığından kaynaklanan sayfa bulunamadı hatası.

Oluşturduğumuz JSP sayfasının koduna bir göz atarsak <%ve%> etiketlerini görürüz. Bu etiket-
lerin arasına yazdığımız bütün kod blokları Java kodu olarak yorumlanır JSP script’leri yazmak
için kullanılır. İşletim sistemi üzerinde çalışan Java uygulamalarında kullanılan System.out.
println() komutu JSP ortamında out.println() şeklini alır ve istemciye (client) metin çık-
tısı vermek için kullanılır.

ROOT dizininin altında JspOrnekleri adında bir dizin oluşturalım ve bundan sonraki örnekleri bu
dizinin içine kaydedelim.

Java dilinde standart olarak bulunan komutlar JSP sayfaları oluşturulurken de kullanılır. Az önce
yazdığımız metni beş defa yazan bir programı for döngüsü kullanarak oluşturalım. Dongu.jsp
adında bir jsp sayfasını Notepad kullanarak JspOrnekleri dizinine kaydedelim. Dongu.jsp sayfa-
sını oluşturmak için kullanılan kod aşağıdaki gibidir.

Örnek Uygulama 8.2:

       <%
      1	
       	
      2	         for(int	i	=	0;	i	<	5;	i++)
       	
      3	         	          out.println(“Ilk	Ornek<br>”);
       %>
      4	

Kodu incelersek, JSP sayfalarında Java ve HTML kodlarının bir arada bulunaibildiğini görürüz.
out.println() komutunun sonunda kullandığımız <br> etiketi çıktının bir alt satıra geçmesini
128   Bölüm 8



           sağlar ve standart HTML etiketlerindendir. Döngü yapısının Java dilinin standart for döngüsü
           olduğunu görüyoruz.

           http://localhost:8080/JspOrnekleri/Dongu.jsp adresi üzerinden sayfayı çalıştırdığımızda Şekil
           11’deki gibi bir görünüm elde ederiz.




                         Şekil 11: Döngü kullanımı.


           JSP ortamı; ASP, PHP, ASP.Net, vb. teknolojileri gibi sunucu tarafında çalışır. Bunun anlamı,
           JSP kodunun sunucunun üzerinde çalışması ve istemci tarafında HTML kodunun gönderilmesi-
           dir. JSP sayfalarına http://Adres/SayfaAdi.jsp şeklinde ulaşılsa da istemci üzerinde çalışan web
           tarayıcısına saf HTML ve gerekirse Javascript kodu gelir. Web ortamında çalışan bütün sunucu
           tabanlı teknolojilerin web tarayıcıları tarafından yorumlanabilmesinin sebebi de budur. Dongu.
           jsp sayfasına sağ tıkladığımızda karşımıza çıkan menüden “view source” komutunu çalıştırırsak
           bahsedilen özellik daha iyi anlaşılır. İstemci tarafına gelen HTML kodu aşağıdaki gibidir.

           Ilk Ornek<br>

           Ilk Ornek<br>

           Ilk Ornek<br>

           Ilk Ornek<br>

           Ilk Ornek<br>

           Karşımıza çıkan HTML kodunda aynı ifade beş kere yazılmıştır ve ifadeler arasında bulunan <br>
           etiketinden dolayı çıktı beş satır halinde görünmektedir. Sunucu tarafında çalışan JSP sayfası
           üzerinde kullanılan döngü ve “<%”, “%>” etiketleri istemci tarafında görünmez.


           JSP Teknolojisinde Kullanılan Etiketler
           JSP Direktifleri
           JSP sayfalarının özelliklerini değiştirmek amacıyla kullanılan yapılardır ve başlarında “@” karak-
           teri bulunur. JSP direktifleri istemciye çıktı göndermez. En çok “Page” direktifi kullanılır. Page
           direktifi ile sayfanın script dili, durum yönetimi, buffer gibi özellikleri ile ilgili ayarlar yapılır, harici
           kütüphanelerin sayfa tarafından kullanılması sağlanır. Örneğin;
           <%@ page session=”true” import=”java.util.*” %> direktifi ile sayfada durum yö-
           netimi etkin hale getirilir ve java.util paketinin içisnde bulunan bileşenler sayfaya eklenerek bu
           pakette bulunan sınıfların sayfa tarafından kullanılması sağlanır. session=”true” yazmasak
           bile varsayılan olarak sayfanın session desteği açıktır, kapatmak için session=”false” yaz-
           mamız gerekir.
                                                                                                         JSP   129




JSP Script Etiketleri
Script etiketleri, JSP sayfalarında asıl işi yapan etiketlerdir. Sayfada bulunacak Java kodları script
etiketleri içine yazılır, sunucu bu etiketler içinde bulunan kodları Java kodu olarak algılar. JSP’de
üç çeşit script etiketi bulunur.

Tanımlama etiketleri: Java değişkenlerini tanımlamak için kullanılır ve <%! ...          %> şeklinde
oluşturulur.

Scriptlet etiketleri: Java ifadelerinden oluşan kod parçalarını çalıştırmak için kullanılır ve <% ...
%> şeklinde oluşturulur.

İfade etiketleri: Bütün Java ifadelerini çalıştırmak için kullanılır ve <%= ... %> şeklinde oluştu-
rulur.

Bu etiketlerin dışında, JSP sayfaları içinde yorum satırı oluşturmak için <%-- ... --% etiketi
kullanılır.


Form Verilerinin Kullanılması
JSP uygulamalarında sayfalar arasında veri taşımak için HTML standartlarının içinde bulunan
POST veya GET metodları kullanılabilir. Herhangi bir HTML veya JSP sayfasının içinde oluştu-
rulan form alanının içinde bulunan kontrollerin verileri GET veya POST işlemi sırasında üzerinde
çalışılan sayfaya veya farklı bir sayfaya gönderilir. Basit bir HTML sayfasından bir JSP sayfasına
POST metodu aracılığıyla verilerin gönderilmesi işlemi aşağıdaki gibi yapılabilir.

FormOrnegi.html sayfasını oluşturan HTML kodu aşağıdaki gibidir.

       <html>
      1	
       <body>
      2	
       	
      3	         <form	method=”post”	action=”FormData.jsp”>
       	
      4	         	       <table>
       	
      5	         	       <tr>
       	
      6	         	       	        <td>Ad:</td>	
       	
      7	         	       	        <td><input	type=”text”	name=”txtAd”	/>	</td>
       	
      8	         	       </tr>
       	
      9	         	       <tr>
      10	        	       	        	        <td>Soyad:</td>	
      11	    	           	        	        <td><input	type=”text”	name=”txtSoyad”	
      />	</td>
      12	        	       	        </tr>
      13	        	       	        <tr>
      14	    	     	     	     <td><input	type=”submit”	
      name=”btnGonder”	value=”Gonder”	/><td>
      15	        	       	        </tr>
      16	        	       	        </table>
      17	        	       </form>	
      18	        </body>
      19	        </html>

HTML sayfasında, <body> etiketinin içinde bir form oluşturduk ve POST metodunu kullanaca-
ğımızı belirttik. Formun içine eklenen “submit” butonunun tetiklenmesi sonrasında form verileri
130   Bölüm 8



           FormData.jsp sayfasına gönderilir. Bu işlem action=”FormData.jsp” satırıyla gerçeklenir. Kullanı-
           cının ad ve soyad değerlerini girmesi forma iki tane “text” tipinden input ekledik. Kontrollerin ara-
           yüz üzerinde düzgün bir şekilde görüntülenmesi için standart HTML yapılarından biri olan <table>
           etiketini kullandık. HTML sayfası aşağıdaki gibi görünür.




                       Şekil 12




           Kullanıcı tarafından veri girişi yapıldıktan sonra Gönder butonuna tıklandığında form verileri
           FormData.jsp sayfasına gönderilir. FormData.jsp adında bir JSP sayfası oluşturarak gönderilen
           verileri alıp işleyebiliriz.

                  <%@	page	import=”java.util.*”	%>
                 1	
                  <%
                 2	
                  	
                 3	               out.print(“Ad:”	+	request.getParameter(“txtAd”));
                 4		              out.print(“<br>Soyad:”	+	request.getParameter(“txtSoyad”))
                 ;
                  %>
                 5	

           Request.getParameter metodu, herhangi bir form üzerinden FormData.jsp sayfasına gönderilen
           verileri almak için kullanılır. txtAd ve txtSoyad anahtarları, FormOrnegi.html sayfasında bulunan
           text türünden veri giriş elemanlarının isim (name) değeridir. Gönder butonuna tıklandıktan sonra
           FormData.jsp sayfası yüklenir ve aşağıdaki gibi bir görünüm elde edilir.




                         Şekil 13

           HTML sayfasında verileri göndermek için POST yerine GET metodunu kullansak da FormData.
           jsp sayfasından verilere aynı şekilde ulaşabilir. Bu durumda veriler gizli olarak değil URL üzerin-
           den gönderilecektir. Önemli verilerin GET metodu ile gönderilmesi güvenlik açısından sakıncalı-
           dır. GET metodu kullanıldığında FormData.jsp sayfası aşağıdaki gibi görünür:

           Adres çubuğunda görünen URL değerine dikkat edersek bütün form verilerinin açık bir şekilde ve
           saf metin formatında aktarıldığını görebiliriz.
                                                                                                         JSP   131




Durum Yönetimi
HTTP protokolü durum özelliğine sahip değildir. Durum mekanizması, bir kullanıcı sisteme bağlı
kaldığı sürece verilerinin birden fazla sayfa arasında taşınabilmesine olanak verir. JSP de diğer
sunucu tabanlı web teknolojileri gibi kendine özel bir durum yönetimi mekanizmasına sahiptir.
JSP’de durum yönetimi session nesnesiyle sağlanır. Session nesnesine request.getSession()
metodu aracılığıyla ulaşılır. Basit bir sisteme giriş sayfasıyla kullanıcının bilgilerini session nes-
nesine kaydeden ve uygulama içindeki farklı bir sayfadan bu bilgilere ulaşan bir JSP uygulaması
yazalım:

       <%---------	KullaniciGirisi.jsp	---------%>
      1	
       <html>
      2	
       <body>
      3	
       <%
      4	
       	
      5	         out.print(“Session	ID:	“	+	session.getId());
       %>
      6	
       <form	method=”post”	action=”KullaniciGirisi.jsp”>
      7	
       	
      8	         <table>
       	
      9	         <tr>
      10	        	       	        <td>Ad:</td>	
      11	        	       	        <td><input	type=”text”	name=”txtAd”	/>	</td>
      12	        	       </tr>
      13	        	       <tr>
      14	        	       	        <td>Sifre:</td>	
      15	        	       	        <td><input	type=”password”	name=”txtSifre”	/>	
      </td>
      16	        	       </tr>
      17	        	       <tr>
      18	    	     	     <td><input	type=”submit”	name=”btnGonder”	
      value=”Gonder”	/><td>
      19	        	       </tr>
      20	        	       </table>
      21	        </form>	
      22	        <%
      23	        	       String	ad	=	request.getParameter(“txtAd”);
      24	        	       String	sifre	=	request.getParameter(“txtSifre”);
      25	        	       if(ad	!=	null	&&	sifre	!=	null)
      26	        	       {
132   Bölüm 8



                 27	    	     	                        if(ad.equals(“Yalcin”)	&&	sifre.
                 equals(“1234”))
                 28	          	            	           {
                 29	          	            	           	           session.putValue(“kullaniciAdi”,	ad);
                 30	          	            	           	           response.sendRedirect(“SifreDogru.jsp”);
                 31	          	            	           }
                 32	          	            	           else
                 33	          	            	           {
                 34	    	                  	           	           out.println(“Kullanici	adi	veya	sifre	
                 hatali”);
                 35	          	            	           }
                 36	          	            }
                 37	          %>
                 38	          </body>
                 39	          </html>

           Kullanıcının kullanıcı adı ve şifre bilgilerini girmesi için KullaniciGirisi.jsp adında bir JSP sayfası
           oluşturduk. Bir önceki örnekten farklı olarak kullanıcıdan gelecek bilgileri HTML sayfası yerine JSP
           sayfası üzerinden almayı tercih ettik. Bunun sebebi, kullanıcı giriş sayfasında da JSP kullanmayı
           planlamamız. Sayfanın başında kullandığımız <% out.print(“Session ID: “ + session.getId()); %>
           komutuyla o anda geçerli olan oturumun ID değerini kullanıcıya gösterdik. Form etiketinin action
           özelliğinin KullaniciGirisi.jsp sayfasını gösterdiğine dikkat edelim. Kullanıcı bilgilerini aldığımız
           sayfayla bu bilgilerin geçerliliğini kontrol ettiğimiz sayfa aynı. Form etiketinden sonra kullanıcının
           girdiği bilgilerin geçerliliğini kontrol etmek için request.getParameter() metodu ile form verilerini
           aldık. Kullanıcı adı ve şifre bilgilerini sayfanın içinde kontrol ettik; kullanıcı adı olarak “Yalcin”,
           şifre olark “1234” değerleri girilmişse sisteme giriş yapılabildiğini varsaydık. Gerçek bir uygula-
           mada kullanıcıdan girilen değerler bir veri kaynağı üzerinden doğrulanır. Eğer kullanıcı sisteme
           girmeyi başarabilirse kullanıcı adı değeri session nesnesine ekleniyor ve kullanıcı SifreDogru.
           jsp sayfasına yönlendiriliyor. Sisteme giriş işlemi başarısız olursa “Kullanıcı adı veya şifre hatalı”
           mesajı veriliyor ve yönlendirme yapılmıyor. KullaniciGirisi.jsp sayfası ilk açıldığında ve şifre yanlış
           girildiğinde aşağıdaki gibi görünür:




                       Şekil 15: KullaniciGirisi.jsp sayfası ilk defa yüklendi.

           Şifre yanlış girildi. Sayfanın yeniden yüklenmesi sırasında Session nesnesinin ID değerinin de-
           ğişmediği görülüyor.
                                                                                                      JSP   133




Kullanıcı adı ve şifre değerlerinin doğru girilmesi durumunda kullanıcının yönlendirileceği Sifre-
Dogru.jsp sayfasının kodu aşağıda verilmiştir:

      <%
      	 out.print(“Kullanici	adi:	“	+	session.getValue(“kullaniciAdi”));
      	 out.print(“<br>Session	ID:	“	+	session.getId());
      %>

Session nesnesine kaydedilmiş olan kullanıcı adı değeri alınıyor ve ekrana basılıyor. Session
değişkeninin ID değeri de aynı şekilde ekrana basılıyor.

Kullanıcı SifreDogru.jsp sayfasına yönlendirildiğinde aşağıdaki gibi bir sayfayla karşılaşır:

Kullanıcı adı ve şifre doğru girildi, session nesnesinde bulunan kullanıcı adı değeri ve session ID
değeri görüntülendi. Bu sayfadaki session ID değeriyle daha önceki sayfalardaki session ID de-
ğerinin aynı olduğunu görüyoruz. Session bilgileri bütün oturum boyunca ve uygulamanın bütün
sayfaları arasında geçerli olduğundan ID değeri de aynıdır.




JSP Uygulamalarında JDBC Kullanımı:

JSP uygulamalarının veritabanı sistemleriyle iletişim kurması için Java platformunun JDBC kütüp-
hanesi kullanılır. JDBC kütüphanesi kullanarak bir ürün ekleme sayfası oluşturalım.

       <%@	page	import=”java.util.*”	%>
      1	
       <%@	page	import=”java.sql.Connection”	%>
      2	
       <%@	page	import=”java.sql.DriverManager”	%>
      3	
       <%@	page	import=”java.sql.PreparedStatement”	%>
      4	
      5 <%@ page import=”java.sql.SQLException” %>
      6
       <html>
      7	
       <body>
      8	
134   Bölüm 8



                 	
                9	      <form	method=”post”	action=”UrunEkle.jsp”>
                10	     	    	      <table>
                11	     	    	      <tr>
                12	     	    	      	       <td>Urun	adi:</td>	
                13	    	     	      	       <td><input	type=”text”	name=”txtUrunAd”	
                />	</td>
                14	     	    	      </tr>
                15	     	    	      <tr>
                16	     	    	      	       <td>Fiyat:</td>	
                17	    	     	     	     <td><input	type=”text”	
                name=”txtUrunFiyat”	/>	</td>
                18	     	    	      </tr>
                19	     	    	      <tr>
                20	    	     	     	     <td><input	type=”submit”	
                name=”btnUrunKaydet”	value=”Kaydet”	/><td>
                21	     	    	      </tr>
                22	     	    	      </table>
                23	     	    </form>	
                24	     	    <%
                25	     	    	      String	urunAdi	=	request.getParameter(“txtUrun
                Ad”);
                26	    	     	      String	urunFiyat	=	request.getParameter(“txtUr
                unFiyat”);
                27	     	    	      if(urunAdi	!=	null	&&	urunFiyat	!=	null)
                28	     	    	      {
                29	     	    	      	       try
                30	     	    	      	       {
                31	    	     	      	       	     double	fiyat	=	Double.
                valueOf(urunFiyat);
                32	    	     	      	       	     Class.forName(“sun.jdbc.odbc.
                JdbcOdbcDriver”);
                33	    	     	     	     	     Connection	dbConnection	=	
                DriverManager.getConnection(“jdbc:odbc:AlisverisSitesi”);
                34	    	     	     	     	     PreparedStatement	statement	=	
                dbConnection.prepareStatement(“INSERT	INTO	Urun	(urunAdi,	fiyat)	
                VALUES (?, ?)”);
                35	     	    	      	       	     statement.setString(1,	urunAdi);
                36	     	    	      	       	     statement.setDouble(2,	fiyat);
                37	    	     	      	       	     int	rowCount	=	statement.
                executeUpdate();
                38	     	    	      	       	     statement.close();
                39	     	    	      	       	     if(rowCount	==	0)
                40	     	    	      	       	     {
                41	    	     	      	       	     	    System.out.println(“Ürün	
                kaydedilemedi”);
                42	     	    	      	       	     }
                                                                                                        JSP   135



      43	        	           	           	            }
      44	        	           	           	            catch(Exception	e)
      45	        	           	           	            {
      46	    	     	      	                           	           out.print(“Fiyat	alanina	sayi	
      degeri	girin<br>”);
      47	        	           	           	            }
      48	        	           	           }
      49	        	           %>
      50	        </body>
      51	        </html>

Ürün bilgilerini veritabanına kaydetmek için JDBC kütüphanesini kullandık. Veritabanı üzerin-
de çalıştırılacak olan sorgunun parametreleri kullanıcıdan alındığından PreparedStatement sınıfı
cinsinden bir nesne oluşturarak parametrelerini verdik. Ürün fiyatı alanının cinsi double olması
gerektiği için fiyat alanına girilen değeri double’a çevirmeye çalıştık. Uygulamanın akışına göre,
fiyat alanının değeri double’a çevrilebilirse sorgu çalıştırılıyor, çevrilemezse kullanıcıya hata me-
sajı veriliyor. Bir önceki örnekte olduğu gibi formun action değeri, yani post edildiğinde verilerini
göndereceği sayfa, yine formun kendisi.

UrunEkle.jsp sayfası çalıştırılmadan önce ve hatalı veri girildiğinde aşağıdaki gibi görünür.




            Şekil 18




            Şekil 19: Fiyat alanına double tipine çevrilemeyen veri girildi.


Veritabanını sorgulayarak sipariş bilgilerini getirmek için JSP sayfalarımızı oluşturalım. Öncelikle
veritabanı sunucumuzun arayüz programını açarak sipariş ve sipariş detayı bilgilerini ekleyelim.

      INSERT	INTO	Siparis	(musteriID,	siparisTarihi)	VALUES	(1,	
      ‘12/2/2007’)
      INSERT	INTO	Siparis	(musteriID,	siparisTarihi)	VALUES	(1,	
      ‘10/8/2007’)
136   Bölüm 8



                 INSERT	INTO	Siparis	(musteriID,	siparisTarihi)	VALUES	(2,	
                 ‘5/3/2007’)
                 INSERT	INTO	Siparis	(musteriID,	siparisTarihi)	VALUES	(3,	
                 ‘5/8/2007’)
                 INSERT	INTO	SiparisDetay	(siparisID,	urunID,	miktar)	VALUES	(1,	
                 1,	1)
                 INSERT	INTO	SiparisDetay	(siparisID,	urunID,	miktar)	VALUES	(1,	
                 3,	2)
                 INSERT	INTO	SiparisDetay	(siparisID,	urunID,	miktar)	VALUES	(2,	
                 7,	1)
                 INSERT	INTO	SiparisDetay	(siparisID,	urunID,	miktar)	VALUES	(3,	
                 5,	1)
                 INSERT	INTO	SiparisDetay	(siparisID,	urunID,	miktar)	VALUES	(3,	
                 8,	3)
                 INSERT	INTO	SiparisDetay	(siparisID,	urunID,	miktar)	VALUES	(4,	
                 3,	1)

           Verileri veritabanına ekledikten sonra JSP sayfalarımızı oluşturmaya başlayabiliriz. Öncelikle ve-
           rilen siparişleri görüntülemek için Siparis.jsp adında bir JSP sayfası oluşturalım.

                  <%@	page	import=”java.util.*”	%>
                 1	
                  <%@	page	import=”java.sql.Connection”	%>
                 2	
                  <%@	page	import=”java.sql.DriverManager”	%>
                 3	
                  <%@	page	import=”java.sql.ResultSet”	%>
                 4	
                  <%@	page	import=”java.sql.Statement”	%>
                 5	
                  <html>
                 6	
                  <body>
                 7	
                  <%
                 8	
                  	
                 9	        Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);
                 10	    	     Connection	dbConnection	=	DriverManager.
                 getConnection(“jdbc:odbc:AlisverisSitesi”);
                 11	    	     Statement	statement	=	dbConnection.
                 createStatement();
                 12           ResultSet resultSet = statement.executeQuery(“SELECT
                 siparisID,	siparisTarihi,	ad,	soyad	FROM	siparis	s	JOIN	Musteri	m	
                 ON	(s.musteriID	=	m.musteriID)”);
                 13	    	     out.println(“Detay	bilgilerini	ogrenmek	istediginiz	
                 siparisin	tarihine	tiklayin<br><br>”);
                 14	       %>	     	
                 15	       <table>
                 16	       <%
                 17	       	       while(resultSet.next())
                 18	       	       {
                 19	       %>
                 20	       	       	        <tr>
                 21	    	     	     	     <td	width=”100”><a	href=”SiparisDetay.
                 jsp?id=<%out.println(resultSet.getInt(“siparisID”));
                                                                                                         JSP   137



      22	         %>”>
      23	         <%
      24	    	     out.println(resultSet.getDate(“siparisTarihi”).
      toString());	25	   %>
      26	         	       </a></td>
      27	         	       	       	        <td	width=”60”>
      28	         <%	
      29	         	       out.println(resultSet.getString(“ad”));	28	
      30	         %>
      31	         	       </td>
      32	    	     	     <td	width=”60”><%	out.println(resultSet.
      getString(“soyad”));	33	 %>
      34	         </td>
      35	         	       	       </tr>
      36	         <%
      27	         	       }
      38	         %>
      39	         	       </table>
      40	         <%
      41	         statement.close();
      42	         %>
      43	         </body>
      44	         </html>

Kodun açıklaması: Veritabanı bağlantısı oluşturulduktan sonra sipariş bilgilerini çekmek amacıy-
la bir select sorgusu veritabanı üzerinde çalıştırılır ve geri dönen sonuç kümesi ResultSet nesnesi
aracılığıyla alınır. Verilerin düzgün bir biçimde görüntülenebilmesi için <table> yapısı kullanılmış-
tır. ResultSet nesnesinin her bir kaydı için tabloda bir satır oluşturulmuştur. Bir satır üç sütundan
oluşur: İlk sütün siparişin verildiği tarihi içerir ve SiparisDetay.jsp sayfasına bağlantı kurmak ama-
cıyla <a href> etiketinden oluşur. SiparisDetay.jsp sayfasına siparis numarası URL aracılığıyla ta-
şınacağından her bir kaydın siparisID değeri ile <a href> etiketinin URL alanı belirlenir. Bu alanın
değeri SiparisDetay.jsp?id=... şeklinde olup “...” ile ifade edilen yere sipariş numarası gelir. Sayfa
yüklendiği zaman aşağıdaki gibi görünür.




             Şekil 20
138   Bölüm 8



           Sipariş tarihi alanına tıklandığında açılacak olan SiparisDetay.jsp sayfasında seçilen siparişin
           detay bilgileri veritabanından çekildikten sonra görüntülenecektir. SiparisDetay.jsp sayfasını oluş-
           turan JSP kodu aşağıdaki gibidir.

                  <%@	page	import=”java.util.*”	%>
                 1	
                  <%@	page	import=”java.sql.Connection”	%>
                 2	
                  <%@	page	import=”java.sql.DriverManager”	%>
                 3	
                  <%@	page	import=”java.sql.ResultSet”	%>
                 4	
                  <%@	page	import=”java.sql.Statement”	%>
                 5	
                  <%@	page	import=”java.sql.PreparedStatement”	%>
                 6	
                  <html>
                 7	
                  <body>
                 8	
                  <%
                 9	
                 10	       	        if(request.getParameter(“id”)	==	null)
                 11	       	        	       response.sendRedirect(“Siparis.jsp”);
                 12	       	        Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);
                 13	    	     Connection	dbConnection	=	DriverManager.
                 getConnection(“jdbc:odbc:AlisverisSitesi”);
                 14	    	     PreparedStatement	statement	=	dbConnection.
                 prepareStatement(“SELECT	urunAdi,	fiyat,	miktar	FROM	SiparisDetay	
                 sd JOIN Urun u ON (sd.urunID = u.urunID) WHERE siparisID = ?”);
                 15	       	        statement.setString(1,	request.getParameter(“id”));
                 16                 ResultSet resultSet = statement.executeQuery();
                 17	       %>	      	
                 18	       <table>
                 19	       <%
                 20	       	        while(resultSet.next())
                 21	       	        {
                 22	       %>
                 23	       	        	       <tr>
                 24	       	        	       	        <td	width=”200”>
                 25	       <%
                 26	       	        out.println(resultSet.getString(“urunAdi”));
                 27	       %>
                 28	       	        </td>
                 29	       	        	       	        <td	width=”100”>
                 30	       <%
                 31	       	        out.println(resultSet.getDouble(“fiyat”));
                 32	       %>
                 33	       </td>
                 34	       	        	       	        <td	width=”100”>
                 35	       <%
                 36	       	        out.println(resultSet.getInt(“miktar”));
                 37	       %>
                 38	       </td>
                                                                                                           JSP   139



      39	         	       	        </tr>
      40	         <%
      41	         	       }
      42	         %>
      43	         	       </table>
      44	         <%
      45	         	       statement.close();
      46	         %>
      47	         </body>
      48	         </html>

Kodun açıklaması: Sayfanın ilk yüklenmesi sırasında URL aracılığıyla “id” değerinin gelip gel-
mediği kontrol edilir. Eğer “id” değeri yoksa kullanıcı Siparis.jsp sayfasına yönlendirilir. “id” değeri
varsa veritabanı bağlantısı kurulduktan sonra parametreli bir select ifadesi çalıştırmak üzere Pre-
paredStatement nesnesi oluşturulur ve sipariş numarası URL aracılığıyla gelen siparişin detay
bilgileri veritabanından çekilir. Geri dönen sonuç kümsi ResultSet nesnesi aracılığıyla bir HTML
tablosunda kullanıcıya gösterilir.

SiparisDetay.jsp sayfası açıldığında “id” alanının değeri boş değilse aşağıdaki gibi bir sayfa gö-
rüntülenir.




             Şekil 21
9   JAVA I/O
9 JAVA I/O
• Dosyalar ve Dizinler

• FilterInputStream Sınıfları

• FileInputStream ve FileOutputStream
  Sınıflarının Kullanımı

• Reader ve Writer Sınıfları:

• Standart Giriş-Çıkış Biriminin Kullanılması:

• Java ile Ağ Programlama
                                        JAVA I/O
.NET platformunda olduğu gibi Java platformunda da giriş-çıkış işlemleri Stream adı verilen veri
yapıları aracılığıyla yapılır. Veri gönderme ve alma kabiliyetine sahip bütün nesneler Stream ola-
rak tanımlanabilir. Stream yapısının kullanımıyla, giriş-çıkış birimlerinin içinde bulunan veri ya-
zılım ortamından soyutlanmış olur. Java ortamındaki Stream okuma amacıyla kullanılan sınıflar
InputStream sınıfından, Stream yazma amacıyla kullanılan sınıflar OutputStream sınıfından tü-
retilirler. InputStream türünden sınıflarda bulunan Read() metodu ile byte bazında okuma yapıla-
bilir. Benzer bir şekilde OutputStream türünden sınıflarda bulunan sınıfların sahip olduğu Write()
metodu ile byte bazında yazma işlemi yapılabilir. Stream yapılarını kullanmak için oluşturulmuş
olan InputStream ve OutputStream sınıfları temel olarak byte veri tipinden verilerle çalışsa da
Java ortamında bulunan farklı sınıflar kullanılarak char veri tipi ile de işlem yapılabilir. Aşağıdaki
veri kaynakları kullanılarak Stream üzerinden okuma veya yazma işlemi gerçekleştirilebilir:

    Byte dizileri
    Dosyalar
    String nesneleri
    Ağ (network) kaynakları
Stream yapısının detaylarına girmeden önce dosya sistemi üzerinde duralım.


Dosyalar ve Dizinler
Okuma ve yazma işlemleri için disk üzerinde bulunan dosyalara erişilmek istendiğinde File sı-
nıfından oluşturulan nesneler kullanılır. File kelimesi sadece dosya kavramını temsil ediyor gibi
görünse de dizin kavramını da içerir. Disk üzerinde bulunan dizinlere ve dosyalara erişmek için
File nesneleri kullanılır. File nesnesinin bir dosyayı temsil etmesi istendiğinde yapıcı metoduna
parametre olarak bu dosyanın yeri, adı ve uzantısı String formatında verilir. Benzer şekilde, File
nesnesinin yapıcı metoduna parametre olarak temsil edilecek dizinin yeri ve adı da verilebilir.

File nesnesi kullanılarak C:\Program Files\Java\jre1.6.0_02 dizininin içinde bulunan bütün dosya
ve dizinler aşağıdaki gibi görüntülenebilir:

        import	java.io.File;
       1	
        public	class	Giris	
       2	
        {
       3	
        	
       4	            public	static	void	main(String[]	args)	
        	
       5	            {
        	
       6	     	     File	kaynakDizin	=	new	File(“C:\\Program	Files\\
       Java\\jre1.6.0_02”);
        	
       7	            	    String[]	dosyalarVeDizinler	=	kaynakDizin.list();
        	
       8	            	    for	(String	dosyaVeyaDizin	:	dosyalarVeDizinler)	
        	
       9	            	    {
       10	           	    	       	        System.out.println(dosyaVeyaDizin);
       11	           	    	       }
       12	           	    }
       13	           }

Kodun açıklaması: File nesnesi oluşturularak C:\Program Files\Java\jre1.6.0_02 dizininin Java
programında temsil edilmesi sağlanır. File nesnesinin list() metodu, dizin içinde bulunan bütün
dosya ve dizinlerin adını bir String dizisi şeklinde döndürür.
144   Bölüm 9



           Uygulama çalıştırıldığında aşağıdaki gibi bir çıktı alınır:

                 bin
                 COPYRIGHT
                 lib
                 LICENSE
                 PATCH.ERR
                 README.txt
                 THIRDPARTYLICENSEREADME.txt
                 Welcome.html

           Bilgisayarınızda bu dizin bulunmuyorsa File sınıfının yapıcı metoduna başka bir dizin adını pa-
           rametre olarak verebilirsiniz. C:\Program Files\Java\jre1.6.0_02 dizininin altında bulunan bütün
           dosya ve klasörlerin görüntülendiğine ve verilen dizin altında bulunan dizinlerin içindeki dosya ve
           klasörlerin listelenmediğine dikkat edelim. Sadece dosyaların görüntülenmesi için aşağıdaki kod
           bloğu kullanılabilir:

                  import	java.io.File;
                 1	
                  public	class	Giris	
                 2	
                  {
                 3	
                  	
                 4	         public	static	void	main(String[]	args)	
                  	
                 5	         {
                  	
                 6	     	     File	kaynakDizin	=	new	File(“C:\\Program	Files\\
                 Java\\jre1.6.0_02”);
                  	
                 7	         	        File[]	dosyalarVeDizinler	=	kaynakDizin.listFiles();
                  	
                 8	         	        for	(File	dosyaVeyaDizin	:	dosyalarVeDizinler)	
                  	
                 9	         	        {
                 10	        	        	        	       if(dosyaVeyaDizin.isFile())
                 11	        	        	        	       {
                 12	    	            	        	       	        System.out.println(dosyaVeyaDizin.
                 getName());
                 13	        	        	        	       }
                 14	        	        	        }
                 15	        	        }
                 16	        }

           Kodun açıklaması: Bir önceki örnekten farklı olarak File nesnesinin listFiles() metodunu kul-
           landık. Bu metod String dizisi yerine File dizisi döndürür. Böylece verilen dizinin altında bulunan
           bütün dosya ve dizinler birer tane File nesnesiyle temsil edilmiş olur. Döngü içinde bulunan File
           nesnesinin isFile() metodu ile temsil edilen yapının dosya olup olmadığını kontrol ediyoruz, eğer
           dosyaysa dosyanın adını ekrana basıyoruz. Sadece dizinleri görüntülemek isteseydik File nes-
           nesinin isDirectory() metodunu kullanabilirdik. Uygulama çalıştırıldığında aşağıdaki gibi bir çıktı
           alınır:

                 COPYRIGHT
                 LICENSE
                 PATCH.ERR
                 README.txt
                                                                                                  JAVA I/O   145



      THIRDPARTYLICENSEREADME.txt
      Welcome.html
InputStream

Çeşitli veri kaynaklarından veri okumak amacıyla aşağıdaki sınıflardan oluşturulan nesneler kul-
lanılabilir. Bu sınıflar InputStream sınıfından türetilmiştir.

ByteArrayInputStream: Bellek üzerinde bulunan tampon bölgelerden veri alınması amacıyla
kullanılır.

StringBufferInputStream: Bir String nesnesinin InputStream nesnesi olarak kullanılmasını sağ-
lar.

FileInputStream: Disk üzerinde bulunan dosyaların okunması için kullanılır.

SequenceInputStream: Birden fazla InputStream nesnesinin tek bir InputStream nesnesine dö-
nüştürülmesini sağlar.

PipedInputStream: PipedOutputStream nesnesine yazılan verileri biçimlendirmek için kullanılır.

OutputStream

Çeşitli veri kaynaklarına veri yazmak amacıyla aşağıdaki sınıflardan oluşturulan nesneler kullanı-
labilir. Bu sınıflar OutputStream sınıfından türetilmiştir.

ByteArrayOutputStream: Bellek üzerinde buffer bölgesi oluşturulması amacıyla kullanılır. Byte-
ArrayOutputStream üzerine yazılan bütün verilen bellekte bulunan tampon bölgeye yazılır.

FileOutputStream: Disk üzerinde bulunan dosyalara veri yazılması için kullanılır.

PipedOutputStream: PipedInputStream nesnesine gönderilecek verileri hazırlamak için kullanı-
lır.

Bahsedilen Stream sınıflarından başka, InputStream türevi sınıflardan oluşan nesneler aracılı-
ğıyla yapılan okuma işleminin veya OutputStream türevi sınıflardan oluşan nesneler aracılığıyla
yapılan yazma işleminin özelliklerinin belirlenmesi amacıyla FilterInputStream ve FilterOutputS-
tream sınıfları kullanılır. Byte veri tipinden farklı veri tipleri ile okuma veya yazma yapma, okuna-
cak veya yazılacak verilerin bir tampon bölgede tutulması veya tutulmaması gibi özellikler Filter
sınıfları aracılığıyla sağlanır. FilterInputStream ve FilterOutputStream sınıfları soyut olarak oluş-
turulmuştur, bu sınıflardan türetilen ve yerleşik olarak Java ortamında bulunan sınıflar yardımıyla
Stream nesnelerine çeşitli özellikler kazandırılabilir.

FilterInputStream Sınıfları
Giriş kaynaklarını biçimlendirmek amacıyla kullanılan sınıfların bir kısmı şunlardır:

DataInputStream: Farklı veri tiplerinde verilerin okunması amacıyla kullanılır.

BufferedInputStream: Her okumada fiziksel kaynağa erişilmesini engeller, okunan verilerin bel-
lekte bulunan bir tampon bölgeye aktarılmasını sağlar.

LineNumberInputStream: Giriş kaynağına gelen satır sayısını saklar. Bu sınıfın kullanılması
tavsiye edilmez, satır sayısını elde etmek amacıyla kullanılan LineNumberReader sınıfı ileride
açıklanacaktır.

Bu sınıfların yapıcı metodları parametre olarak InputStream sınıfından türemiş bir sınıftan oluşan
bir nesne alır.
146   Bölüm 9



           FilterOutputStream Sınıfları

           Çıkış kaynaklarını biçimlendirmek amacıyla kullanılan sınıfların bir kısmı şunlardır:

           DataOutputStream: Farklı veri tiplerinde verilerin yazılması amacıyla kullanılır.

           BufferedOutputStream: Her yazma işleminde fiziksel kaynağa erişilmesini engeller, yazılacak
           verilerin bellekte bulunan bir tampon bölgeye aktarılmasını sağlar.

           PrintOutputStream: Çıkış kaynağına gönderilen verilerin görsel olarak biçimlendirilmesini sağ-
           lar.

           Bu sınıfların yapıcı metodları parametre olarak OutputStream sınıfından türemiş bir sınıftan olu-
           şan bir nesne alır.

           FileInputStream ve FileOutputStream Sınıflarının Kullanımı
           Disk üzerinde bulunan bir dosyanın okunarak içeriğinin disk üzerindeki başka bir dosyaya yazıl-
           masını aşağıdaki kod ile gerçekleştirebiliriz.

                  import	java.io.FileInputStream;
                 1	
                  import	java.io.FileOutputStream;
                 2	
                  import	java.io.IOException;
                 3	
                  public	class	DosyaIslemleri	
                 4	
                  {
                 5	
                  	
                 6	        public	static	void	main(String[]	args)	throws	IOException
                  	
                 7	        {
                  	
                 8	     	      FileInputStream	okuma	=	new	FileInputStream(“c:\\
                 okunan.txt”);
                  	
                 9	     	     FileOutputStream	yazma	=	new	FileOutputStream(“c:\\
                 yazilan.txt”);
                 10	       	        	       int	okunanKarakter;
                 11	       	        	       while((okunanKarakter	=	okuma.read())	!=	-1)
                 12	       	        	       {
                 13	       	        	       	        System.out.print((char)okunanKarakter);
                 14	       	        	       	        yazma.write(okunanKarakter);
                 15	       	        	       }
                 16	       	        	       okuma.close();
                 17	       	        	       yazma.close();
                 18	       	        }
                 19	       }

           Kodun açıklaması: C sürücüsünde oluşturduğumuz okunan.txt dosyasını okuyarak içeriğini C
           sürücüsündeki “yazilan.txt” dosyasında kopyalamak istiyoruz. okunan.txt dosyasını aşağıdaki gibi
           oluşturabilirsiniz:

                 Java	ile	dosyadan	okuma
                 islemi yaptık

           Dosyadaki verileri okumak için FileInputStream nesnesi, dosyaya yazmak için FileOutputStre-
           am nesnesi oluşturduk. FileInputStream nesnemizin read() metodu döngünün her dönüşünde bir
           byte değerini tam sayı olarak okur, ekranda görüntüler ve yazmak için açtığımız dosyaya yazar.
                                                                                                    JAVA I/O   147



yazilan.txt isimli dosya disk üzerinde bulunmuyorsa FileOutputStream nesnesi tarafından oluştu-
rulur, bulunuyorsa içi boşaltılır.

Uygulama çalıştırıldığında ekranda aşağıdaki gibi bir görüntü oluşur. Türkçe karakterlerin düzgün
görünmemesinin sebebi, okunan değerlerin unicode desteğine sahip olmamasıdır.

      Java	ile	dosyadan	okuma
      i?lemi yapt?k

“yazilan.txt” dosyasının içeriği ise aşağıdaki gibi olur. Türkçe karakterlerin “yazilan.txt” dosyasına
düzgün bir şekilde aktarılmıştır.

      Java	ile	dosyadan	okuma
      işlemi yaptık


Dosyadan okunan karakteri ekrana basmak için tip dönüşümü işlemini kullanarak okunan tam
sayı cinsinden verileri karakter tipine çevirdik. Tip dönüşümü yapmasaydık veriler ekrana tam
sayı olarak basılırdı. Aşağıdaki veriler, dosyadan okunan karakterlerin tam sayı cinsinden kar-
şılığıdır. Println() metodunu kullanırken araya boşluk bırakmadığımız için bütün sayılar aralıksız
gösterildi. Bunun sebebi, boşluk karakterinin de tam sayı cinsinden bir karşılığa sahip olmasıdır.

      74971189732105108101321001111151219710097110321111071171099713101
      052541081011091053212197112116253107

Okuma veya yazma işlemini tek bir tamsayı ile sınırlandırmak yerine byte blokları şeklinde de
yapabiliriz. Bunun için bir tane byte dizisi tanımlanarak read() ve write() metodlarına parametre
olarak verilir. Okunan veriler byte dizisine yazılır, yazma işlemi yapılacaksa byte dizisi kullanılarak
yapılır. Örnek kod aşağıda verilmiştir.

       import	java.io.FileInputStream;
      1	
       import	java.io.FileOutputStream;
      2	
       import	java.io.IOException;
      3	
       public	class	DosyaIslemleri	
      4	
       {
      5	
       	
      6	         public	static	void	main(String[]	args)	throws	IOException
       	
      7	         {
       	
      8	     	      FileInputStream	okuma	=	new	FileInputStream(“c:\\
      okunan.txt”);
       	
      9	     	     FileOutputStream	yazma	=	new	FileOutputStream(“c:\\
      yazilan.txt”);
      10	        	        	       byte[]	veri	=	new	byte[1000];
      11	        	        	       int	dosyaBoyutu	=	okuma.read(veri);
      12	        	        	       yazma.write(veri);
      13	        	        	       okuma.close();
      14	        	        	       yazma.close();
      15	        	        }
      16	        }
148   Bölüm 9




           FileInputStream ve FileOutputStream Sınıflarının File Sınıfıyla Birlikte Kullanımı:
           Duruma göre FileInputStream ve FileOutputStream nesnelerinin yapıcı metodlarına parametre
           olarak dosya adı yerin File nesneleri de verebiliriz. Uygulamanın kodunun aşağıdaki gibi olması
           durumunda da ekran çıktısı ve yeni oluşan dosyanın içeriği değişmeyecektir:

                  import	java.io.File;
                 1	
                  import	java.io.FileInputStream;
                 2	
                  import	java.io.FileOutputStream;
                 3	
                  import	java.io.IOException;
                 4	
                  public	class	DosyaIslemleri	
                 5	
                  {
                 6	
                  	
                 7	         public	static	void	main(String[]	args)	throws	IOException
                  	
                 8	         {
                  	
                 9	         	       File	okunanDosya	=	new	File(“c:\\okunan.txt”);
                 10	    	           	        File	yazilanDosya	=	new	File(“c:\\yazilan.
                 txt”);
                 11	    	           	        FileInputStream	okuma	=	new	FileInputStream(ok
                 unanDosya);
                 12	    	     	              FileOutputStream	yazma	=	new	FileOutputStream(
                 yazilanDosya);
                 13	        	       	        int	okunanKarakter;
                 14	        	       	        while((okunanKarakter	=	okuma.read())	!=	-1)
                 15	        	       	        {
                 16	        	       	        	        System.out.print((char)okunanKarakter);
                 17	        	       	        	        yazma.write(okunanKarakter);
                 18	        	       	        }
                 19	        	       	        okuma.close();
                 20	        	       	        yazma.close();
                 21	        	       }
                 22	        }

           DataInputStream ve DataOutputStream Sınıflarının Kullanımı:
           DataInputStream ve DataOutputStream sınıflarından oluşturulan nesneler kullanılarak çeşitli veri
           tipleri ile okuma ve yazma işlemi yapılabilir. Bu sınıflardan oluşan nesneler ile UTF formatında
           veri okunabilir ve yazılabilir. UTF formatında veri yazma kabiliyeti, farklı platformlar arasında veri
           aktarımı yapılacağında kullanılır.

           Aşağıdaki örnekte, bir DataInputStream ile readChar() metodunu kullanarak karakter bazında
           okuma yaptıktan sonra DataOutputStream nesnesini kullanarak bu karakterleri dosyaya yazdı-
           racağız.


                  import	java.io.DataInputStream;
                 1	
                  import	java.io.DataOutputStream;
                 2	
                  import	java.io.FileInputStream;
                 3	
                  import	java.io.FileNotFoundException;
                 4	
                  import	java.io.FileOutputStream;
                 5	
                  import	java.io.IOException;
                 6	
                                                                                               JAVA I/O   149



       public	class	DosyaIslemleri	
      7	
       {
      8	
       	
      9	     public	static	void	main(String[]	args)	throws	
      FileNotFoundException,	IOException
      10	       	       {
      11	    	     	     FileInputStream	okuma	=	new	
      FileInputStream(“c:\\okunan.txt”);
      12	    	     	     FileOutputStream	yazma	=	new	
      FileOutputStream(“c:\\yazilan.txt”);
      13	    	     	     DataInputStream	ozellesmisOkuma	=	new	
      DataInputStream(okuma);
      14	    	     	     DataOutputStream	ozellesmisYazma	=	new	
      DataOutputStream(yazma);
      15	       	       	        while(ozellesmisOkuma.available()	!=	0)
      16	       	       	        {
      17	    	          	        	       char	okunanKarakter	=	ozellesmisOkuma.
      readChar();
      18	       	       	        	       ozellesmisYazma.writeChar(okunanKarakter
      );
      19	       	       	        }
      20	       	       	        ozellesmisOkuma.close();
      21	       	       	        ozellesmisYazma.close();
      22	       	       	        okuma.close();
      23	       	       	        yazma.close();
      24	       	       }
      25	       }

Kodun açıklaması: Bir önceki örnekte yaptığımız gibi FileInputStream ve FileOutputStream
nesnelerini oluşturduk. Farklı veri tipleri kullanarak okuma yapmak için DataInputStream sınıfını,
farklı veri tipleri kullanarak yazma yapmak için DataOutputStream sınıfını kullanacağımızı söy-
lemiştik. DataInputStream sınıfının yapıcı metodu parametre olarak bir FileInputStream nesnesi,
DataOutputStream sınıfının yapıcı metodu parametre olarak bir FileOutputStream nesnesi alır.
Dosyanın sonuna gelinip gelinmediğini, DataInputStream nesnesinin available() metodu ile an-
layabiliriz. Bu metod, DataInputStream nesnesinin bulunduğu yerden dosyanın sonuna kadar
okunabilecek byte sayısını döndürür. Bu metodun döndürdüğü değer sıfır olduğunda dosyanın
sonuna gelinmiş demektir. Uygulamayı çalıştırdığımızda, “yazilan.txt” dosyasının içeriğinin aşa-
ğıdaki gibi olduğunu görürüz.

Uygulamayı çalıştırdığımızda, “yazilan.txt” dosyasının içeriğinin aşağıdaki gibi olduğunu görü-
rüz.

      Java	ile	dosyadan	okuma
      işlemi yaptık

DataInputStream sınıfında bulunan readChar() metodu ile iki byte uzunluğunda okuma yapılır.
Aynı şekilde DataOutputStream sınıfında bulunan writeChar() metodu ile iki byte uzunluğunda
yazma gerçekleştirlir. Bu durumda dolayı; DataInputStream sınıfından oluşan bir nesne üzerin-
den okunan verileri FileOutputStream sınıfından oluşturulan bir nesne ile başka bir dosyaya ya-
zarsak veri kaybıyla karşılaşırız.

Az önce yazdığımız örneği aşağıdaki gibi değiştirelim:
150   Bölüm 9



                  import	java.io.DataInputStream;
                 1	
                  import	java.io.FileInputStream;
                 2	
                  import	java.io.FileNotFoundException;
                 3	
                  import	java.io.FileOutputStream;
                 4	
                  import	java.io.IOException;
                 5	
                  public	class	DosyaIslemleri	
                 6	
                  {
                 7	
                  	
                 8	     public	static	void	main(String[]	args)	throws	
                 FileNotFoundException,	IOException
                  	
                 9	         {
                 10	    	     	     FileInputStream	okuma	=	new	
                 FileInputStream(“c:\\okunan.txt”);
                 11	    	     	     FileOutputStream	yazma	=	new	
                 FileOutputStream(“c:\\yazilan.txt”);
                 12	    	     	     DataInputStream	ozellesmisOkuma	=	new	
                 DataInputStream(okuma);
                 13	        	        	        while(ozellesmisOkuma.available()	!=	0)
                 14	        	        	        {
                 15	    	            	        	        char	okunanKarakter	=	ozellesmisOkuma.
                 readChar();
                 16	        	        	        	        yazma.write(okunanKarakter);
                 17	        	        	        }
                 18	        	        	        ozellesmisOkuma.close();
                 19	        	        	        okuma.close();
                 20	        	        	        yazma.close();
                 21	        	        }
                 22	        }

           Okuma işlemini DataInputStream nesnesi ile, yazma işlemini FileOutputStream nesnesi ile yap-
           tık. Uygulamayı çalıştırdığımızda oluşan “yazilan.txt” dosyasının içeriği aşağıdaki gibidir.

                 aaiedsaa	km
                 ilm	atk

           Dikkat edersek, “okunan.txt” dosyasında bulunan verilen birer karakter atlanarak “yazilan.txt”
           dosyasına yazılmış olduğunu görürüz.

           Reader ve Writer Sınıfları:
           Java 1.1 sürümünden itibaren platforma Stream’ler üzerinde okuma ve yazma işlemlerini daha
           işlevsel hale getirmek için Reader ve Writer sınıfları eklenmiştir. Bu sınıflar byte veri tipi yerine
           unicode karakter tipini kullanırlar. Karakter tipinden verilerin kullanılması yazılımcının işini birçok
           durumda kolaylaştırdığı gibi desteklenen karakter formatının unicode olması yazılımın farklı dilleri
           desteklemesini de sağlar. InputStream ve OutputStream sınıfları aracılığıyla okunan ve yazılan
           veriler 8 bitlik byte tipi verilerden oluştuğu halde, Reader ve Writer sınıfları 16 bitlik veri desteği-
           ne sahiptir. Reader ve Writer sınıfları birçok durumda InputStream ve OutputStream sınıflarının
           yerine kullanılabilse de byte bazında işlemlerin yapılması gereken senaryolar da olabilir; bu gibi
           durumlarda InputStream ve OutputStream sınıflarının ve bu sınıfların türevlerinin kullanılması
           gerekir. Writer türevi sınıflarla Stream yapıları üzerinde append() işlemi yapılabilir.
                                                                                                   JAVA I/O   151



Stream sınıflarının Reader ve Writer karşılıkları aşağıdaki tabloda gösterilmiştir.

 Stream sınıfları                   Reader ve Writer sınıfları
 InputStream                        Reader
 OutputStream                       Writer
 ByteArrayInputStream               CharArrayReader
 ByteArrayOutputStream              CharArrayWriter
 FileInputStream                    FileReader
 FileOutputStream                   FileWriter
 PipedInputStream                   PipedReader
 PipedOutputStream                  PipedWriter
 StringBufferInputStream            StringReader

Verileri ve veri aktarma şekillerini biçimlendirmek amacıyla Stream sınıflarının biçimlendirilmesin-
de kullanılan Filter sınıflarına benzer sınıflar da vardır. Bu sınıflar aşağıdaki tabloda gösterilmiş-
tir.

 Stream sınıfları                   Reader ve Writer sınıfları
 FilterInputStream                  FilterReader
 FilterOutputStream                 FilterWriter
 BufferedInputStream                BufferedReader
 BufferedOutputStream               BufferedWriter
 DataInputStream                    -
 PrintStream                        PrintWriter
 LineNumberInputStream              LineNumberReader


FileReader ve FileWriter Sınıflarının Kullanılması:
FileReader ve FileWriter sınıflarının kullanımı, FileInputStream ve FileOutputStream sınıflarının
kullanımıyla benzerdir. Aşağıdaki örnekte FileReader nesnesi ile dosya içeriği okunmakta ve Fi-
leWriter nesnesi ile diğer dosyaya yazılmaktadır. Okuma işlemi için daha önce oluşturduğumuz
“okunan.txt” dosyası kullanılmıştır.

       import	java.io.FileNotFoundException;
      1	
       import	java.io.FileReader;
      2	
       import	java.io.FileWriter;
      3	
       import	java.io.IOException;
      4	
       public	class	DosyaIslemleri	
      5	
       {
      6	
       	
      7	     public	static	void	main(String[]	args)	throws	
      FileNotFoundException,	IOException
       	
      8	           {
       	
      9	           	       FileReader	okuma	=	new	FileReader(“c:\\okunan.txt”);
      10	    	     	              FileWriter	yazma	=	new	FileWriter(“c:\\
      yazilan.txt”);
      11	          	       	      int	okunanKarakter;
      12	          	       	      while((okunanKarakter	=	okuma.read())	!=	-1)
152   Bölüm 9



                 13	       	        	       {
                 14	       	        	       	       System.out.print((char)okunanKarakter);
                 15	       	        	       	       yazma.write(okunanKarakter);
                 16	       	        	       }
                 17	       	        	       okuma.close();
                 18	       	        	       yazma.close();
                 19	       	        }
                 20	       }

           Uygulama çalıştırıldığında aşağıdaki gibi bir çıktı alınır. FileInputStream sınıfının kullanımında
           Türkçe karakterler bozuk göründüğü halde FileReader sınıfı kullanıldığında Türkçe karakterler
           düzgün bir şekilde görünür. “yazilan.txt” dosyası da aynı verileri içerir.

                 Java	ile	dosyadan	okuma
                 işlemi yaptık

           FileInputStream sınıfından oluşan bir nesne ile bir dosyadaki verileri byte dizisi şeklinde okuya-
           biliyorduk. FileReader sınıfından oluşan bir nesne ile veriler karakter dizisi şeklinde okunabilir.
           Örnek kullanım aşağıdaki gibidir:

                  import	java.io.FileNotFoundException;
                 1	
                  import	java.io.FileReader;
                 2	
                  import	java.io.FileWriter;
                 3	
                  import	java.io.IOException;
                 4	
                  public	class	DosyaIslemleri	
                 5	
                  {
                 6	
                  	
                 7	     public	static	void	main(String[]	args)	throws	
                 FileNotFoundException,	IOException
                  	
                 8	        {
                  	
                 9	        	        FileReader	okuma	=	new	FileReader(“c:\\okunan.txt”);
                 10	    	     	             FileWriter	yazma	=	new	FileWriter(“c:\\
                 yazilan.txt”);
                 11	       	        	       char[]	veri	=	new	char[1000];
                 12	       	        	       okuma.read(veri);
                 13	       	        	       yazma.write(veri);
                 14	       	        	       okuma.close();
                 15	       	        	       yazma.close();
                 16	       	        }
                 17	       }

           Uygulama çalıştırıldığında, “yazilan.txt” dosyasının içeriğinin “okunan.txt” dosyasının içeriğiyle
           aynı olduğu görülür.

           BufferedReader Sınıfının Kullanımı:
           BufferedReader sınıfını kullanarak verileri satır bazında okuyabilir ve yazabiliriz. Örnek kullanım
           aşağıda verilmiştir.

                  import	java.io.BufferedReader;
                 1	
                  import	java.io.FileNotFoundException;
                 2	
                                                                                                JAVA I/O   153



       import	java.io.FileReader;
      3	
       import	java.io.FileWriter;
      4	
       import	java.io.IOException;
      5	
       public	class	DosyaIslemleri	
      6	
       {
      7	
       	
      8	     public	static	void	main(String[]	args)	throws	
      FileNotFoundException,	IOException
       	
      9	        {
      10	    	           	       FileReader	okuma	=	new	FileReader(“c:\\okunan.
      txt”);
      11	    	     	             FileWriter	yazma	=	new	FileWriter(“c:\\
      yazilan.txt”);
      12	    	     	     BufferedReader	tamponOkuma	=	new	
      BufferedReader(okuma);
      13	       	        	       String	satir	=	new	String();
      14	       	        	       String	butunVeri	=	new	String();
      15	       	        	       while((satir	=	tamponOkuma.readLine())	!=	
      null)
      16	       	        	       {
      17	       	        	       	       butunVeri	+=	satir	+	“\n”;
      18	       	        	       }
      19	       	        	       System.out.println(butunVeri);
      20	       	        	       yazma.write(butunVeri);
      21	       	        	       tamponOkuma.close();
      22	       	        	       okuma.close();
      23	       	        	       yazma.close();
      24	       	        }
      25	       }

Daha önceki örneklerden farklı olarak, dosyada bulunan veriler satır satır okunmuştur. Buffered-
Reader nesnesinin readLine() metodu kullanılarak okunan satırlar satir adındaki String değişke-
nine aktarılır, her satır butunVeri isimli String değişkenine eklenir. butunVeri değişkeni dosyadan
okunan bütün metni saklamak amacıyla kullanılmıştır. Uygulama çalıştırıldığında ekranda ve “ya-
zilan.txt” dosyasında aşağıdaki gibi bir görünüm oluşur.

      Java	ile	dosyadan	okuma
      işlemi yaptık

Okunan satır değerinin butunVeri değişkenine eklenmesi sırasında “\n” karakteri kullanılmasaydı
bütün satırlar ekran çıktısında yan yana görünür ve “yazilan.txt” dosyasına yan yana yazılırdı.
Bunun sebebi, readLine() metodunun satırı okuduktan sonraki “\n” değerini almamasıdır. “\n”
karakterinin kullanımaması durumunda dosyadaki veri aşağıdaki gibi olur:

      Java ile dosyadan okumaişlemi yaptık
154   Bölüm 9




           Standart Giriş-Çıkış Biriminin Kullanılması:
           Konsol üzerinden veri okuma ve veri yazma işlemlerinin yapılması için standart giriş-çıkış birimini
           oluşturan System.in, System.out ve System.err sınıfları kullanılır. Bu sınıflar, .Net platformundaki
           Console sınıfının karşılığıdır. Genelde konsole üzerinden yapılan readLine() işleminin tampon
           bellek bölgesi ile kullanımı uygundur.

           Konsoldan girilen verileri okuyan ve standart çıkışa yazan bir Java programı aşağıda verilmiştir.
           Kullanıcı boş satır girdiğinde uygulama sonlanır.

                  import	java.io.BufferedReader;
                 1	
                  import	java.io.IOException;
                 2	
                  import	java.io.InputStreamReader;
                 3	
                  public	class	Konsol	
                 4	
                  {
                 5	
                  	
                 6	        public	static	void	main(String[]	args)	throws	IOException
                  	
                 7	        {
                  	
                 8	     	     InputStreamReader	giris	=	new	
                 InputStreamReader(System.in);
                  	
                 9	        	        BufferedReader	tampon	=	new	BufferedReader(giris);
                 10	       	        	       String	satir;
                 11                 System.out.println(“Uygulamadan çıkmak için
                 enter tuşuna basın”);
                 12	       	        	       System.out.print(“Veri	girin:	“);
                 13	       	        	       satir	=	tampon.readLine();
                 14	       	        	       while(satir.length()	!=	0)
                 15	       	        	       {
                 16                                  System.out.println(“Girdiğiniz veri: “ +
                 satir);
                 17	       	        	       	        System.out.print(“Veri	girin:	“);
                 18	       	        	       	        satir	=	tampon.readLine();
                 19	       	        	       }		
                 20	       	        }
                 21	       }

           Uygulama çalıştırıldığında kullanıcıdan sürekli veri girmesini bekler, kullanıcı Enter tuşuna bas-
           tığında uygulama sonlanır. Veri girin metninin doğru yerde görüntülenmesini sağlamak için dön-
           güden önce readLine() metodu bir kere çalıştırılmıştır. Örnek girişlerle aşağıdaki gibi bir çıkış
           üretilir:

                 Uygulamadan çıkmak için enter tuşuna basın
                 Veri	girin:	Java	ile
                 Girdiğiniz veri: Java ile
                 Veri girin: Giriş-Çıkış
                 Girdiğiniz veri: Giriş-Çıkış
                 Veri girin: İşlemleri
                 Girdiğiniz veri: İşlemleri
                 Veri	girin:	
                                                                                               JAVA I/O   155




Java ile Ağ Programlama:
Ağ üzerinde bulunan farklı bilgisayarlar üzerinde çalışan programların haberleşmesi Socket yapı-
ları ile sağlanır. Socket’ler, uygulamaların haberleşmesini sağlayan iletişim noktalarıdır. Sunucu
tarafında tanımlanan ServerSocket nesnesi ile herhangi bir istemcinin sunucuya belirli bir port
üzerinden bağlanması beklenir, istemci bağlandığında sıradaki işlemler gerçekleştirilir. Sunucu
ile istemci arasındaki veri aktarımı Socket arabirimleri üzerinden, Stream yapıları kullanılarak
gerçekleştirilir. ServerSocket sınıfı adından dolayı özelleşmiş bir Socket yapısı gibi görünse de,
temel işlevi sunucunun istemciden gelen isteği beklemesini ve istek geldiğinde bu isteği kabul
etmesini sağlamaktır. İstemci sunucuya bağlandığı zaman ServerSocket nesnesi bir Socket nes-
nesi oluşturarak döndürür.

ServerSocket ve Socket nesneleri kullanılarak ağ üzerinden sunucu-istemci arasında veri akta-
rımı yapan Java dosyaları aşağıda verilmiştir. Sunucu ve istemci için birer tane Java sınıfı oluş-
turulmuştur.

      1 // Sunucu Uygulaması
       import	java.io.BufferedReader;
      2	
       import	java.io.BufferedWriter;
      3	
       import	java.io.IOException;
      4	
       import	java.io.InputStreamReader;
      5	
       import	java.io.OutputStreamWriter;
      6	
       import	java.net.ServerSocket;
      7	
       import	java.net.Socket;
      8	
       public	class	Sunucu	
      9	
      10	       {
      11	    	          public	static	void	main(String[]	args)	throws	
      IOException
      12	       	       {
      13	    	     	     ServerSocket	serverSocket	=	new	
      ServerSocket(60000);
      14                         System.out.println(“İstemcinin bağlanması
      bekleniyor”);
      15	       	       	        Socket	clientSocket	=	serverSocket.accept();
      16                         System.out.println(“İstemci ile bağlantı
      kuruldu”);
      17	    	     	     InputStreamReader	okuma	=	new	
      InputStreamReader(System.in);
      18	    	     	     BufferedReader	tamponOkuma	=	new	
      BufferedReader(okuma);
      19	    	     	     OutputStreamWriter	yazma	=	new	
      OutputStreamWriter(	clientSocket.getOutputStream());	
      20	    	     	     BufferedWriter	tamponYazma	=	new	
      BufferedWriter(yazma);
      21	       	       	        String	veri	=	new	String();
      22	       	       	        while((veri	=	tamponOkuma.readLine()).length()	
      !=	0)
      23	       	       	        {
      24	       	       	        	       tamponYazma.write(veri);
156   Bölüm 9



                 25	        	       	        	       tamponYazma.write(“\n”);
                 26	        	       	        	       tamponYazma.flush();
                 27	    	           	        	       System.out.println(“Gönderilen	veri:	“	+	
                 veri);
                 28	        	       	        }
                 29                          System.out.println(“Bağlantı kesildi”);
                 30	        	       	        serverSocket.close();
                 31	        	       	        clientSocket.close();
                 32	        	       	        okuma.close();
                 33	        	       	        yazma.close();
                 34	        	       	        tamponOkuma.close();
                 35	        	       	        tamponYazma.close();
                 36	        	       }
                 37	        }

           Kodun açıklaması: Sunucu üzerinde tanımlanan ServerSocket nesnesi, daha önce anlatıldığı
           gibi istemcinin bağlanmasını bekler ve bir istemci bağlanana kadar uygulamanın çalışmasını elin-
           de tutar. İstemci sunucuya bağlandıktan sonra ServerSocket nesnesinin accept() metodu Socket
           cinsinden bir nesne döndürür. Bu nesne ile sunucu istemciyle iletişim kurar. “okuma” isimli InputS-
           treamReader nesnesi, standart giriş-çıkış biriminden veri almak için kullanılır. Standart giriş-çıkış
           biriminden alınan verileri satır bazında okumak için BufferedReader nesnesi kullanılmıştır. Ben-
           zer şekilde Socket nesnesi üzerinden istemciye veri göndermek için OutputStreamWriter nesnesi
           oluşturulmuştur. OutputStreamWriter sınıfının yapıcı metoduna parametre olarak Socket nesne-
           sinin getOutputStream() metodundan dönen OutputStream nesnesi verilir. Verileri istemciye satır
           bazında göndermek için BufferedWriter nesnesi kullanılmıştır. Bir döngü içinde standart giriş-çıkış
           biriminden okunan veriler BufferedWriter nesnesi aracılığıyla istemciye gönderilir. BufferedWriter
           nesnesine veriyi yazdıktan sonra flush() komutu çalıştırılır. Bunun sebebi satır bazında gönderilen
           verinin hemen Stream’e yazılmasını sağlamaktır. Kullanıcı boş satır girdiğinde döngü sonlanır ve
           bağlantı sunucu tarafından kesilir.

                 1 // İstemci Uygulaması
                  import	java.io.BufferedReader;
                 2	
                  import	java.io.IOException;
                 3	
                  import	java.io.InputStreamReader;
                 4	
                  import	java.net.Socket;
                 5	
                  public	class	Istemci	
                 6	
                  {
                 7	
                  	
                 8	         public	static	void	main(String[]	args)	throws	IOException
                  	
                 9	         {
                 10	        	       	        Socket	socket;	
                 11	        	       	        try
                 12	        	       	        {
                 13	        	       	        	       socket	=	new	Socket(“127.0.0.1”,	60000);
                 14	        	       	        }
                 15	        	       	        catch(IOException	ex)
                 16	        	       	        {
                                                                                             JAVA I/O   157



      17                                System.out.println(“Bağlantı
      kurulamadı”);
      18	       	       	       	       return;
      19	       	       	       }
      20	    	     	     InputStreamReader	okuma	=	new	
      InputStreamReader(socket.getInputStream());
      21	    	     	     BufferedReader	tamponOkuma	=	new	
      BufferedReader(okuma);
      22                        System.out.println(“Sunucu ile bağlantı
      kuruldu”);
      23	       	       	       String	veri	=	new	String();
      24	       	       	       try
      25	       	       	       {
      26	       	       	       	       while((veri	=	tamponOkuma.readLine())	!=	
      null)
      27	       	       	       	       {
      28	    	          	       	       	       System.out.println(“Gelen	veri:	“	
      +	veri);
      29	       	       	       	       }
      30                                System.out.println(“Bağlantı kesildi”);
      31	       	       	       }
      32	       	       	       catch(IOException	ex)
      33	       	       	       {
      34                                System.out.println(“Bağlantı hatası”);
      35	       	       	       }
      36	       	       	       finally
      37	       	       	       {
      38	       	       	       	       okuma.close();
      39	       	       	       	       tamponOkuma.close();
      40	       	       	       	       socket.close();
      41	       	       	       }
      42	       	       }
      43	       }

Kodun açıklaması: İstemci tarafında, sunucu ile iletişim kurmak için bir Socket nesnesi tanımla-
nır. İstemci üzerinde çalışan uygulamada ServerSocket nesnesi kullanılmamıştır, bunun sebebi
istemcinin herhangi bir port üzerinden bağlantı beklememesidir. İstemci sadece sunucuya bağ-
lanmak ve veri almak için tasarlanmıştır. Verilen IP adresine belirtilen port üzerinden bağlantı
kurulamazsa IOException oluşur ve program sonlanır. Sunucu çalıştırılmadan istemci çalıştırı-
lırsa bahsedilen hata mesajı alınır. Sunucu uygulamadan Stream üzerinden gelen verileri almak
için InputStreamReader nesnesi, gelen verileri satır bazında işleyebilmek içinse BufferedReader
nesnesi kullanılmıştır. Sunucu üzerinde çalışan uygulamada olduğu gibi istemcide de InputS-
treamReader sınıfının yapıcı metoduna parametre olarak Socket nesnesinin getInputStream()
metodundan dönen InputStream nesnesi verilir. Sunucuyla bağlantı kurulduktan sonra bir sonsuz
döngü içinde sunucudan gelen mesajlar BufferedReader nesnesinin readLine() metodu ile satır
bazında alınır ve standart çıkışa yazılır. Bu noktadan sonra IOException oluşursa sunucunun
kapandığı anlaşılır ve “bağlantı kesildi” mesajı verilir.
158   Bölüm 9



           Her iki uygulamada da Stream ve Socket nesnelerini kapatmayı unutmamalıyız.

           Sunucu ve istemci uygulamalarının farklı şekillerde çalıştırılmaları aşağıdaki gibi çıktılar verir.

                 1. Sunucu çalıştırılmadan istemci çalıştırıldığında:

                 Bağlantı kurulamadı

                 2. Sunucu çalıştırıldıktan sonra istemcinin bağlanmasını beklerken:

                 İstemcinin bağlanması bekleniyor
                 3. İstemci ile sunucu arasında bağlantı kurulduğunda:

                 Sunucu tarafı:

                 İstemcinin bağlanması bekleniyor
                 İstemci ile bağlantı kuruldu

                 İstemci tarafı:

                 Sunucu ile bağlantı kuruldu

                 4. Sunucudan istemciye mesaj gönderildiğinde:

                 Sunucu tarafı:

                 İstemcinin bağlanması bekleniyor
                 İstemci ile bağlantı kuruldu
                 Java	ile
                 Gönderilen	veri:	Java	ile
                 Ağ Programlama
                 Gönderilen veri: Ağ Programlama
                 İstemci tarafı:
                 Sunucu ile bağlantı kuruldu
                 Gelen	veri:	Java	ile
                 Gelen veri: Ağ Programlama

                 5. Bağlantı kesildiğinde:

                 Sunucu tarafı:

                 İstemcinin bağlanması bekleniyor
                 İstemci ile bağlantı kuruldu
                 Java	ile
                 Gönderilen	veri:	Java	ile
                 Ağ Programlama
                 Gönderilen veri: Ağ Programlama
                 Bağlantı kesildi
                 İstemci tarafı:

                 Sunucu ile bağlantı kuruldu
                 Gelen	veri:	Java	ile
                 Gelen veri: Ağ Programlama
                 Bağlantı kesildi
10
     Oracle
     Veritabanı
     Ailesi
10 Oracle Veritabanı Ailesi
• Oracle Üzerinde Uygulama Geliştirme

• Oracle Veri Tabanı Sisteminin Kurulması

• Tablespace

• Undo Tablespace

• Oracle’da Veri Tabanı Oluşturmak

• Temel Veri Tipleri
                       Oracle Veritabanı Ailesi
Oracle Personal Edition: Microsoft SQL Server 2005’teki Express Edition gibi düşünülebilir.
Kişisel veritabanıdır. Uygulama geliştirme için kullanılır.

Oracle Standard Edition: Giriş seviyesinde çok kullanıcılı sürümdür. Microsoft SQL Server 2005
Standard Edition’a karşılık olarak düşünülebilir.

Oracle Enterprise Edition: En geniş kapsamlı sürümdür. Microsoft SQL Server 2005 Enterprise
Edition’a karşılık olarak düşünülebilir.

Oracle Lite: Mobil uygulamalar için kullanılır.


Oracle Üzerinde Uygulama Geliştirme
Oracle üzerinde uygulama geliştirme için kullanılacak çeşitli diller ve ortamlar mevcuttur. Bunlar
SQL, PL/SQL, Java olarak sayılabilir. Bunların dışında .NET, C, C++ gibi dil ve ortamlardan erişim
yapılabilir.

PL/SQL: Microsoft SQL Server’daki T-SQL’e karşılık olarak düşünülebilecek olan prosedürel SQL
genişletmesidir. Oracle üzerinde PL/SQL kullanılarak SP (stored procedure), trigger gibi nesneler
oluşturulabilir. T-SQL’deki gibi değişkenler, döngüler ve koşullar PL/SQL’de de mevcuttur. SQL
Plus arayüzü kullanılarak ya da TOAD ile PL/SQL yazılabilir.

Java: Microsot SQL Server üzerine .NET ile nesnelerin yazılmasına karşılık olarak, bunun için
Oracle tarafında Java kullanılır.

Oracle Veri Tabanı Sisteminin Kurulması
1� Öncelikle, eğer değilse, bilgisayarınızın bölgesel ayarlarını İngilizce olarak değiştirmeniz ge-
   rekir. Bunun için, Start > Control Panel > Regional and Language Options’ tan (Başlat >
   Denetim Masası > Bölge ve Dil Seçenekleri) English (United States) (İngilizce (A.B.D.)) olarak
   belirleyin.
162   Bölüm 10




           2. Daha sonra, Advanced (Gelişmiş) sekmesinde kullanılan dil seçeneği olarak yine English
              (United States) (İngilizce (A.B.D))‘yi seçin ve tamam butonuna tıklayın.




           3� Tamam butonuna tıkladığınızda, gerekli dosyaların bilgisayarınızda yüklü olduğunu ve
              Setup’ın (Kur) dosyaları buradan kurabileceğini belirten bir uyarı ile karşılaşabilirsiniz. Bu
              durumda, Yes (Evet) seçeneğini tıklayın. Ardından Windows bilgisayarınızı yeniden başlat-
              mak isteyebilir. Bu durumda yine Yes (Evet) seçeneğini tıklayarak bilgisayarınızı yeniden
              başlatın.
           4. Ardından Oracle10g kurulu dosyalarının bulunduğu klasöre giderek setup.exe’yi çalıştırın.
              Karşınıza ilk olarak daha önce yüklenmiş bir Oracle ürünü olup olmadığını kontrol eden bir
              işlem penceresi gelecektir.
                                                                                            Oracle Veritabanı   163




5. Kontol işleminin ardından gelen ekranda yükleme seçeneği olarak Basic Installation ve Ad-
   vanced Installation olmak üzere iki yöntem karşınıza çıkacaktır. Bunlardan Basic Installation
   seçeneğini seçin. Böylelikle birçok ayarın otomatik olarak yapılması sağlanacaktır.
Oracle Home Location: Veritabanının kurulacağı klasörün yerini belirtir.

Installation Type: Kurulum tipini belirtir. Standart ya da Enterprise Edition olarak belirlenir.

Create Starter Database: Bu seçenek işaretlendiğinde kurulum işlemi gerçekleştikten sonra
veritabanı da oluşturulur. Aksi halde sadece Oracle 10g kurulumu gerçekleştirilecek, veritabanı
yaratmak için SQL-Plus altından Create Database komutu ile veritabanı oluşturmak gerekecektir.
Bu seçeneğin işaretli olmasına dikkat edin.

Global Database Name: Veritabanının adı girilir.

Database Password: Veritabanı şifresi girilir. Bu bölümde girilen şifre kesinlikle unutulmamalıdır.
Oracle’da en üst seviyedeki admin kullanıcısı “sys” olarak hazır gelmekte ve burada belirlenen
şifre bu kullanıcının şifresi olarak belirlenmektedir.

Confirm Password: Girilen şifre tekrar teyit amacıyla bu bölüme girilir.

Girişleri tamamladıkan sonra Next butonuna tıklayın.




1� Karşınıza gelen pencerede, kurulum sırasında yaptığınız seçimleri özet olarak görebilirsiniz.
   Değişiklik yapmak isterseniz Back butonuna tıklayarak geri dönebilirsiniz. Daha sonra Install
   butonuna tıklayarak devam edin.
164   Bölüm 10




           2. Kurulum işlemi otomatik olarak başlayacaktır.




           3� Kurulum sırasında belirlenen ayarlar çerçevesinde konfigürasyon işlemleri otomatik olarak
              gerçekleştirildikten sonra işlemlerin özeti görüntülenir. Yine Next butonuna tıklayın.
                                                                                             Oracle Veritabanı   165




4. Veritabanı otomatik olarak oluşturulur.




5. Daha sonra, oluşturulan veritabanı ile ilgili bilgilerin özetlendiği ve şifre ayarlarının yapılabil-
   diği pencere gelir.
166   Bölüm 10



           6. Özet penceresinde yer alan Password Management butonuna tıklandığında açılan ekrandan,
              varsayılan kullanıcılara ilişkin şifre değişiklikleri ve kilitli/kilitsiz ayarları yapılabilir.




           7. Belirtilen ayarların yapılmasından sonra, kurulum tamamlanır. Exit butonuna tıklayarak çıkın.




           8. Açılan browserdan Oracle Enterprise Manager’a kullanıcı adı ve şifre ile giriş yapabilirsiniz.
                                                                                            Oracle Veritabanı   167




Tablespace
Microsoft SQL Server’da data file olarak geçen MDF ve NDF uzantılı dosyalar Oracle’da
tablespace’lerde tutulur.

system Tablespace
system tablespace’i Oracle’ın veri sözlüğünü barındırır. Bu da Microsoft SQL Server’daki master
veritabanındaki metadata tutan sys ile başlayan tablolar gibi düşünülebilir.

sysaux Tablespace
Eskiden system tablespace’te yer alan birtakım veriler ve özellikler 10g ile birlikte sysaux
tablespace’ine alınmıştır. Oracle sisteminin kullandığı bir tablespace olarak düşünülmelidir.

Default Temporary Tablespace
Default Temporary Tablespace ilgili veritabanında çalıştırılan sorgu için bellek alanı yetersiz ge-
liyorsa disk üzerinde bellek alanı gibi kullanılır. Windows ve Linux gibi işletim sistemlerinde kulla-
nılan swap alanı gibi düşünülebilir.

Undo Tablespace
Microsoft SQL Server’daki Transaction Log Space gibi düşünülebilir. Herhangi bir transaction
başladığında rollback ya da commit edilene kadar undo tablespace’te eski veri tutulur.

Arka Planda Çalışan Processler
Veritabanı sisteminin düzenli çalışabilmesi için arka planda çalışan birtakım process’lere ihtiyaç
vardır. Oracle’da çalışan temel arka plan process’leri şunlardır:

dbwr – Database Writer Process: Tampon bölgelere alınan verilerin veritabanına yazılmasın-
dan sorumludur.
lgwr – Log Writer Process: Online redo logları bellekte geçici olarak tutulur. Bu log’ların verita-
banına aktarılmasından log writer process sorumludur.
ckpt – Chekpoint Process: Checkpoint işlemi bellekteki verilerin veritabanı üzerinde uygun bö-
lümlere yazılmasından sorumludur. Checkpoint process database writer ve log writer’ı tetikleye-
bilir.
168   Bölüm 10



           smon – System Monitor Process: System monitor process veritabanlarının bütünlüğü ve tutar-
           lılığından sorumludur.

           pmon – Process Monitor: .NET ortamındaki garbage collector gibi düşünülebilir. Genel olarak
           kaynak yönetimi yaptığını söyleyebiliriz.

           Oracle’da Veri Tabanı Oluşturmak
           Oracle’da veri tabanı oluşturmak için kullanılabilecek en kolay yol Oracle DatabaseConfiguration
           Assistant (DBCA) kullanmaktır. DBCA’e Start > Programs > Oracle Oracle Home > Configuration
           and Migration Tools > Database Configuration Assistant yoluyla ulaşılır. Program açılınca bir
           sihirbaz aracılığıyla veri tabanını yapılandırabiliriz.




                  Şekil 1: DBCA açılış ekranı.

           Sihirbazın ilk adımı sadece bilgilendirici bir ekrandır. Bu adımda Next butonuna tıklayarak devam
           edebiliriz. Bu adımdan sonra veri tabanını oluşturmak için önümüze çıkan kavramları, opsiyonlar-
           la birlikte değerlendireceğiz.

           Sihirbazın ikinci adımında veri tabanı yönetiminde ne yapacağımızı belitmemiz gerekir. Burada ilk
           seçenek olan Create a Database (Veri tabanı oluştur) seçeneğini seçeceğiz. Diğer opsiyonlar ve
           açıklamaları da aşağıdaki gibidir; fakat sihirbazı bu seçeneklere göre ilerletmeyeceğiz.


            Opsiyon                              Açıklama
                                                 Sihirbazla adım adım veritabanı oluşturmak için kullanılır. Varolan veri
            Create a Database                    tabanı şablonları kullanılabildiği gibi şablonlardan farklılaştırarak da veri
                                                 tabanı oluşturulabilir.

                                                 Var olan bir veri tabanının dedicated (adanmış) bir sunucudan Shared
            Configure Database Options
                                                 (paylaşılan) bir sunucuya taşınması için gerekli işlerin yapılmasını sağlar.

            Delete a Database                    Var olan bir veri tabanının tamamen silinmesini sağlar.

                                                 Veritabanı şablonlarının yönetilmesini sağlar. Şablonlar yerel diskte XML
            Manage Templates                     formatında saklanmaktadır. Mevcut şablonlarda değişiklik yapılabilir ya da
                                                 yeni bir şablon oluşturulabilir.
                                                                                          Oracle Veritabanı   169




     Şekil 2: DBCA ilk kurulum ekranı.




       Şekil 3: DBCA veri tabanı şablonu seçme ekranı.

Şekil 3’deki veri tabanı şablonu seçim ekranında yeni oluşturulacak veri tabanının yapısı belir-
lenir. Herhangi bir şablonu seçerek sağ alt köşedeki Shoe Details butonuna tıklayarak şablo-
nun alt yapısı hakkında bilgi alabilirsiniz, ancak bu aşamada kavramlar karmaşık gelebilir. Her
şablon için genel veri tabanı özellikleri, başlangıç parametreleri, karakter setleri, veri dosyaları
(tablespace’ler), kontrol dosyaları ve redo log grupları hakkında bilgileri bu pop-up’tan görebilir-
siniz; ancak mevcut şablonların yapıları üzerinde değişiklik yapamazsınız. Burada hazır olarak
göreceğiniz şablonlar Data Warehouse, General Purpose ve Transaction Processing’tir. Burada
General Purpose seçeneğini seçip Next butonuna tıklayarak devam edebiliriz.
170   Bölüm 10




                  Şekil 4: DBCA veri tabanı isimlendirme ekranı.

           Sihirbazın 3. adımında Şekil 4’te gördüğümüz isimlendirme ekranı gelir. Bu ekranda veri tabanı
           adı ve SID (system identification)’si tanımlanır. Veri tabanı adı yazarken SID’de de aynı karak-
           terlerin yazıldığını göreceksiniz. Bir sistemde aynı isimde birden fazla veri tabanı olabilirken aynı
           SID’ye sahip birden fazla veri tabanı bulunamaz. Aynı zamanda SID’nin maksimum uzunluğu 8
           karakterdir. SID kısmına 8 karakterden daha uzun bir ifade yazsanız da SID 8 karaktere kısaltı-
           lacaktır. Bu ekranda veri tabanı adına ve SID’ye “ornek” yazıp Next butonuna tıklayarak devam
           edebiliriz.




                  Şekil 5: DBCA yönetim seçenekleri ekranı.
                                                                                                       Oracle Veritabanı   171



Şekil 5’teki yönetim seçenekleri ekranında veri tabanının Enterprise Manager (EM) ile kontrol
edilip edilemeyeceği seçeneği ile birlikte uyarıların e-mail ile gönderilmesi ve backup seçenek-
leri tanımlanır. Bu ekranda Configure the Database with Enterprise Manager seçeneğeni işaretli
olarak bırakalım. Eğer makinenizde grid kurulumu varsa ilk opsiyon olan Use Grid Control for
Database Management opsiyonu da açık olacaktır. Diğer opsiyon olan Use Database Control for
Database Management seçeneği mecburen seçili olarak kalarak devam edecektir. Enable Email
Notifications ve Enable Daily Backup seçeneklerini işaretlemeden devam edebiliriz.




       Şekil 6: DBCA şifre tanımlamaları ekranı.

Şekil 6’daki şifre tanımlama ekranında SYS, SYSTEM, DBSNMP ve SYSMAN kullanıcıları için
şifre tanımlamaları yapmamız gerekir. Burada 2 seçenek mevcuttur. Birincisi varsayılan olarak
seçili gelen Use the Same Password for All Accounts seçeneğidir. Bu seçenekte yukarıda adı
geçen 4 sistem kullanıcısı için de yazılan aynı şifre geçerli olur. Eğer veri tabanını yönetirken bu
4 hesabı tek kişi kullanıyorsa hepsi için tek şifre tanımlamak daha uygun olacaktır. Diğer seçenek
olan Use Different Password seçilirse 4 kullanıcının hepsi için farklı farklı şifreler tanımlanabilir.
Bu noktada adı geçen kullanıcıların özelliklerini listeleyelim:

Kullanıcı            Özellik
SYS                  SYS kullanıcısı veri sözlüğünü oluşturan tüm iç Oracle tablolarının sahibidir. SYS
                     kullanıcısıyla hiçbir işlem yapılmaması için bu hesabın kilitlenmesi tercih edilmelidir. SYS
                     kullanıcısının sahibi olduğu nesnelerde de değişiklik yapılmamalıdır.
SYSTEM               SYSTEM kullanıcısı birtakım yönetimsel tabloların ve view’ların sahibidir. Yetkisiz kullanım
                     ihtimaline karşı kilitlenmesi ve kullanılmaması tercih edilmelidir.
DBSNMP               Veri tabanı hakkında performans istatistiklerini toplamak ve görüntülemek amacıyla
                     Enterprise Manager tarafından kullanılan kullanıcıdır.
SYSMAN               Enterprise Manager’da SYS kullanıcısıyla aynı haklara sahiptir.

Bu ekranda Use the Same Password for All Accounts seçiliyken şifreyi 2 defa yazıp Next butonu-
na tıklayarak devam edebiliriz.

Şekil 7’deki saklama seçenekleri ekranında 3 seçenek söz konusudur. Bu ekranda dikkat ede-
ceğimiz bir nokta da bu aşamada Finish butonuna tıklayarak veri tabanı oluşturma işlemini ta-
mamlayabilecek olmamızdır. Bundan sonraki sihirbaz ekranı buradaki seçime göre değişir. Bu
seçeneklerin özellikleri şu şekildedir:
172   Bölüm 10




                  Şekil 7: DBCA Diskte saklama seçenekleri ekranı.


            Saklama Seçenekleri                 Özellik

                                                En çok kullanılan seçenektir. Veri tabanının disk üzerinde normal bir veri
            File System
                                                tabanı gibi oluşturulmasını sağlar.

                                                ASM (Automatic Storage Management) için öncelikle CSS (Oracle Cluster
                                                Synchronization Service) kurulumu yapılması gerekir. Disk yönetimini
            ASM Storage
                                                File System seçeneğine göre kolaylaştırır. Birçok işi veri tabanı yöneticisi
                                                yerine Oracle kendisi yapar.
                                                Veri tabanı dosyalarını işletim sistemi yerine donanım aracılığıyla
            Raw Devices                         doğrudan Oracle yönetir. RAC (Real Application Cluster) veri tabanları için
                                                paylaşımlı alan olarak kullanılabilir.



           Bu adımda File System seçeneğini işaretleyip Next butonuna tıklayarak devam edebiliriz.

           Şekil 8’deki veri tabanı dosyaları ekranında tanımladığımız veri tabanına ait fiziksel dosyaların
           nereye konulacağı belirtilir. Bu adımda 3 seçenek mevcuttur. Bu seçeneklerin açıklamaları şu
           şekilde özetlenebilir:

            Seçenek                          Açıklama
            Use Database File                Daha önce seçilen şablona göre veri tabanı dosyalarının yerleri belirlenir,
            Locations From Template          sonradan değiştirilebilir.
            Use Common Location fo           Veri tabanı dosyalarının yeri için farklı bir klasör tanımlamak için kullanılır,
            All Database Files               belirlenen klasör sonradan değiştirilebilir.
                                             Diskte saklama seçeneklerinde ASM seçildiyse bu seçenek seçilmelidir.
            Use Oracle-Managed Files         Bu seçenek seçildiğinde dosyaların yerleri veya adları ile ilgili sonradan
                                             yapılamaz.
                                                                                        Oracle Veritabanı   173




       Şekil 8: DBCA dosya konumlandırma ekranı.

Bu adımda Use Database File Locations From Template seçeneğini seçip Next butonuna tıkla-
yarak devam edebiliriz.




       Şekil 9: DBCA kurtarma yapılandırması ekranı.

Şekil 9’daki kurtarma yapılandırası ekranı backup ve kurtarma işlemlerinin yapılandırılması için
kullanılır. Bu aşamada 2 seçenek mevcuttur ve her ikisi bir arada da kullanılabilir seçeneklerdir.
İlk seçenek olan Specify Flash Recovery Area seçildiğinde ilgili dosyaların nerede saklanacağı
ve bu alanın MB cinsinde büyüklüğü tanımlanır. Bu alan tercihen fiziksel olarak veri tabanı dos-
yalarının bulunduğu yerden farklı olmalıdır. Diğer seçenek olan Enable Archiving seçeneği seçili
olduğunda arşiv loglaması yapacağımızı ifade eder. DBCA kurtarma yapılandırması ekranında
174   Bölüm 10



           sadece Specify Flash Recovery Area seçeneğini işaretleyip Next butonuna tıklayarak devam
           edebiliriz.




                  Şekil 10: DBCA veri tabanı içeriği ekranı, Database Components sekmesi.

           Şekil 10’daki veri tabanı içeriği ekranının Database Components sekmesinde, Oracle Data Mi-
           ning, Oracle Text, Oracle OLAP gibi Oracle veritabanı bileşenlerinin hangilerinin kurulan verita-
           banı için kullanılacağı ve hangi tablespace üzerine yerleştirileceği belirlenir. Bu sekmede sample
           Schemas seçeneğini işaretlemeden Custom Scripts sekmesine geçelim.




                  Şekil 11: DBCA veri tabanı içeriği ekranı, Custom Scripts sekmesi.

           Veri tabanı içeriği Custom Scripts sekmesinde, veri tabanı oluşturulduktan sonra üzerinde ça-
           lışmasını istediğimiz bir SQL script dosyası varsa bu dosyayı seçerek birtakım kurulumların oto-
                                                                                       Oracle Veritabanı   175



matik olarak yapılmasını sağlayabiliriz. Bu ekranda No scripts to run seçeneğini işaretleyip Next
butonuna tıklayarak devam edebiliriz.




       Şekil 12: DBCA başlangıç parametreleri, Memory sekmesi.

Şekil 12’deki başlangıç parametreleri, Memory sekmesinde oluşturduğumuz veritabanı için fizik-
sel bellek alanı üzerinde ne kadar yer kullanılacağını tanımlayabiliriz. Typical– Allocate memory
as a percentage of total physical memory seçeneği ve Custom seçeneği bulunur. Eğer 1.seçenek
seçilirse bellek yönetimini Oracle kendisi yapar. Diğer seçenekte ise bellek yönetiminde SGA
(System Global Area) ve PGA (Process Global Area) için bellekte ne kadar yer ayıracağımızı
belirtebiliriz. Bu sekmede 1.seçeneği işaretleyerek Sizing sekmesine geçelim.




       Şekil 13: DBCA başlangıç parametreleri, Sizing sekmesi.
176   Bölüm 10



           Şekil 13’deki başlangıç parametreleri, Sizing sekmesinde Microsoft SQL Server’daki veri sayfa-
           sına (data page) karşılık gelen blok boyutu girilebilir. Transactional veri tabanları için bu boyut
           genellikle 8KB’dir. Data warehouse için 16KB ve üstü düşünülmelidir. Processes’de belirtilen sayı
           işletim sisteminden bu veritabanına açılabilecek maksimum eş zamanlı process sayısını belirtir.
           En başta belirtilen arka planda çalışan process’ler için en az 6 olarak tanımlanmalıdır. Burada
           belirtilen sayı büyüdükçe bellekte SGA olarak bu veri tabanı için ayrılacak alan büyüyecektir.
           Buradaki sayıyı da 150’de bırakarak Character Sets sekmesine geçelim.




                  Şekil 14: DBCA başlangıç parametreleri, Character Sets sekmesi.

           Şekil 14’teki başlangıç parametreleri, Character Sets sekmesinde yerelleştirme ayarları yapılır.
           Bu ayarları Microsoft SQL Server’daki collation yapılandırması gibi düşünebiliriz. Use the default
           seçeneği işletim sisteminde o andaki seçili karakter setine göre, Use Unicode, Unicode’a göre,
           Choose from the list of character sets’de seçeceğimiz karakter setine göre veri tabanını yapılan-
           dırır. Bu 3’lü seçimin altında bulunan National Character Set Unicode olarak tanımlanmayan ka-
           rakter setine alternatif Unicode karakter setinin eklenmesini sağlar. Default Language, tarih, AM,
           PM gibi yerel ayarlar ve ORDER BY ile sıralama yapısının hangi dile göre yapılacağını belirler.
           Default Date Format ise tarih verilerinin hangi ülkeye, dile göre gösterileceğini tanımlar. Bu sek-
           mede sadece Use the Default seçeneğini seçip, diğer hiçbir seçeneği değiştirmeden Connection
           Mode sekmesine geçelim.

           Şekil 15’teki başlangıç parametreleri, Connection Mode sekmesinde Oracle veri tabanı sunucu-
           suna bağlantı şekli belirtilir. Burada 2 seçenek mevcuttur. Dedicated Server Mode seçildiğinde
           veri tabanına bağlanan her istemci için ayrı bir kaynak ayrılır. Eğer veri tabanına bağlanan kulla-
           nıcı sayısı çok değişken değil ve az sayıdaysa ve bağlanan kullanıcılar çok kısa sürede bağlan-
           tılarını sonlandırmıyorlarsa bu seçenek seçilmelidir. 2. seçenek olan Shared Server Mode ise bir
           önceki seçenek için tanımlanan durumların dışında kalan uygulamalar için idealdir. Bu seçenekte
           kaynakların ortak kullanımı söz konusu olduğundan ne kadar ortak server process’inin oluşturula-
           cağı tanımlanmalıdır. Genellikle çoğu OLTP veri tabanı için Shared Server Mode, çoğu OLAP veri
           tabanı için de Dedicated Server Mode daha doğru seçim olacaktır. Bu sekmede Shared Server
           Mode seçeneğini işaretleyip, Shared Server sayısını 1 bırakıp (bu veri tabanı oluşturma işlemi
           örnek olduğu için 1’de bıraktık, bu sayı veri tabanının kullanım yoğunluğuna ve gelen istemlerin
           büyüklüklerine göre ayarlanmalıdır) Next butonuna tıklayarak devam edebiliriz.
                                                                                            Oracle Veritabanı   177




       Şekil 15: DBCA başlangıç parametreleri, Connection Mode sekmesi.




       Şekil 16: DBCA veri tabanı saklama yapısı ekranı.

Şekil 16’daki veri tabanı saklama yapısı ekranından daha önce belirlediğimiz (örnek şablona göre
seçtiğimiz için tek tek tanımlamadık) veri tabanına yazılacak dosyaların yerleri ve isimleriyle ilgili
değişiklikleri yapabilmemizi sağlar. Bu ekrandan soldaki ağaç yapısından kontrol dosyaları, veri
dosyaları ve log dosyalarının yerlerini ve yapıları görüntülenip değiştirilebilir. Burada herhangi bir
değişiklik yapmadan Next butonuna tıklayarak devam edelim.

Şekil 17’deki veri tabanı oluşturma ekranı DBCA sihirbazının son ekranıdır. Bu ekranda 3 seçenek
mevcuttur. Create Database seçeneği tanımladığımız veri tabanının fiziksel olarak oluşturulması-
nı sağlar. Save as a Database Template seçeneği yapılandırdığımız veri tabanı yapısının şablon
olarak saklanmasını sağlar. Generate Database Creation Scripts seçeneği de yapılandırdığımız
178   Bölüm 10



           veri tabanı yapısnın script’inin oluşturulmasını sağlar. Bu ekrandaki seçeneklerini herhangi birini,
           ikisini ya da hepsini seçebiliriz. Sadece Create Database seçeneğini seçerek Finish butonuna
           tıklayarak tanımladığımız veri tabanını oluşturalım.




                  Şekil 17: DBCA veri tabanı oluşturma ekranı.

           Sihirbaz veri tabanını oluşturmadan önce tüm parametreleri özet şeklinde çıkarır. Bu ekran üze-
           rinden değişiklik yapılamaz. Save as an HTML file seçeneğiyle bilgi olarak saklamak faydalı ola-
           bilir. OK butonuna tıkladığımızda veri tabanı oluşturulmaya başlayacaktır.




                             Şekil 18: Veri tabanı parametreleri ekranı.
                                                                                          Oracle Veritabanı   179




                 Şekil 19: Veri tabanı oluşturma ekranı.

Şekil 19’da veri tabanının oluşturulma sürecini görebilirsiniz. Böylece Oracle üzerinde örnek veri
tabanı oluşturma işlemini tamamlamış olduk.

Temel Veri Tipleri
varchar2: 4000 taneye kadar karakter tutabilen veri tipidir. Microsoft SQL Server’daki varchar
veri tipi gibi düşünülebilir. Eğer saklanacak verinin başında ya da sonunda boşluk (space) karak-
teri varsa bunları silerek tutar.

nvarchar2: 4000 taneye kadar Unicode karakter tutabilen veri tipidir. Microsoft SQL Server’daki
nvarchar veri tipi gibi düşünülebilir. Eğer saklanacak verinin başında ya da sonunda boşluk (spa-
ce) karakteri varsa bunları silerek tutar.

char: 2000 taneye kadar sabit uzunluklu karakter tutabilen veri tipidir. Microsoft SQL Server’daki
char veri tipi gibi düşünülebilir.

nchar: 2000 taneye kadar sabit uzunluklu Unicode karakter tutabilen veri tipidir. Microsoft SQL
Server’daki nchar veri tipi gibi düşünülebilir.

number: Her türlü sayısal verilerin tutulabileceği veri tipidir. Microsoft SQL Server’daki int, flo-
at gibi veri tiplerine karşılık olarak düşünülebilir. Dikkat edilmesi gereken nokta Microsoft SQL
Server’daki decimal gibi tanımlanmasıdır.

date: Saniye bazında tarih ve zaman verisi tutar. Geçerli tarih aralığı MÖ 1 Ocak 4712’den MS 31
Aralık 9999’a kadardır. Microsoft SQL Server’daki smalldatetime veri tipi gibi düşünülebilir.

timestamp: date tipine çok benzeyen bir veri tipidir. date tipine göre daha detaylı zaman bilgisi
tutar. Microsoft SQL Server’daki datetime veri tipi gibi düşünülebilir.

clob (character large object): 4 GB’a kadar karakter verisi tutar. varchar2’nin büyütülmüş bir
tipi olarak düşünülebilir. Microsoft SQL Server 2005 ile birlikte gelen varchar(max) veri tipi gibi
düşünülebilir.

blob (binary large object): clob’a benzer bir veri tipi olmakla birlikte içinde tuttuğu veri tipi
binary’dir. Maksimum büyüklüğü 4 GB’tır. Microsoft SQL Server’daki text, image tiplerine ben-
zerdir.

Oracle’da Kullanıcı Yönetimi ve Güvenlik
Oracle sisteminde kullanıcı yönetimi ve güvenlik Microsoft SQL Server’a göre daha detaylıdır;
çünkü Microsoft SQL Server sadece Microsoft Windows ailesi işletim sistemlerinde çalışırken
180   Bölüm 10



           Oracle Microsoft Windows ailesi, UNIX türevleri ve Linux türevleri üzerinde de çalışmaktadır. Bu
           sebeple kullanıcı yapısı farklılıklar göstermektedir. Örneğin Microsoft SQL Server’da olan “Win-
           dows Authentication” Oracle için geçerli değildir; ancak bunu karşılayan farklı bir yapı mevcuttur.
           Ayrıca Oracle’da kullanıcı, hesap ve şema (schema) ifadeleri aynı anlamda kullanılabilir. Kimlik
           denetleme yöntemlerine geçmeden önce kimlik denetiminde kullanılan bazı kavramları tanımla-
           yalım.

           Default Tablespace: Bir kullanıcının oluşturduğu/oluşturacağı nesnelerin (schema objects),
           nesne oluşturulurken nesnelerin hangi tablespace üzerinde tutulacağı belirtilmediğinde default
           olarak tutulduğu tablespace’tir. Kullanıcı tanımlanırken belirtilmezse, veri tabanı kendi default
           tablespace’ini kullanıcıya da default tablespace olarak atar.

           Ara İşlemler İçin Kullanılan (Temporary) Tablespace: Temporary tablespace üzerinde GROUP
           BY, ORDER BY, DISTINCT, JOIN ve index oluşturma gibi geçici alan ihtiyacı olan işlemlerde kul-
           lanılan tablespace’tir, aynı zamanda geçici tablolar için de kullanılır. Kullanıcı tanımlanırken belir-
           tilmezse, veri tabanı kendi default tablespace’ini kullanıcıya da default tablespace olarak atar.

           Profiller: Kullanıcı yönetimini kolaylaştıran bir mekanizmadır. Her kullanıcı mutlaka bir profil al-
           tında tanımlıdır. Kaynakların kullanınımı profil tanımına göre kısıtlar ve şifre kurallarının tanımlan-
           masını sağlar. Kullanıcı tanımlanırken belirtilmezse, kullanıcı Oracle default profile atanır.

           Authentication (Kimlik Denetleme) Yöntemleri
           Oracle’da 3 kimlik denetleme yöntemi vardır. Bu yöntemler şu şekildedir:

           1� Password Authentication
           2. External Authentication
           3� Global Authentication

           Password Authentication
           Microsoft SQL Server’daki SQL Authentication ile eşleniktir. Kullanıcılar Oracle veri tabanı üze-
           rinde tanımlıdır. Oracle kullanıcıya ait şifreyi üzerinde şifreli olarak tutar. Password Authentication
           ile kullanılacak bir kullanıcı şöyle tanımlanır:

                 CREATE	USER	kaya	IDENTIFIED	BY	qwedcv89;

           Burada “kaya” kullanıcının adıyken “qwedcv89” bu kullanıcın şifresidir.

           Bu kullanıcıya ait bir default tablespace; yani oluşturacağı nesnelerin tutulacağı bir tablespace
           belirtmek istersek;

                 CREATE	USER	kaya	IDENTIFIED	BY	qwedcv89
                 DEFAULT	TABLESPACE	xyz;

           ifadesini kullandığımızda bu kullanıcının nesnelerinin yaratılacağı default tablespace xyz adlı
           tablespace olacaktır. Eğer “kaya” kullanıcısı daha önceden oluşturulduysa ALTER ifadesi ile de
           default tablespace tanımlayabiliriz.

                 ALTER	USER	kaya
                 DEFAULT	TABLESPACE	xyz;

           Bu kullanıcı için bir de geçici tablespace tanımlamak istersek;

                 CREATE	USER	kaya	IDENTIFIED	BY	qwedcv89
                 DEFAULT	TABLESPACE	xyz
                 TEMPORARY	TABLESPACE	abc;
           ifadesini kullanabiliriz. Bu durumda “kaya” kullanıcısının çalıştırdığı büyük veri üzerinde işlem
           yapıp geçici alanlar kullanan sorgular, geçici tablespace olarak abc tablespace’ini kullanacaktır.
                                                                                             Oracle Veritabanı   181



Profil tanımlamak için de şu şekilde bir ifade kullanabilirsiniz:

      CREATE	USER	kaya	IDENTIFIED	BY	qwedcv89
      DEFAULT	TABLESPACE	xyz
      TEMPORARY	TABLESPACE	abc
      PROFILE	prf1;

External Authentication
External authentication Microsoft SQL Server’daki Windows authentication’a çok benzerdir. Kul-
lanıcılar yine veri tabanında tutulur; ancak kimlik denetlemesini işletim sistemi yapar. Microsoft
SQL Server’daki Windows authentication’dan en önemli farkı sadece Microsoft Windows’la değil
diğer işletim sistemleri ile de entegre çalışabilmesidir. Bu tip kullanıcılar OPS$ kullanıcıları olarka
da adlandırılırlar. External authentication mekanizmasıyla bir kullanıcı tanımlamak için;

      CREATE	USER	ops$kaya	IDENTIFIED	EXTERNALLY;

ifadesini kullanabiliriz. Bu durumda işletim sistemi üzerinde kullancı adı “kaya” olan kullanıcı,
Oracle sistemine, ilgili işletim sistemi üzerinden onaylanarak girecektir. Bu işlem Linux ve UNIX
türevleri için oldukça kolaydır; ancak Windows üzerinde bir miktar karmaşıktır. Linux ve UNIX
türevlerinde /etc/passwd içinde kullanıcının tanımlanmış olması yeterlidir. Windows üzerindeki bir
kullanıcıyı Oracle’da tanımlamak için yapmamız gerekenler şu şekildedir:

1� Windows işletim sistemi üzerinde kullanıcıyı tanımlayın.
2. Tanımladığınız kullanıcıyı Windows üzerinde ora_dba grubuna ekleyin.
3� Start > Programs > Oracle - OraDb10g_home1 > Configuration and Migration Tools > Ad-
   ministration Assistant for Windows üzerinden OS Database Administrators ve OS Database
   Operators gruplarına ekleyin.
4. SPFILE dosyasında OS_AUTHENT_PREFIX=OPS$ şeklinde tanımlana yapın.
5. CREATE USER OPS$kullanici IDENTIFIED EXTERNALLY; ifadesini SQL Plus üzerinde
   çalıştırın.

Global Authentication
Oracle üzerinde Microsoft SQL Server’dan farklı olarak bulunan bir authentication mekanizması-
dır. Authentication işlemi, gelişmiş güvenlik opsiyonu ile sağlanan bir servis aracılığıyla sağlanır
ve password authentication’daki şifrelerin tutulması söz konusu değildir. Burada kullanılan me-
kanizmalara örnek olarak biyometrik yöntemler, Kerberos ve X.509 sertifikaları sayılabilir. Diğer
mekanizmalara göre oldukça detaylı bir yöntemdir.
11
     Oracle
     Üzerinde
     Programlama
11 Oracle Üzerinde
Programlama

• PL/SQL Nedir?

• SQL Plus

• TOAD

• PL/SQL ile Programlama

• PL/SQL’de Kontrol Yapıları

• PL/SQL’de Alfanümerik Tipler

• PL/SQL’de Mantıksal Tipler

• PL/SQL’de Tarih ve Zaman Tipleri

• Referans Tipleri

• LOB (Large Object) Tipleri
                  Oracle Üzerinde Programlama
PL/SQL Nedir?
PL/SQL’i (Procedural Language Extensions to the Structured Query Language) Microsoft SQL
Server’daki T-SQL’in (Transact SQL)Oracle sistemindeki karşılığı olarak düşünebilirsiniz. T-SQL
gibi PL/SQL de standart SQL dilinin, günün gereksinimleri bağlamında yetersiz kalması çerçeve-
sinde ortaya çıkmıştır. PL/SQL ile stored procedure, trigger gibi veri tabanı nesneleri oluşturabi-
lirsiniz. PL/SQL ifadeleri Oracle veri tabanı üzerinde çalışır.

PL/SQL dil olarak ilk bakışta bir miktar yabancı gelebilir; ancak yeterli veri tabanı bilginiz varsa
alışmanız çok zor olmayacaktır. Her dilde olduğu gibi bol bol pratik, PL/SQL’deki yetkinliklerinizi
çabuk geliştirmeniz açısından çok faydalı olacaktır. T-SQL’den tanıdığınız standart SQL dilinin
kapsadığı bütün ifadeleri burada da kullanabileceksiniz. Bildiğiniz 4 temel SQL ifadesi olan SE-
LECT, INSERT, UPDATE, DELETE ifadelerini aynen kullanabilirsiniz.

PL/SQL ifadelerini yazmak için kullanabileceğiniz temel ortam, Oracle yüklemesiyle birlikte gelen
SQL Plus’tır. SQL Plus’ı Microsoft SQL Server 2000 ve öncesindeki Query Analyzer, Microsoft
SQL Server 2005’te SQL Server Management Studio’daki Query Window’a karşılık gelen bir araç
olarak düşünebilirsiniz; ancak her ikisine göre de daha ilkel bulabilirsiniz.

SQL Plus
SQL Plus’ı Start > Programs > Oracle – OraDb10g_home1 > Application Development > SQL
Plus yoluyla çalıştırabilirsiniz. Çalıştırdığınızda karşınıza Şekil – 1’deki ekran görüntüsü gelecek-
tir.




     Şekil 1: SQL Plus Açılış Ekranı.


Programı ilk açtığınızda Log On ekranı karşınıza gelecektir. Bu ekranda User Name bölümüne
tanımladığınız kullanıcılardan birini girmeniz gerekir. Veri tabanı oluştururken tanımlanan 4 kul-
lanıcımız vardı, bunlardan SYSTEM kullanıcısını burada kullanabiliriz. Host String bölümüne de
veri tabanımızın adını yazmalıyız. Host String’te kullanabileceğimiz veri tabanlarını tnsnames.ora
dosyasından da bulabiliriz. Bunun için Windows Search ile tnsnames.ora dosyasını aratabilirsi-
niz. Başarılı bir şekilde login olduğunuzda karşınıza Şekil 2’deki gibi bir ekran gelecektir.
186   Bölüm 11




                 Şekil 2: SQL Plus Açılış Ekranı – 2.

           Önce SQL Plus üzerinden veri tabanımızda basit bir tablo oluşturalım. Bunun için standart
           SQL’den bildiğimiz CREATE TABLE ifadesini kullanacağız. Bu tablonun oluşturulmasını Şekil
           3’de görebilirsiniz.




                 Şekil 3: Tablo oluşturmak.


           Bu tabloyu oluşturduktan sonra tabloya veri girişi için;

           INSERT INTO Urun ( UrunId, UrunAdi) VALUES ( 1, ‘Çikolata’);

           yazalım. İfadelerin sonunda noktalı virgül “;” koymayı unutmayın. Microsoft SQL Server’da yaz-
           dığımız ifadelere göre ifadelerin sonunda “;” bulunması gerekir. Ayrıca bu ifadeyi ya da ifade
           bloğunu çalıştırmak için Enter’a basmanız yeterlidir.

           Benzer şekilde bir sorgu yapmak için de SQL Plus’ta

           SELECT * FROM Urun;

           yazarak Urun tablosunun içindeki verileri inceleyebiliriz. Yazdığımız bu ifadeleri SQL Plus ekra-
           nında Şekil 4’te görebilirsiniz.
                                                                      Oracle Üzerinde Programlama ve PL/SQL   187




     Şekil 4: SQL Plus’ta SQL İfadeleri.


TOAD
SQL Plus’a daha iyi bir alternatif olarak TOAD’u kullanabilirsiniz. http://www.toadsoft.com/lic_ag-
ree.html adresinden TOAD’un Oracle için ücretsiz (freeware) versiyonunu indirebilirsiniz.

TOAD Oracle, Microsoft SQL Server, IBM DB2 ve mySQL gibi veri tabanları için kullanılabilen
bir araçtır. TOAD’u Microsoft SQL Server 2005 Management Studio gibi düşünebilirsiniz. Hem
yönetim hem de programlama arayüzlerini birlikte sunar.




                Şekil 5: TOAD Login Ekranı.

Şekil 5’teki TOAD’un login ekranını Microsoft SQL Server Login ekranına benzer olarak düşüne-
bilirsiniz. Bağlanacağınız veri tabanını, hangi kullanıcı ile hangi rolle ve hangi sunucuya bağlana-
cağınızı belirterek TOAD’un ana ekranına geçebilirsiniz. Dikkat edeceğiniz gibi Windows Authen-
tication şeklinde bir seçenek bulunmaz. Oracle’da Windows Authentication şeklinde bir seçenek
bulunmaz; ancak external authentication ile Windows kullanıcıları ile Oracle sistemine login ola-
bilirsiniz. Bu opsiyonu kurmak Microsoft SQL Server kadar kolay ve düz değildir. Bu sebeple
Oracle’ın kendi kullanıcı (schema) sistemini kullanarak devam edeceğiz. TOAD login ekranında
bilgileri doğru olarak girip Connect butonuna tıkladığımızda ana ekrana geçebiliriz.
188   Bölüm 11




                 Şekil 6: TOAD ana ekranı.

           TOAD ana ekranında Şekil 6’dan gördüğünüz gibi pek çok işi yapabilirsiniz. Buraya standart SQL
           ve PL/SQL sorgularınızı yazarak çalıştırabilirsiniz. Sorgu yazarken, eğer sorguda nesne kullanı-
           yorsak dikkat etmemiz gereken nokta nesne adından önce schema adını yazmamız gerekliliği-
           dir. Schema’ları Microsoft SQL Server 2005’teki schema’lara denk olarak düşünebiliriz. SYSTEM
           kullanıcısını da Microsoft SQL Server 2005’deki dbo’ya karşılık gibi görebiliriz. Aslında birebir bu
           şekilde denkleştirmeler söz konusu olmasa da bu benzetmeleri bir kolaylık olarak görebilirsiniz.




                 Şekil 7: TOAD’da sorgu.
                                                                         Oracle Üzerinde Programlama ve PL/SQL   189



TOAD’da sorgu yazmayı Şekil 7’de görebilirsiniz. SQL ifadelerinin sonunda “;” kullanmanız ya
da kullanmamanız sorgu sonucunu değiştirmez. Sorguda daha önce oluşturduğumuz Urun tab-
losunu SYSTEM.Urun olarak kullandığımıza dikkat edin. Bu şekilde yazmazsanız hata alırsınız.
Sorguyu çalıştırmak için klavyeden F5 tuşunu kullanabilirsiniz. Bununla birlikte TOAD üzerindeki
toolbar’dan da sorguları çalıştırabilirsiniz. Sorgu çalıştırabileceğiniz butonları Şekil 8’den görebi-
lirsiniz.




  Şekil 8: TOAD sorgu çalıştırma butonları.



PL/SQL ile Programlama
PL/SQL ile programlamaya basit bir örnek ile başlayalım. T-SQL’dekine göre muhtemelen en çok
zorlayacak durum PL/SQL içinde kullanılabilecek fonksiyonların çokluğu olacaktır. PL/SQL’de
büyük ya da küçük harf kullanarak kod yazabilirsiniz.

Uygulama 1: PL/SQL ile İlk Örnek Uygulama

        DECLARE
       1	
       2		           	           UrunSayisi	INTEGER;
        	
       3	            BEGIN
        	
       4	            	           SELECT
        	
       5	            	           	            COUNT(*)	INTO	UrunSayisi
        	
       6	            	           	            FROM	Urun;
        	
       7	            	           DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi:	‘	||	UrunSayisi);
        	
       8	            END;

Uygulama 1’deki kod oldukça basit bir uygulamadır; ancak PL/SQL konusunda oldukça önemli
bilgiler verir. Bu örnekte 1 ve 2 numaralı satırlar tanımlama (declaration) bloğudur. Altındaki kod
bloğunda kullanılacak değişkenler, parametreler gibi yapılar burada tanımlanır. Örneğimizde 2
numaralı satırda INTEGER tipinde, UrunSayisi adında bir değişken tanımlanmıştır. 3 numaralı
satırda çalıştırma bloğunun (execution block) başladığını gösteren BEGIN ifadesi bulunuyor. Ör-
nekteki 8 numaralı satırda bulunan END ifadesine kadar tüm ifadeler çalıştırma bloğunun içinde-
dir. 4, 5 ve 6 numaralı satırlarda Urun tablosu içindeki satır sayısını UrunSayisi değişkeninin içine
atan basit bir sorguyu görebilirsiniz. 5 numaralı satırdaki INTO ifadesini T-SQL’de kullandığımız
değişkene değer atamadaki “=” gibi düşünebilirsiniz. 7 numaralı satırda ise T-SQL’deki print
ifadesine benzer bir iş yapan DBMS_OUTPUT.PUT_LINE fonksiyonu bulunuyor. DBMS_OUTPUT.
PUT_LINE DBMS Output tamponuna yazma işlemi yapar. Bu fonksiyonun içinde kullandığımız
|| işaretini T-SQL’de alfanümerik ifadeleri birleştirmek için kullandığımız + işaretinin yerine kul-
lanıyoruz. T-SQL’de print ifadesinde bu şekilde bir çıktı almak için ise tanımladığımız intde-
ğişkeni öncelikle alfanümerik bir tipe çevirmemiz gerekir, çünkü print 2 ifadeyi otomatik olarak
alfanümeriğe dönüştürmez. Buradan da anlayacağımız gibi DBMS_OUTPUT.PUT_LINE fonksiyo-
nu otomatik çevirme (implicit conversion) yapmaktadır. Burada T-SQL’de kullandığımız SELECT
@UrunSayisi gibi bir ifade ile değişkenin taşıdığı değeri yazdıramayız. 8 numaralı satırda da
çalışma bloğu sona ermektedir. Bu örneğin T-SQL’deki benzer karşılığını Uygulama 1.1’de ince-
leyebilirsiniz.
190   Bölüm 11



           Uygulama 1.1: Uygulama – 1’deki PL/SQL Kodunun T-SQL’deki Eşleniği

                    DECLARE	@UrunSayisi	int
                   1	
                    SELECT
                   2	
                    	
                   3	           @UrunSayisi	=	COUNT(*)
                    	
                   4	           FROM	Urun
                    PRINT	‘Urun	Sayisi:	’	+	CONVERT(	varchar,	@UrunSayisi)
                   5	

           Uygulama 1’deki örneği TOAD’da çalıştırdığınızda herhangi bir çıktı göremezsiniz. Çünkü DBMS_
           OUTPUT.PUT_LINE fonksiyonu bir çalışma ekranında bir sonuç üretmez bir tampona yazar.
           TOAD ile bu tampon bölgeyi görüntüleyebiliriz. Bunun için örnek uygulamayı çalıştırmadan önce
           View menüsünden DBMS Output seçeneğini seçin. Karşınıza boş bir ekran gelecektir. Standart
           Windows uygulamalarında olduğu gibi, daha önceden kod yazdığınız pencereye dönmek için Ctrl-
           Tab kullanabilirsiniz ya da TOAD’un Window menüsünden diğer pencereye geçiş yapabilirsiniz.




                 Şekil 9: Uygulama 1’in çalışmasında sorgu ekranı.


           Şekil 9’da görebileceğiniz gibi burada satır sayısı ile ilgili herhangi bir sonuç göremiyoruz, sadece
           PL/SQL procedure successfully completed ifadesini görebilirsiniz.




                        Şekil 10: TOAD DBMS Output penceresi.
                                                                        Oracle Üzerinde Programlama ve PL/SQL   191



Şekil 10’da TOAD DBMS Output penceresini görebilirsiniz. Burada DBMS_OUTPUT.PUT_LINE
ifadesinin sonucu olan Urun Sayisi: 2 string’i yazılmıştır.

PL/SQL’de Kontrol Yapıları
PL/SQL’de T-SQL’deki gibi IF-THEN-ELSE kontrol yapısı bulunur. Bununla birlikte T-SQL’de
bulunmayan CASE yapısı da mevcuttur. CASE yapısı C#’taki ve Java’daki switch yapısı şeklinde
çalışır.

IF-THEN-ELSE
Uygulama 2: PL/SQL ile IF-THEN-ELSE

       DECLARE
      1	
      2		        	        UrunSayisi	INTEGER;
       	
      3	         BEGIN
       	
      4	         	        SELECT
       	
      5	         	        	       COUNT(*)	INTO	UrunSayisi
       	
      6	         	        	       FROM	Urun;
       	
      7	         	        IF	UrunSayisi	<=	2
       	
      8	         	        THEN
       	
      9	     	     	     DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	‘’’’	
      ||	‘den	az	ya	da	2’);
      10	        	        	       ELSE
      11	    	     	     	     DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	
      ‘’’’	||	‘den	fazla...’);
      12	        	        	       END	IF;
      13	        	        END;

Uygulama 2’deki kodun 7, 8, 9, 10, 11 ve 12 numaralı satırlarda IF-THEN-ELSE yapısını göre-
bilirsiniz. PL/SQL’deki IF-THEN-ELSE yapısı T-SQL’deki IF-ELSE bloğu ile aynı şekilde çalışır.
Uygulama 2.1’de Uygulama 1’deki PL/SQL kodunun T-SQL eşleniğini inceleyebilirsiniz.

Uygulama 2.1: Uygulama 1’deki Kodun T-SQL Eşleniği

       DECLARE	@UrunSayisi	int
      1	
       SELECT
      2	
       	
      3	         @UrunSayisi	=	COUNT(*)
       	
      4	         FROM	Urun
       IF	@UrunSayisi	<=	2
      5	
       	
      6	         PRINT	‘Urun	sayisi	2’	+	char(39)	+	‘den	az	ya	da	2’
       ELSE
      7	
       	
      8	         PRINT	‘Urun	sayisi	2’	+	char(39)	+	‘den	fazla...’

IF-THEN-ELSIF-ELSE
IF yapısının en detaylı şekli ELSIF ile kullanılan şeklidir. ELSIF (ELSE IF’in kısaltması) yapısı
T-SQL’deki ELSE IF ile aynı şekilde çalışır. ELSIF, üstündeki IF ya da ELSIF bloğundan false
ile çıkıldığında çalışır ve tanımladığı koşul true sonuç veriyorsa bloğu çalıştırır; aksi takdirde ken-
dinden sonra gelen bloğa geçer.
192   Bölüm 11



           Uygulama 3: PL/SQL ile ELSIF

                  DECLARE
                 1	
                 2		       	       UrunSayisi	INTEGER;
                  	
                 3	        BEGIN
                  	
                 4	        	       SELECT
                  	
                 5	        	       	      COUNT(*)	INTO	UrunSayisi
                  	
                 6	        	       	      FROM	Urun;
                  	
                 7	        	       IF	UrunSayisi	<	2
                  	
                 8	        	       THEN
                  	
                 9	     	     	           DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	‘’’’	
                 ||	‘den	az...’);
                 10	       	       	      ELSIF	UrunSayisi	>	2
                 11	       	       	      THEN
                 12	    	     	     	     DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	
                 ‘’’’	||	‘den	fazla...’);
                 13	       	       	      ELSE
                 14	       	       	      	       DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘);
                 15	       	       	      END	IF;
                 16	       	       END;

           Uygulama 3’de 7 numaralı satırda eğer UrunSayisi 2’den küçük değilse 10 numaralı satırdaki
           ELSIF çalışır. Eğer UrunSayisi 2’den büyükse 12 numaralı satır çalışır. Eğer UrunSayisi
           2’den de büyük değilse 2’ye eşit demektir. Bu durumda da 13 numaralı satırdan dolayı 14 numa-
           ralı satır çalışır.

           Eğer IF yapısı içerisinde bir blok oluşturumak istersek bunun için T-SQL’de olduğu gibi BEGIN-
           END blok yapılandırıcıları ile bloğu tanımlamalıyız.

           Uygulama 3.1: PL/SQL ile ELSIF

                  DECLARE
                 1	
                 2	UrunSayisi	INTEGER;
                  	BEGIN
                 3	
                  	SELECT
                 4	
                  	COUNT(*)	INTO	UrunSayisi
                 5	
                  	FROM	Urun;
                 6	
                  	IF	UrunSayisi	<	2
                 7	
                  	THEN
                 8	
                  	DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	‘’’’	||	‘den	az...’);
                 9	
                 10	ELSIF	UrunSayisi	>	2
                 11	THEN
                 12	BEGIN
                 13	DBMS_OUTPUT.PUT_LINE(‘ELSIF	blogu...’);
                 14	DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	‘’’’	||	‘den	
                 fazla...’);
                 15	END;
                 16	ELSE
                                                                    Oracle Üzerinde Programlama ve PL/SQL   193



      17	DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘);
      18	END	IF;
      19	END;
Uygulama 3.1’de 10 numaralı satırdan başlayan ELSIF bloğu 15 numaralı satıra kadar de-
vam eder. Eğer UrunSayisi 2’den büyükse ELSIF içinde tanımlanan her 2 DBMS_OUTPUT.
PUT_LINE ifadesi de çalışacaktır. Her ne kadar yazdığımız BEGIN-END blok yapılandırıcılarını
kullanmak zorunda olmasak da kodun okunurluğunu artırmak açısından blok yapılandırıcılarını
kullanmak faydalıdır.

İç İçe IF Yapıları
PL/SQL’de iç içe IF yapıları da kullanılabilir. Çalışma şekli C#, Java ya da T-SQL’den farklı de-
ğildir.

Uygulama 4: PL/SQL ile İç İçe IF Yapısı

       DECLARE
      1	
      2		       	       UrunSayisi	INTEGER;
       	
      3	        UrunSayisiB	INTEGER;
       	
      4	        BEGIN
       	
      5	        	       SELECT
       	
      6	        	       	       COUNT(*)	INTO	UrunSayisi
       	
      7	        	       	       FROM	Urun;
       	
      8	        	       SELECT
       	
      9	        	       	       COUNT(*)	INTO	UrunSayisiB
      10	       	       	       	        FROM	Urun
      11	       	       	       	        WHERE	UrunAdi	LIKE	‘B%’;
      12	       	       	       IF	UrunSayisi	<	2
      13	       	       	       THEN
      14	    	     	     	               DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	
      ‘’’’	||	‘den	az...’);
      15	       	       	       	        IF	UrunSayisiB	=	1
      16	       	       	       	        THEN
      17	    	     	     	     	     DBMS_OUTPUT.PUT_LINE(‘B	ile	
      baslayan	urun	sayisi:	’	||	UrunSayisiB);
      18	       	       	       	        END	IF;
      19	       	       	       ELSIF	UrunSayisi	>	2
      20	       	       	       THEN
      21	       	       	       BEGIN
      22	       	       	       	        DBMS_OUTPUT.PUT_LINE(‘ELSIF	blogu...’);
      23	    	     	     	     DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	
      ‘’’’	||	‘den	fazla...’);
      24	       	       	       END;
      25	       	       	       ELSE
      26	       	       	       	        DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘);
      27	       	       	       END	IF;
      28	       	       END;
194   Bölüm 11



           Uygulama 4’te 8 ile 11 numaralı satırlardaki SELECT ifadesinde UrunSayisiB değişkenine B
           harfiyle başlayan ürünlerin sayısı atanacaktır. Eğer UrunSayisi 2’den küçükse 15 numaralı
           satırdaki iç IF yapısı da çalışacaktır. Eğer UrunSayisiB 1’e eşitse de 17 numaralı satır çalışa-
           caktır.

           IF Yapısı ile İlgili Dikkat Edilmesi Gereken Noktalar
           1� Her IF için mutlaka bir END IF bulunmalıdır.
           2. Her END IF kendinden önceki ilk IF ifadesine aittir.
           3� END IF birleşik yazılmaz.
           4. END IF’in sonunda mutlaka “;” bulunmalıdır.
           5. ELSIF yazarken ELSE’in son “E” harfi yoktur.

           CASE
           CASE yapısı C# ve Java’daki switch yapısı gibi çalışır. IF-THEN-ELSIF-ELSE yapısını daha
           kolay ve okunaklı hale getirir. PL/SQL’deki CASE yapısını T-SQL’de SELECT ifadesinin içinde
           kullanılan CASE ifadesiyle karıştırmamak gerekir. T-SQL’deki CASE yapısı result set’in içindeki
           tüm kayıtlar için tek tek çalışırken PL/SQL’de kayıtlar bazında çalışmaz. Kod yazımı olarak her
           ikisi de birbirine çok benzerdir.

           Uygulama 5: PL/SQL’de CASE Örneği 1

                   DECLARE
                  1	
                  2		        	        UrunSayisi	INTEGER;
                   	
                  3	         BEGIN
                   	
                  4	         	        SELECT
                   	
                  5	         	        	        COUNT(*)	INTO	UrunSayisi
                   	
                  6	         	        	        FROM	Urun;
                   	
                  7	         	        CASE	UrunSayisi
                   	
                  8	         	        WHEN	2	THEN
                   	
                  9	         	        	        DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘);
                  10	        	        	        WHEN	3	THEN
                  11	        	        	        	        DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘);
                  12	        	        	        ELSE
                  13	    	     	     	     DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	3‘	||	
                  ‘’’’	||	‘ten	fazla...’);
                  14	        	        	        END	CASE;
                  15	        	        END;

           Uygulama 4’te 7 – 14 numaralı satırlar CASE bloğunu oluşturur. 7 numaralı satırdaki CASE Urun-
           Sayisi ifadesi UrunSayisi değişkeninin karşılaştırmada kullanılacağını gösterir. 8 numaralı
           satır eğer UrunSayisi değişkeninin 2’ye eşitliğini kontrol eder. Eğer 2’ye eşitse 9 numaralı satı-
           ra geçer, eşit değilse 10 numaralı satır ve UrunSayisi değişkeninin 3’e eşit olup olmadığı kon-
           trol eder. 3’e eşit olması halinde 11 numaralı satır çalışr; aksi takdirde 12 numaralı satırdaki ELSE
           ifadesine gelir. PL/SQL’de CASE yapısında ELSE ifadesi C# ve Java’daki switch ifadesindeki
           default gibi çalışır. Eğer ELSE’ten önce gelen WHEN ifadelerinin hiçbirinde true oluşmazsa ELSE
           bloğu çalışır. WHEN bloklarının sonunda C# ve Java’daki break ifadesinin yerine kullanılması
           gereken herhangi bir ifade yoktur.

           Uygulama 5’teki yapıyı IF-ELSIF-ELSE ile kurmak daha doğru olacaktır. Uygulama 3’deki gibi
           bir IF yapısını CASE ile yazmak istersek PL/SQL bu konuda bize esneklik sağlamaktadır.
                                                                    Oracle Üzerinde Programlama ve PL/SQL   195



Uygulama 6: PL/SQL’de CASE Örneği 2

       DECLARE
      1	
      2		       	       UrunSayisi	INTEGER;
       	
      3	        BEGIN
       	
      4	        	       SELECT
       	
      5	        	       	        COUNT(*)	INTO	UrunSayisi
       	
      6	        	       	        FROM	Urun;
       	
      7	        	       CASE	TRUE
       	
      8	        	       WHEN	UrunSayisi	<	2	THEN
       	
      9	     	     	             DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	‘’’’	
      ||	‘den	az...’);
      10	       	       	        WHEN	UrunSayisi	>	2	THEN
      11	    	     	     	     DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	
      ‘’’’	||	‘den	fazla...’);
      12	       	       	        ELSE
      13	       	       	        	       DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘);
      14	       	       	        END	CASE;
      15	       	       END;

Uygulama 6’da 7 numaralı satır her durumda çalışacaktır. 8 numaralı satırda UrunSayiside-
ğişkeninin değerinin 2’den küçük olup olmadığı kontrol edilir. Eğer 2’den küçükse 9 numaralı satır
çalışır; aksi takdirde 10 numaralı satırda UrunSayisi değişkeninin değerinin 2’den büyük olup
olmadığı kontrol edilir. Eğer 2’den büyükse 11 numaralı satır çalışır; aksi takdirde 12 numaralı
satırdaki ELSE ifadesi çalışır. Bu noktadan sonraki çalışma Uygulama 5’teki ELSE bloğu ile aynı
şekildedir.

Uygulama 6’daki örneğe benzer olarak CASE ifadesinini farklı bir kullanımı daha vardır. CASE’in
bu kullanımı esnekliği daha da artırır ve özellikle karmaşık mantıksal işlemler için idealdir.

Uygulama 7: PL/SQL’de CASE Örneği 3

       DECLARE
      1	
      2	UrunSayisi	INTEGER;
       	UrunSayisiB	INTEGER;
      3	
       	BEGIN
      4	
       	SELECT
      5	
       	COUNT(*)	INTO	UrunSayisi
      6	
       	FROM	Urun;
      7	
       	SELECT
      8	
       	COUNT(*)	INTO	UrunSayisi
      9	
      10	FROM	Urun
      11	WHERE	UrunAdi	LIKE	‘B%’;
      12	CASE
      13	WHEN	UrunSayisi	<	2	AND	UrunSayisiB	=	1	THEN
      14	DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	‘’’’	||	‘den	az...’);
      15	WHEN	UrunSayisi	>	2	AND	UrunSayisiB	<	1	THEN
196   Bölüm 11



                  16	    	     	     	     DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘	||	
                  ‘’’’	||	‘den	fazla...’);
                  17	           	           	           ELSE
                  18	           	           	           	           DBMS_OUTPUT.PUT_LINE(‘Urun	Sayisi	2‘);
                  19	           	           	           END	CASE;
                  20	           	           END;

           Uygulama 7’de 12 numaralı satırdaki CASE ifadesi ne olursa olsun çalışacaktır ve CASE ile 1’den
           fazla sayıda değişken kontrol edilebilecektir.

           Şu ana kadar yaptığımız örnekleri TOAD yerine SQL Plus ile yapmak istediğinizde yazarken dik-
           kat etmeniz gereken birkaç nokta vardır. DBMS_OUTPUT.PUT_LINE fonksiyonunun çalışması için
           SET SERVEROUTPUT ON ifadesini bir kere çalıştırmalısınız. Bu ifadeyi Microsoft SQL Server’daki
           direktiflere benzetebilirsiniz. SET SERVEROUTPUT ON ifadesi TOAD’daki View menüsündeki
           DBMS Output öğesinin açılması işlevini görür. SET SERVEROUTPUT ON ifadesini çalıştırdıktan
           sonra PL/SQL bloğunu yazabiliriz. Bloğun sonunda “/” işaretini kullandığımızda yazdığımız blok
           çalışacaktır. Şekil 11’de SQL Plus ile PL/SQL bloklarının nasıl çalıştırıldığına yönelik ekran çık-
           tısını görebilirsiniz.




                 Şekil 11: SQL Plus ile PL/SQL bloklarının çalıştırılması.



           PL/SQL’de Değişkenler
           PL/SQL’de veri tipleri 4 ana gruba ayrılır. Bu gruplar:

           1� Basit (skaler) Tipler: T-SQL’deki basit tiplere ya da Java ve C#’taki değer tipli değişkenlere
              benzetilebilir. Herhangi bir anda doğrudan tek değer taşırlar, bellekte doğrudan tutulurlar.
           2. Bütünleşik (kompozit) Tipler: Dizi gibi kendi içinde tek tek işlenebilecek, T-SQL’de eksikli-
              ğini hissettiğimiz tiplerdir. Java ve C#’taki dizilere benzetebiliriz; ancak Java ve C#’ta dizilerin
              referans tipli olduğunu unutmamak gerekir.
           3� Referans Tipleri: Bir işaretçi (pointer) aracılığıyla taşıdığı değerlere erişilebilen tiplerdir. T-
              SQL’de doğrudan karşılığı yoktur. Java ve C#’taki referans tipli değişkenlerle benzer mantıkta
              çalışırlar.
           4. LOB (Large Object) Tipleri: Şekil, metin gibi büyük verileri tutmak için geliştirilmiş tiplerdir. T-
              SQL’deki text, image gibi düşünülebilir. Özünde referans tipli yapılara çok benzerdirler; çünkü
              taşıdıkları değer resmin ya da metnin başlangıcını gösteren bir işaretçidir.
                                                                    Oracle Üzerinde Programlama ve PL/SQL   197



PL/SQL’de bir değişkeni tanımlarken önce değişkenin adını sonra da tipini yazarız.

        DECLARE <değişken adı> <tip adı>;

Herhangi bir değişkene değer ataması yaparken “:=” işaretini kullanırız.

        <değişken adı> := <değer>

 BASİT TİPLER                BÜTÜNLEŞİK TİPLER        REFERANS TİPLERİ        LOB TİPLERİ
 BINARY_DOUBLE               RECORD                   REF CURSOR              BFILE
 BINARY_FLOAT                TABLE                    REF object_type         BLOB
 BINARY_INTEGER              VARRAY                                           CLOB
 DEC                                                                          NCLOB
 DECIMAL
 DOUBLE PRECISION
 FLOAT
 INT
 INTEGER
 NATURAL
 NATURALN
 NUMBER
 NUMERIC
 PLS_INTEGER
 POSITIVE
 POSITIVEN
 REAL
 SIGNTYPE
 SMALLINT
 CHAR
 CAHARACTER
 LONG
 LONG RAW
 NCHAR
 NVARCHAR2
 RAW
 ROWID
 STRING
 UROWID
 VARCHAR
 VARCHAR2
 BOOLEAN
 DATE
 TIMESTAMP
198   Bölüm 11




           PL/SQL’de Sayısal Tipler
           Sayısal tipler adlarından anlaşılabileceği gibi matematiksel işlemlerde kullanılabilecek tiplerdir.
           Tam sayıları, reel ve ondalıklı sayıları tutabileceğiniz pek çok tip PL/SQL’de mevcuttur.

           BINARY_INTEGER
           32 bitlik (4 byte) işaretli (signed), tam sayısal tiptir. -231 ile 231 – 1 aralığında değerleri tutar. PLS_
           INTEGER tipine benzer bir tiptir. NUMBER tipine göre işlem performanı avantajı vardır ve NUMBER
           tipine göre daha az yer kaplar.

           NATURAL, NATURALN, POSITIVE, POSITIVEN, SIGNTYPE tipleri BINARY_INTEGER tipinin alt
           tipleridir.

           NATURALvePOSITIVE tipleri sadece pozitif sayıları taşırlar. Dolayısıyla işaretsiz tiplerdir diye-
           biliriz. NATURAL tipinin POSITIVE tipinden tek farkı 0 (sıfır) değerini de alabilmesidir. NATURALN
           vePOSITIVEN tiplerinin NATURALvePOSITIVE tiplerinden tek farkı null değer taşıyamamala-
           rıdır. NATURAL, POSITIVE, NATURALN ve POSITIVEN tiplerinin taşıyabileceği en büyük değer
           231 – 1’dir. SIGNTYPE ise sadece -1, 0 ve 1 değerlerini taşıyabilir.

           Örnek 1: BINARY_INTEGER Tanımlama

                   DECLARE
                  1	
                  2		        	        bix	BINARY_INTEGER;
                   	
                  3	         nx	NATURAL;
                   	
                  4	         nnx	NATURALN;
                   	
                  5	         px	POSITIVE;
                   	
                  6	         pnx	POSITIVEN;
                   	
                  7	         stx	SIGNTYPE;
                   BEGIN
                  8	
                   	
                  9	         bix	:=	-55;
                  10	        	        nx	:=	null;
                  11	        	        nnx	:=	0;
                  12	        	        px	:=	7;
                  13	        	        pnx	:=	88;
                  14	        	        stx	=	-1;
                  15	        END;

           BINARY_FLOAT ve BINARY_DOUBLE
           Java ve C#’taki IEEE 754 standardındaki ondalıklı tiplerdir. BINARY_FLOAT bir değer sonuna
           eklenen ‘f’ harfiyle (1.004f), BINARY_DOUBLE bir değer sonuna eklenen ‘d’ harfiyle (3,05478d)
           ayrıştırılır.

           Örnek 2: BINARY_FLOAT ve BINARY_DOUBLE Tanımlama

                   DECLARE
                  1	
                  2		        	        bfx	BINARY_FLOAT;
                   	
                  3	         bdx	BINARY_DOUBLE;
                   BEGIN
                  4	
                   	
                  5	         bfx	:=	10.054f;
                   	
                  6	         bdx	:=	10.054d;
                   	
                  7	         IF	bfx	=	bdx
                                                                       Oracle Üzerinde Programlama ve PL/SQL   199



       	
      8	         THEN
       	
      9	         	       DBMS_OUTPUT.PUT_LINE(‘Esit’);
      10	        	       ELSE
      11	        	       	        DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
      12	        	       END	IF;
      13	        END;

Örnek 2’deki 7 numaralı satırdaki kontrolden FALSE sonucu çıkacaktır. Bu sebeple akış 8 nu-
maralı satırdan değil 10 numaralı satırdan devam edecektir ve DBMS Output penceresine “Esit
degil” yazacaktır.

NUMBER
PL/SQL’deki en genel sayısal tiptir. Hem tam sayıları hem de ondalıklı sayıları tutabilir. Değer
aralığı 1E-130 ile 10E125’tir. NUMBER tipinde bir değişkeni sadece NUMBER olarak tanımlaya-
bileceğimiz gibi hassasiyet (precission) ve ölçek (scale) değerleriyle birlikte de tanımlayabiliriz.
Hassasiyet sayının toplam hane (dijit) sayısıdır, ölçek ise noktadan sonraki hane sayısıdır. Do-
layısıyla hassasiyet için yazdığımız değer mutlaka ölçek için yazdığımız değerden büyük olmak
zorundadır. NUMBER tipinde bir değişkeni sadece hassasiyet değeri ile de tanımlayabiliriz. Bunun
anlamı ölçek değerinin yani ondalık hane sayısının 0 (sıfır) olmasıdır. En fazla 38 hanelik hassa-
siyet değeri ile tanımlanabilirken ölçek değeri -84 ile 127 arasında değişir. Ölçek değerinin negatif
olması tam sayının yuvarlanması anlamına gelir. Örneğin ölçek değeri -2 olan bir NUMBER değiş-
kene 257 değeri 200 olarak atanacaktır.

DEC, DECIMAL, DOUBLE PRECISION, FLOAT, INTEGER, INT, NUMERIC, REALveSMALLINT
tipleri NUMBER tipinin alt tipleridir.

DEC, DECIMALveNUMERIC tipleri NUMBER gibi tanımlanırken alabileceği en büyük ölçek değeri
38’dir.

DOUBLE PRECISION ve FLOAT tiplerinde ondalıklı kısım 126 bitte tutulur, bu da yaklaşık 38
ondalıklı haneye karşılık gelir.

REAL tipinde ondalıklı kısım 63 bit’te tutulur, bu da yaklaşık 18 ondalıklı haneye karşılık gelir.

INTEGER, INTveSMALLINT tiplerinde de en fazla hassasiyet seviyesi 38’dir. T-SQL’deki tam
sayısal tipler gibi düşünmek doğru değildir; çünkü PL/SQL’deki bu tiplerde ondalıklı kısım tanım-
lanabilir.

Örnek 3: NUMBER Tanımlama

       DECLARE
      1	
      2		        	       nx1	NUMBER;
       	
      3	         nx2	NUMBER(3);
       	
      4	         nx3	NUMBER(3,2);
       	
      5	         nx4	NUMBER(3,-1);
       	
      6	         ix1	INTEGER;
       	
      7	         ix2	INTEGER(3,1);
       	
      8	         dpx	DOUBLE	PRECISION;
       	
      9	         fx	FLOAT;
      10	        BEGIN
      11	        	       nx1	:=	10;
      12	        	       nx2	:=	267;
200   Bölüm 11



                 13	       	       nx3	:=	1.25;
                 14	       	       nx4	:=	254;
                 15	       	       ix1	:=	8;
                 16	       	       ix2	:=	4.7;
                 17	       	       dpx	:=	16.874;
                 18	       	       fx	:=	6.8;
                 19	       	       DBMS_OUTPUT.PUT_LINE(‘nx4	:	’	||	nx4);
                 20	       	       IF	fx	=	dpx
                 21	       	       THEN
                 22	       	       	        DBMS_OUTPUT.PUT_LINE(‘Esit’);
                 23	       	       ELSE
                 24	       	       	        DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
                 25	       	       END	IF;
                 26	       	       IF	nx4	=	250
                 27	       	       THEN
                 28	       	       	        DBMS_OUTPUT.PUT_LINE(‘nx4	=	250’);
                 29	       	       ELSE
                 30	       	       	        DBMS_OUTPUT.PUT_LINE(‘nx4	<>	250’);
                 31	       	       END	IF;
                 32	       END;

           Örnek 3’deki kodun DBMS çıktısı;

                 nx4	:	250
                 Esit
                 nx4	=	250

           şeklinde olacaktır. Bu örnekte nx4 değişkeninin tanımında ölçeğin -1 olmasından dolayı 254 de-
           ğeri 250’ye dönüştürülecektir. Eğer ölçek -2 olsaydı 200’e dönüştürülecekti. 20 numaralı satırdaki
           FLOAT tipinde bir değişkenle DOUBLE PRECISION tipinde bir değişkenin karşılaştırılmasında da
           bu tipler arasında bir önceki örnekte kullandığımız BINARY_FLOATveBINARY_DOUBLE tiplerin-
           den farklı olarak eşitlik olduğunu görebilirsiniz.

           PLS_INTEGER
           PLS_INTEGER tipinde de BINARY_INTEGER tipindeki gibi -231 ile 231 – 1 arasındaki tam sayılar
           tutulabilir. PLS_INTEGER tipi hem NUMBER tipinden hem de BINARY_INTEGER tipinden daha
           hızlı çalışır. Bunun NUMBERveBINARY_INTEGER işlemleri yazılımsal olarak yaparken PLS_IN-
           TEGER tipinin donanımsal olarak yapmasıdır.

           BINARY_INTEGER tipi eski versiyonlardan bu yana gelen bir tiptir. Eğer yeni bir uygulama geliş-
           tiriyorsanız PLS_INTEGER tipini kullanmak daha iyi olacaktır.

           Örnek 4: PLS_INTEGER Tanımlama

                  DECLARE
                 1	
                 2		       	       pix	PLS_INTEGER;
                  	
                 3	        bix	BINARY_INTEGER;
                  BEGIN
                 4	
                  	
                 5	        pix	:=	25;
                                                                     Oracle Üzerinde Programlama ve PL/SQL   201



        	
       6	       bix	:=	25;
        	
       7	       IF	pix	=	bix
        	
       8	       THEN
        	
       9	       	       DBMS_OUTPUT.PUT_LINE(‘Esit’);
       10	      	       ELSE
       11	      	       	        DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
       12	      	       END	IF;
       13	      END;

Örnek 4’ü çalıştırdığınızda PLS_INTEGER tipinde taşınan bir değerle BINARY_INTEGER tipinde
taşınan bir değer eğer aynıysa eşitlik sonucunu üreteceğini görebilirsiniz.

PL/SQL’de Alfanümerik Tipler
Alfanümerik tiplerde sayısal olarak yorumlanmayacak karakterler ve string tipler tutulur.

CHAR
Belli uzunlukta alfanümerik ifadeleri tutmak için kullanılır. En fazla uzunluğu 32767 karakterdir.
Eğer bir uzunluk tanımlanmazsa tek karakter tutar. CHARACTER veri tipini CHAR veri tipiyle aynı
şekilde kullanabilirsiniz.

Örnek 5: CHAR Tanımlama

        DECLARE
       1	
       2		      	       cx1	CHAR;
        	
       3	       cx2	CHAR;
        	
       4	       cx3	CHAR(4);
        	
       5	       cx4	CHARACTER;
        BEGIN
       6	
        	
       7	       cx1	:=	‘A’;
        	
       8	       cx2	:=	‘a’;
        	
       9	       cx3	:=	‘ABCD’;
       10	      	       cx4	:=	‘A’;
       11	      	       IF	cx1	=	cx2
       12	      	       THEN
       13	      	       	        DBMS_OUTPUT.PUT_LINE(‘Esit’);
       14	      	       ELSE
       15	      	       	        DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
       16	      	       END	IF;
       17	      	       IF	cx1	=	cx4
       18	      	       THEN
       19	      	       	        DBMS_OUTPUT.PUT_LINE(‘Esit’);
       20	      	       ELSE
       21	      	       	        DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
       22	      	       END	IF;
       23	      	       IF	cx1	=	SUBSTR(cx3,	1,	1)
       24	      	       THEN
       19	      	       	        DBMS_OUTPUT.PUT_LINE(‘Esit’);
202   Bölüm 11



                 20	        	        ELSE
                 21	        	        	       DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
                 22	        	        END	IF;
                 23	        END;

           Örnek 5’i çalıştırdığınızda şu şekilde bir DBMS çıktısı ile karşılaşırsınız:

                 Esit	degil
                 Esit
                 Esit

           Bu örneğin DBMS çıktısından anlaşılacağı gibi “A” harfi ve “a” harfi birbirine eşit değildir. 23
           numaralı satırda kullandığımız SUBSTR() fonksiyonu, adından da anlaşılabileceği gibi alfanü-
           merik bir yapıdan istediğimiz bir parçayı almak için kullanılır. SUBSTR fonksiyonunun kullanımı
           T-SQL’deki SUBSTRING() fonksiyonu gibidir. İlk argüman parça alınacak alfanümerik değer ya
           da değişkendir. İkinci argüman, bu değer ya da değişkenin kaçıncı karakterinden itibaren parça
           alınacağıdır. Üçüncü argüman, ikinci argümanda belirtilen karakter dahil olmak üzere kaç tane
           karakter alınacağını gösterir. Eğer üçüncü argüman girilmezse, ilk argümanda belirtilen değer ya
           da değişkenin, ikinci argümanda belirtilen karakterinden sonuna kadar tüm karakterleri alınır.

           LONG ve LONG RAW
           LONGveLONG RAW tipleri T-SQL’deki LONG tipinden çok farklıdır. PL/SQL’de LONGveLONG RAW
           32760 byte’a kadar alfanümerik değer tutar. Dolayısıyla VARCHAR2 tipine benzerdirler. LONG
           ve LONG RAW tipleri arasında veri tabanına INSERT ve SELECT ile yapılan işlemlerde ve veri
           tutma biçimlerinde farklılıkları vardır.

           Örnek 6: LONG ve LONG RAW Tanımlama

                  DECLARE
                 1	
                 2		        	        lx1	LONG;
                  	
                 3	         lrx1	LONG	RAW;
                  	
                 4	         lx2	LONG;
                  	
                 5	         lx3	LONG;
                  	
                 6	         lrx2	LONG	RAW;
                  	
                 7	         lx4	LONG(3);
                  	
                 8	         lrx3	LONG	RAW(3);
                  BEGIN
                 9	
                 10	        	        lx1	:=	‘ABC’;
                 11	        	        lrx1	:=	‘ABC’;
                 12	        	        lx3	:=	‘ABC’;
                 13	        	        lx4	:=	‘ABC’;
                 14	        	        lrx3	=	‘ABC’;
                 15	        	        IF	lx1	=	lrx1
                 16	        	        THEN
                 17	        	        	       DBMS_OUTPUT.PUT_LINE(‘Esit’);
                 18	        	        ELSE
                 19	        	        	       DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
                 20	        	        END	IF;
                 21	        	        lx2	:=	CONCAT(lx1,	lrx1);
                                                                     Oracle Üzerinde Programlama ve PL/SQL   203



      22	       	       DBMS_OUTPUT.PUT_LINE(lx2);
      23	       	       lx2	:=	CONCAT(lx1,	lx3);
      24	       	       DBMS_OUTPUT.PUT_LINE(lx2);
      25	       	       lrx2	:=	CONCAT(lx1,	lrx1);
      26	       	       DBMS_OUTPUT.PUT_LINE(lrx2);
      27	       END;

Örnek 6’yı çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      Esit	degil
      ABC0ABC
      ABCABC
      0ABC0ABC

15 numaralı satırda LONG tipindeki, tuttuğu değer “ABC” olan lx1 değişkeniyle LONG RAW tipin-
deki, tuttuğu değer “ABC” olan lrx1 değişkeni karşılaştırıldığında FALSE sonucu oluşur ve 18
numaralı satırdaki ELSE bloğuna düşer. Dolayısıyla LONGveLONG RAW değişkenleri doğrudan
karşılaştırmak istediğimiz sonucu üretmez. 21 numaralı satırda LONG tipindeki lx1ilelrx1de-
ğişkenlerini CONCAT() fonksiyonuyla birleştirip LONG tipindeki lx2 değişkenine atadık. 22 nu-
maralı satırda lx2 değişkeninin değerinin “ABC0ABC” olduğunu gördük. 23 numaralı satırda
LONG tipindeki lx2 değişkenine LONG tipindeki lx1velx3 değişkenlerinin birleştirilmesi sonucu
oluşan değeri atadık ve 24 numaralı satırda lx2 değişkenininin değerinin “ABCABC” olduğunu
gördük. Benzer şekilde 25 numaralı satırda bu sefer LONG RAW tipindeki lrx2 değişkeninin içine
LONG tipindeki lx1 ve LONG RAW tipindeki lrx1 değişkenlerinin birleştirilmesi sonucu oluşan
değeri atadık ve 26 numaralı satırda sonucun “0ABC0ABC” olduğunu gördük. Dolayısıyla LONG
tipindeki değişkenlerle LONG RAW tipindeki değişkenleri bir arada kullanırken dikkatli olmakta
fayda vardır.

Örnek 7: LONG ve LONG RAW Tiplerinin CHAR ile Karşılaştırılması

       DECLARE
      1	
      2		       	       lx1	LONG(3);
       	
      3	        lrx1	LONG	RAW(3);
       	
      4	        cx1	CHAR(3);
       BEGIN
      5	
       	
      6	        lx1	:=	‘ABC’;
       	
      7	        lrx1	:=	‘ABC’;
       	
      8	        cx1	:=	‘ABC’;
       	
      9	        IF	lx1	=	lrx1
      10	       	       THEN
      11	       	       	        DBMS_OUTPUT.PUT_LINE(‘Esit’);
      12	       	       ELSE
      13	       	       	        DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
      14	       	       END	IF;
      15	       	       IF	lx1	=	cx1
      16	       	       THEN
      17	       	       	        DBMS_OUTPUT.PUT_LINE(‘Esit’);
      18	       	       ELSE
      19	       	       	        DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
204   Bölüm 11



                 20	        	       END	IF;
                 21	        	       IF	cx1	=	lrx1
                 22	        	       THEN
                 23	        	       	        DBMS_OUTPUT.PUT_LINE(‘Esit’);
                 24	        	       ELSE
                 25	        	       	        DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
                 26	        	       END	IF;
                 27	        END;

           Örnek 7’yi çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

                 Esit	degil
                 Esit
                 Esit	degil

           Bu örnekten de anlaşılabileceği gibi CHAR tipindeki verilerle LONG tipindeki veriler karşılaştırılabi-
           lirken LONG RAW tipindeki verilerin doğrudan karşılaştırılması istediğimiz sonuçları vermeyebilir.

           ROWID ve UROWID
           T-SQL’de olmayan tiplerdir. ROWIDveUROWID herhangi bir tablodaki kaydın yeri hakkında bilgi
           tutarlar. Bu bilgi fiziksel ve mantıksal olmak üzere 2 şekildedir. Fiziksel rowid herhangi bir tabloda
           satır için ayırdedici bir özelliktir. Mantıksal rowid üzerinde index olan bir tablo için ayırdedicidir.
           UROWID hem fiziksel hem de mantıksal rowid tutabilir. Eğer yeni bir uygulama yazıyorsanız ve
           bu tip bir veriye ihtiyacınız varsa UROWID tipini tercih etmek daha iyi olacaktır. Örneğin ROWIDve
           UROWID tiplerini tüm değerleri aynı olan 2 satırdan birini silerken kullanabilirsiniz.

           Örnek 8: ROWID ve UROWID Tipleri

                  DECLARE
                 1	
                 2		        	       rx1	ROWID;
                  	
                 3	         urx1	UROWID;
                  BEGIN
                 4	
                  	
                 6	         SELECT
                  	
                 7	         	       rowid
                  	
                 8	         	       INTO	rx1
                  	
                 9	         	       FROM	Urun
                 10	        	       	        WHERE	UrunId	=	2;
                 11	        	       SELECT
                 12	        	       	        rowid
                 13	        	       	        INTO	urx1
                 14	        	       	        FROM	Urun
                 15	        	       	        WHERE	UrunId	=	2;
                 16	        	       DBMS_OUTPUT.PUT_LINE(rx1);
                 17	        	       DBMS_OUTPUT.PUT_LINE(urx1);
                 18	        	       IF	rx1	=	urx1
                 19	        	       THEN
                 20	        	       	        DBMS_OUTPUT.PUT_LINE(‘Esit’);
                 21	        	       ELSE
                                                                       Oracle Üzerinde Programlama ve PL/SQL   205



      22	        	       	        DBMS_OUTPUT.PUT_LINE(‘Esit	degil’);
      23	        	       END	IF;
      24	        END;

Örnek 8’i çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      AAAM2eAABAAAO5aAAD
      AAAM2eAABAAAO5aAAD	
      Esit

Bu örnekten ROWID tipindeki rx1veUROWID tipindeki urx1 değerlerinin esit olduğunu görebiliriz.
Bununla birlikte DBMS çıktısındaki “AAAM2eAABAAAO5aAAD” ifadeleri sizde farklı değerlerde
olacaktır. Bu karakter dizisi bir anlam taşır. İlk 6 karakter (örneğimizde “AAAM2e”) veri tabanı
segmentini ifade eder. Bu gruba nesne numarası (object number) denir. Sonraki 3 karakter (örne-
ğimizde “AAB”) satırın bulunduğu fiziksel dosyayı ifade eder. Bu gruba dosya numarası (file num-
ber) denir. Sonraki 6 karakter (örneğimizde “AAAO5a”) veri dosyasının içindeki bloğu ifade eder.
Aynı tablespace içinde olan fakat farklı veri dosyasında olan 2 satır aynı blok numarasına sahip
olabilir. Bu gruba blok numarası (block number) denir. Son 3 karakter de (örneğimizde “AAD”)
blok içindeki satır numarasını ifade eder. Bu gruba satır numarası (row number) denir.

Örnek 9: ROWID ve UROWID Tipleri

       DECLARE
      1	
      2		        	       rx1	ROWID;
       	
      3	         rx2	ROWID;
       BEGIN
      4	
       	
      6	         SELECT
       	
      7	         	       rowid
       	
      8	         	       INTO	rx1
       	
      9	         	       FROM	Urun
      10	        	       	        WHERE	UrunId	=	2;
      11	        	       SELECT
      12	        	       	        rowid
      13	        	       	        INTO	rx2
      14	        	       	        FROM	Urun
      15	        	       	        WHERE	UrunId	=	3;
      16	        	       DBMS_OUTPUT.PUT_LINE(rx1);
      17	        	       DBMS_OUTPUT.PUT_LINE(rx2);
      18	        END;

Örnek 9’u çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      AAAM2eAABAAAO5aAAD
      AAAM2eAABAAAO5aAAA

Bu çıktıdan Urun tablosundaki UrunId değerleri 2 ve 3 olan satırların aynı segment’te, aynı veri
dosyasında, aynı blok içindeki farklı yerlerde olduğunu görebiliriz.

VARCHAR2
Değişken uzunluklu alfanümerik verileri tutmak için kullanılır. Verinin VARCHAR2 tipinde nasıl tu-
tulduğu veri tabanının karakter setine göre değişiklik gösterir. En fazla 32767 karakter tutulabilir.
206   Bölüm 11



           2000 byte’tan uzun değerlerde performans düşüşü yükselir. Bu sebeple 2000 byte’tan daha uzun
           verileri tutarken bu durumu dikkate almakta fayda vardır.

           STRINGveVARCHAR veri tipleri VARCHAR2 veri tipinin alt tipleridir. VARCHARileVARCHAR2 veri
           tipleri aynıdır. VARCHAR veri tipinin varlık sebebi ileri sürümlerde farklı şekilde kullanılabilecek
           ayrılmış bir tip yaratmaktır. Bu sebeple VARCHAR2 veri tipini kullanmak daha iyi olacaktır.

           Örnek 10: VARCHAR2 Tipi ve Diğer Alfanümerik Tiplerle Karşılaştırma

                  DECLARE
                 1	
                 2		       	        vx1	VARCHAR2(10);
                  	
                 3	        cx1	CHAR(10);
                  	
                 4	        sx1	STRING(10);
                  	
                 5	        lx1	LONG(10);
                  BEGIN
                 6	
                  	
                 7	        vx1	:=	‘ABC’;
                  	
                 8	        cx1	:=	‘ABC’;
                  	
                 9	        sx1	:=	‘ABC’;
                 10	       	        lx1	:=	‘ABC’;
                 11	       	        IF	vx1	!=	cx1
                 12	       	        THEN
                 13	       	        	       DBMS_OUTPUT.PUT_LINE(‘vx1	!=	cx1’);
                 14	       	        ELSE
                 15	       	        	       DBMS_OUTPUT.PUT_LINE(‘vx1	=	cx1’);
                 16	       	        END	IF;
                 17	       	        IF	vx1	!=	sx1
                 18	       	        THEN
                 19	       	        	       DBMS_OUTPUT.PUT_LINE(‘vx1	!=	sx1’);
                 20	       	        ELSE
                 21	       	        	       DBMS_OUTPUT.PUT_LINE(‘vx1	=	sx1’);
                 22	       	        END	IF;
                 23	       	        IF	vx1	!=	lx1
                 24	       	        THEN
                 25	       	        	       DBMS_OUTPUT.PUT_LINE(‘vx1	!=	lx1’);
                 26	       	        ELSE
                 27	       	        	       DBMS_OUTPUT.PUT_LINE(‘vx1	=	lx1’);
                 28	       	        END	IF;
                 29	       END;

           Örnek 10’u çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

                 vx1	!=	cx1
                 vx1	=	sx1
                 vx1	=	lx1

           Bu örnekten görebileceğimiz gibi VARCHAR2 tipiyle CHAR tipini karşılaştırmak sakıncalıdır. Her ne
           kadar LONG tipiyle karşılaştırmak eşit sonucunu verse de LONG tipi ile VARCHAR2 tipinini kapasi-
           telerinin farklı olması sebebiyle bu tip bir karşılaştırmayı tercih etmemekte fayda vardır.
                                                                      Oracle Üzerinde Programlama ve PL/SQL   207




PL/SQL’de Mantıksal Tipler
PL/SQL’de 1 tane mantıksal tip bulunmaktadır. Bu tip BOOLEAN tipidir. Mantıksal bir tip TRUE ya
da FALSE değerlerinden birini tutar.

BOOLEAN
PL/SQL’de BOOLEAN veri tipi TRUE ya da FALSE değerlerini tutar; ancak dikkat edilmesi gereken
nokta BOOLEAN bir veri tipini DBMS_OUTPUT.PUT_LINE() fonksiyonu ile yazdıramayız.

Örnek 11: BOOLEAN Veri Tipi

        DECLARE
       1	
       2		      	        bx	BOOLEAN;
        BEGIN
       3	
        	
       4	       bx	:=	TRUE;
        	
       5	       IF	bx	=	TRUE
        	
       6	       THEN
        	
       7	       	        DBMS_OUTPUT.PUT_LINE(‘bx	=	TRUE’);
        	
       8	       ELSIF	bx	=	FALSE
        	
       9	       THEN
       10	      	        	       DBMS_OUTPUT.PUT_LINE(‘bx	=	FALSE’);
       11	      	        ELSE
       12	      	        	       DBMS_OUTPUT.PUT_LINE(‘bx	=	null’);
       13	      	        END	IF;
       14	      END;

Örnek 10’u çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

       bx	=	TRUE

Bu örnekte 10 numaralı satırdaki ELSE bloğunu eklemimizin sebebi eğer bx değişkeni tanımlan-
mazsa ya da bx değişkenine null değeri atanırsa 11 numaralı satırdaki ELSE bloğuna girilecek ve
DBMS çıktısı olarak “bx = null” yazılacaktır.

PL/SQL’de Tarih ve Zaman Tipleri
Tarih ve zaman tipleri herhangi bir tarihi ya da saati tutar. PL/SQL’de pek çok tarihsel gösterim
şekli olmasına rağmen bu tipleri temel olarak inceleyeceğiz.

DATE
DATE veri tipi Saniye detayında tarih ve zaman verisi tutar.

Örnek 12: DATE Veri Tipi

        DECLARE
       1	
       2		      	        dx	DATE;
        BEGIN
       3	
        	
       4	       dx	:=	SYSDATE;
        	
       5	       DBMS_OUTPUT.PUT_LINE(dx);
        END;
       6	

Örnek 12’yi çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

       02-DEC-07
208   Bölüm 11



           SYSDATE() fonksiyonu T-SQL’deki GETDATE() fonksiyonuna karşılık gelmektedir ve sistem ta-
           rih ve zamanını getirir. Bu noktadan itibaren INTERVAL yapısına geçebiliriz.

           Örnek 13: INTERVAL YEAR TO MONTH

                  DECLARE
                 1	
                 2		       	       BaslangicTarihi	DATE;
                  	
                 3	        BitisTarihi	DATE;
                  	
                 4	        ix	INTERVAL	YEAR(3)	TO	MONTH;
                  	
                 5	        cYilFarki	CHAR(3);
                  	
                 6	        cAyFarki	CHAR(2);
                  	
                 7	        iYilFarki	INT;
                  	
                 8	        iAyFarki	INT;
                  BEGIN
                 7	
                  	
                 8	        BaslangicTarihi	:=	’01-JAN-00’;
                  	
                 9	        BitisTarihi	:=	SYSDATE;
                 10	    	     DBMS_OUTPUT.PUT_LINE(‘Gun	Farki:	’	||	TO_
                 CHAR(BitisTarihi	-	BaslangicTarihi));
                 11	       	       iYilFarki	:=	FLOOR((BitisTarihi	-	BaslangicTarihi)	/	
                 365);
                 12	       	       cYilFarki	:=	TO_CHAR(iYilFarki);
                 13	    	     iAyFarki	:=	FLOOR(((BitisTarihi	-	BaslangicTarihi)	
                 –	iYilFarki	*	365)	/	30);
                 14	       	       cAyFarki	:=	TO_CHAR(iAyFarki);
                 15	    	     ix	:=	CONCAT(CONCAT(TRIM(iYilFarki),	‘-‘),	
                 TRIM(iAyFarki));
                 16	       	       DBMS_OUTPUT.PUT_LINE(ix);
                 17	       END;

           Örnek 13’ü çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

                 Gun	Farki:	2892
                 +007-11

           Bu örnekten görebileceğimiz gibi uygulamanın çalıştığı tarih (2 Aralık 2007) ile 1 Ocak 2000 tarihi
           arasında 2892 gün vardır. 2892 gün de 7 yıl 11 aya karşılık gelmektedir. Bu örnekte TO_CHAR()
           fonksiyonu herhangi bir tipi CHAR tipine çeviren fonksiyondur. BOOLEAN tipini CHAR tipine çevire-
           mez. TO_CHAR() fonksiyonunu T-SQL’deki CONVERT() fonksiyonunun özelleşmiş bir hali olarak
           düşünebiliriz. FLOOR() fonksiyonu burada, ondalıklı sayının ondalıklı kısmını atarak tam sayı
           kısmını almamızı sağlar. Bu örnekten de görebileceğiniz gibi INTERVAL YEAR TO MONTH tipine
           CHAR tipinde YIL-AY değerini alabilmektedir.

           Örnek 14: INTERVAL YEAR TO MONTH

                  DECLARE
                 1	
                  	
                 2	        ix1	INTERVAL	YEAR(3)	TO	MONTH;
                  	
                 3	        ix2	INTERVAL	YEAR(3)	TO	MONTH;
                  	
                 4	        ix3	INTERVAL	YEAR(3)	TO	MONTH;
                  	
                 5	        ix4	INTERVAL	YEAR(3)	TO	MONTH;
                  	
                 6	        dx	DATE;
                                                                     Oracle Üzerinde Programlama ve PL/SQL   209



         BEGIN
        7	
         	
        8	        ix1	:=	INTERVAL	’10-7’	YEAR	TO	MONTH;
         	
        9	        ix2	:=	INTERVAL	’10’	YEAR;
        10	       	      ix3	:=	INTERVAL	’7’	MONTH;
        11	       	      ix4	:=	ix2	+	ix3;
        12	       	      DBMS_OUTPUT.PUT_LINE(ix4);
        13	       	      dx	:=	SYSDATE;
        14	       	      dx	:=	dx	+	ix4;
        15	       	      DBMS_OUTPUT.PUT_LINE(dx);
        12	       END;

Örnek 14’ü çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

        +010-07
        02-JUL-18

Bu örnekten görülebileceği gibi 11 numaralı satırda 2 INTERVAL YEAR TO MONTH toplanabil-
mektedir. 14 numaralı satırda da INTERVAL YEAR TO MONTH tipinin DATE tipiyle toplanabildiğini
görüyoruz. Bu örnekteki INTERVAL YEAR TO MONTH tipindeki değişkenler tanımlanırken YEAR
ifadesinin yanındaki 3 rakamı en fazla 3 haneli yıl değeri taşıyabileceğini gösterir ve en fazla 4
olabilir.

Benzer şekilde kullanabileceğimiz INTERVAL DAY TO SECOND tipi de mevcuttur.

DATE ve INTERVAL İşlemleri
 1. Argüman              İşlem                  2. Argüman              Sonuç Tipi
 DATE                    +                      INTERVAL                DATE
 DATE                    -                      INTERVAL                DATE
 INTERVAL                +                      DATE                    DATE
 DATE                    -                      DATE                    INTERVAL
 INTERVAL                +                      INTERVAL                INTERVAL
 INTERVAL                -                      INTERVAL                INTERVAL
 INTERVAL                *                      NUMERIC                 INTERVAL
 NUMERIC                 *                      INTERVAL                INTERVAL
 INTERVAL                /                      NUMERIC                 INTERVAL


TIMESTAMP
TIMESTAMP veri tipi DATE veri tipinin bir varyasyonudur. DATE tipi gibi kullanılabilir.

Örnek 15: TIMESTAMP Veri Tipi

         DECLARE
        1	
        2		       	      tx	TIMESTAMP;
         BEGIN
        3	
         	
        4	        tx	:=	SYSDATE;
         	
        5	        DBMS_OUTPUT.PUT_LINE(tx);
         	
        6	        tx	:=	’05-JUL-07	10:42:35.313	PM’
         END;4
        7	
210   Bölüm 11



           Örnek 15’i çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

                 02-DEC-07	12.00.00.000000000

           6 numaralı satırdaki gibi TIMESTAMP tipine değer ataması yapılabilir.

           Bütünleşik Tipler
           Bütünleşik tipler herhangi bir basit tipten, referans tipinden ya da LOB tipinden türetilebilen dizi-
           lerdir.

           Örnek 16: VARRAY Veri Tipi

                  DECLARE
                 1	
                 2		        	        TYPE	PIXA	IS	VARRAY(4)	OF	PLS_INTEGER;
                  	
                 3	         px	PIXA;
                  BEGIN
                 4	
                  	
                 5	         px	:=	PIXA(0,	0,	0,	0);
                  	
                 6	         px(1)	:=	3;
                  	
                 7	         px(2)	:=	4;
                  	
                 8	         DBMS_OUTPUT.PUT_LINE(px(1));
                  	
                 9	         DBMS_OUTPUT.PUT_LINE(px(2));
                 10	        END;

           Örnek 16’yı çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

                 3
                 4

           Bu örnekte göreceğiniz gibi bir diziyi kullanmadan önce bir tip olarak tanımlamamız gerekmekte-
           dir. 2 numaralı satırda bu tanım yapılmaktadır. En genel şekilde tip tanımlaması şu şekildedir:

                 TYPE <yeni tip adı> IS VARRAY(<eleman sayısı>) OF <tip>

           Burada yeni tip adı oluşturduğumuz dizi tipine verdiğimiz addır, tip ise mevcut tiplerden biridir. Dizi
           indis değerleri 1’den başlar.

           Bu örnekte gördüğümüzün dışında bütünleşik tip tanımları da söz konusudur.

           Örnek 17: Bileşik Tipler

                  DECLARE
                 1	
                 2		        	        TYPE	TBLARRAY	IS	TABLE	OF	VARCHAR2(3);
                  	
                 3	     TYPE	TBLARRAY2	IS	TABLE	OF	PLS_INTEGER	INDEX	BY	PLS_
                 INTEGER;
                  	
                 4	     TYPE	TBLARRAY3	IS	TABLE	OF	PLS_INTEGER	INDEX	BY	
                 VARCHAR(3);
                  	
                 5	         tx1	TBLARRAY;
                  	
                 6	         tx2	TBLARRAY2;
                  	
                 7	         tx3	TBLARRAY3;
                  BEGIN
                 8	
                  	
                 9	         tx1	:=	TBLARRAY(‘’,	‘’,	‘’);
                 10	        	        tx1(1)	:=	‘ABC’;
                 11	        	        tx1(2)	:=	‘DEF’;
                                                                       Oracle Üzerinde Programlama ve PL/SQL   211



      12	        	       DBMS_OUTPUT.PUT_LINE(tx1(1));
      13	        	       DBMS_OUTPUT.PUT_LINE(tx1(2));
      14	        	       tx2(1)	:=	10;
      15	        	       tx2(2)	:=	15;
      16	        	       DBMS_OUTPUT.PUT_LINE(tx2(1));
      17	        	       DBMS_OUTPUT.PUT_LINE(tx2(2));
      18	        	       tx3(‘abc’)	:=	20;
      19	        	       tx3(‘def’)	:=	25;
      20	        	       DBMS_OUTPUT.PUT_LINE(tx3(‘abc’));
      21	        	       DBMS_OUTPUT.PUT_LINE(tx3(‘def’));
      22	        END;

Örnek 17’yi çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      ABC
      DEF
      10
      15
      20
      25

Bu örnekte göreceğiniz gibi PL/SQL, herhangi bir genel amaçlı programlama diline göre bile zen-
gin sayılabilecek seçenekler sunmaktadır. 2 numaralı satırda gördüğümüz tanımlama Örnek 16’ya
göre eleman sayısı tanımlamamaktadır. Böylece TBLARRAY tipinde tanımladığımız herhangi bir
değişkenin eleman sayısı sınır lı olmaktan çıkmıştır; ancak hala Örnek 16’daki gibi 9 numaralı sa-
tırda TBLARRAY tipinde tanımladığımız değişkene ilk değerlerini vermek durumundayız. TBLAR-
RAY tipi PLS_INTEGER tipindeki değerlerden oluşan bir dizi tipidir. 3 numaralı satırda, TBLARRAY
tipine göre oluşturduğumuz farklılık INDEX BY ifadesidir. INDEX BY ifadesi dizi tipini tanımlarken
indis değerlerinin hangi tipte olduğunu tanımlamaya yarar. TBLARRAY2 tipinde ilk PLS_INTEGER
ifadesi, TBLARRAY2 tipinden oluşturulacak bir değişkenin PLS_INTEGER tipinde değerler tuta-
cağını gösterirken, satırın sonundaki INDEX BY PLS_INTEGER ifadesi de değişkenin indis de-
ğerlerinin PLS_INTEGER ile gösterileceğini ifade eder. 14 ve 15 numaralı satırlarda gördüğünüz
gibi tx2 tipinin indisleri de değerleri de PLS_INTEGER tipindedir. Ayrıca bu tanımla artık dizinin ilk
değerlerini önceden vermek zorunluluğumuz ortadan kalktı. 4 numaralı satırdaki tip tanımında ise
3 numaralı satırdan sadece değişken indislerinin nasıl tutulacağı değişmiştir. TBLARRAY3 tipinde
tanımlanan bir dizinin indisleri VARCHAR2(3) tipinde olacaktır ve içinde PLS_INTEGER tipinde
değerler tutacaktır. Buna ait kullanımı da 18 ve 19 numaralı satırlarda görebilirsiniz. Herhangi bir
dizide dizinin ilk elemanına erişmek için FIRST, son elemanına erişmek için de LAST ifadelerini
kullanabiliriz. Bununla ilgili örneği Örnek 18’de görebilirsiniz:

Örnek 18: FIRST ve LAST

       DECLARE
      1	
      2		        	       TYPE	TBLARRAY	IS	TABLE	OF	VARCHAR2(3);
       	
      3	     TYPE	TBLARRAY2	IS	TABLE	OF	PLS_INTEGER	INDEX	BY	PLS_
      INTEGER;
       	
      4	     TYPE	TBLARRAY3	IS	TABLE	OF	PLS_INTEGER	INDEX	BY	
      VARCHAR(3);
       	
      5	         tx1	TBLARRAY;
       	
      6	         tx2	TBLARRAY2;
212   Bölüm 11



                  	
                 7	        tx3	TBLARRAY3;
                  BEGIN
                 8	
                  	
                 9	        tx1	:=	TBLARRAY(‘’,	‘’,	‘’);
                 10	       	        tx1(1)	:=	‘ABC’;
                 11	       	        tx1(2)	:=	‘DEF’;
                 12	       	        DBMS_OUTPUT.PUT_LINE(tx1(1));
                 13	       	        DBMS_OUTPUT.PUT_LINE(tx1(tx1.LAST));
                 14	       	        tx2(1)	:=	10;
                 15	       	        tx2(2)	:=	15;
                 16	       	        DBMS_OUTPUT.PUT_LINE(tx2(tx2.FIRST));
                 17	       	        DBMS_OUTPUT.PUT_LINE(tx2(2));
                 18	       	        tx3(‘abc’)	:=	20;
                 19	       	        tx3(‘def’)	:=	25;
                 20	       	        DBMS_OUTPUT.PUT_LINE(tx3(‘abc’));
                 21	       	        DBMS_OUTPUT.PUT_LINE(tx3(tx3.LAST));
                 22	       END;

           Örnek 18’i çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

                 ABC
                 10
                 15
                 20
                 25

           Bu örnekte 13 numaralı satırın çalışmasından sonucu oluşmaktadır; çünkü 9 numaralı satırda
           dizinin 3. elemanını olarak tanımladık.

           RECORD
           RECORD tipi T-SQL’de olmayan bir tiptir. C#’taki struct gibi düşünülebilir.

           Örnek 19: RECORD Tanımlama

                  DECLARE
                 1	
                 2		    	     TYPE	REC_URUN	IS	RECORD(ID	INTEGER,	AD	
                 VARCHAR2(10));
                  	
                 3	        rUrun	REC_URUN;
                  BEGIN
                 4	
                  	
                 5	        SELECT;
                  	
                 6	        	        UrunId,	UrunAdi
                  	
                 7	        	        INTO	rUrun
                  	
                 8	        	        FROM	Urun
                  	
                 9	        	        WHERE	ROWNUM	=	1;
                 10	    	     DBMS_OUTPUT.PUT_LINE(‘Urun	ID:	’	||	rUrun.ID	||	‘	
                 Adi:	’	||	rUrun.AD);
                 11	       END;
                                                                       Oracle Üzerinde Programlama ve PL/SQL   213



Örnek 19’u çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      Urun	ID:	1
      Adi:	Bisküvi

2 numaralı satırda INTEGER tipinde bir değer ve VARCHAR2 tipinde bir değer alan REC_URUN
adında bir RECORD oluşturduk. 3 numaralı satırda bu tipte bir değişken tanımladık. 5, 6, 7, 8 ve 9
numaralı satırlardan oluşan SELECT cümleciği ile rUrun değişkeninin içine IDveAD bilgileri ata-
dık. SELECT cümleciğinde T-SQL’de olmayan bir alan olan ROWNUM’ı kullanıdk. ROWNUM, SELECT
ifadesinin sonucunda oluşan kümenin sıra numarasını alan bir değerdir. Dolayısıyla ROWNUM =
1 olduğu için ilk satır verilerini RECORD’ın içine atmış durumdayız. 10 numaralı satırda da bu de-
ğerleri tek tek yazdırdık. RECORD, CURSOR ile birlikte kullanıldığında daha güçlü bir yapıyla karşı
karşıya kalacağız.

Referans Tipleri
Referans tipleri bir işaretçi aracılığıyla bellekte asıl veri bloğunun tutulduğu adresi gösteren veri
tipidir. Esnek tipler olışturabilmek açısından oldukça önemlidir.

REF CURSOR
REF CURSOR tipine geçmeden önce daha basit bir tip olan CURSOR tipinden bahsetmek gere-
kir. CURSOR tipi T-SQL’deki CURSOR’lara karşılık gelir; ancak kullanımında çok sayıda detay
vardır. Mantıksal olarak da T-SQL’deki CURSOR’larla aynı mantıkta çalışır.

Örnek 20: CURSOR Tanımlama

       DECLARE
      1	
      2		        	       CURSOR	curUrun	IS
       	
      3	         	       SELECT
       	
      4	         	       	        UrunId,	UrunAdi
       	
      5	         	       	        FROM	Urun;
       	
      6	         ID	INTEGER;
       	
      7	         AD	VARCHAR2(10);
       BEGIN
      8	
       	
      9	         OPEN	curUrun;
      10	        	       LOOP
      11	        	       	        FETCH	curUrun	INTO	ID,	AD;
      12	        	       	        EXIT	WHEN	NOT	curUrun%FOUND;
      13	        	       	        	       DBMS_OUTPUT.PUT_LINE(ID	||	‘	–	‘	||	AD);
      14	        	       END	LOOP;
      15	        	       CLOSE	curUrun;	           	
      16	        END;

Örnek 20’yi çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      1	-	Bisküvi
      2 - Çikolata

2, 3, 4 ve 5 numaralı satırlar CURSOR tanımını oluşturur. 3, 4 ve 5 numaralı satırlardaki SELECT
cümleciğinin sonucu curUrun adlı CURSOR içine satır satır atılacaktır; ancak bu işlem bu bölüm-
de yapılmaz. Burada sadece CURSOR için tanım mevcuttur. 9 numaralı satırda CURSOR açıldıktan
sonra, bir sonraki konuda işleyeceğimiz LOOP döngüsü içinde CURSOR tanımına göre satır satır
işleme yapılacaktır. 11 numaralı satırda ilk staır CURSOR değişkenleri olan IDveAD değişkenle-
214   Bölüm 11



           rine alınır. 12 numaralı satır LOOP döngüsünün curUrun içinde satır bulunamadığında çıkması
           için yazılmıştır. curUrun%FOUND ifadesi T-SQL’deki CURSOR için kullandığımız WHILE döngü-
           sündeki @@FETCH_STATUS != -1 ifadesi ile aynı şekilde çalışır. 13 numaralı satırda CURSOR
           değişkenleri DBMS çıktısı olarak yazılır. 15 numaralı satırda da CURSOR kapatılır. OPEN ile açılan
           bir CURSOR belleğin etkin kullanımı açısından mutlaka CLOSE ile kapatılmalıdır.

           Örnek 20: T-SQL’de CURSOR Tanımlama

                  DECLARE	@ID	INT,	@AD	VARCHAR(10)
                 1	
                 2		       DECLARE	curUrun	INSENSITIVE	CURSOR	FOR
                  	
                 3	        SELECT
                  	
                 4	        	       UrunId,	UrunAdi
                  	
                 5	        	       FROM	Urun
                  	
                 6	        OPEN	vurUrun
                  	
                 7	        FETCH	NEXT	FROM	curUrun	INTO	@ID,	@AD
                  	
                 8	        WHILE	@@FETCH_STATUS	!=	-1
                  	
                 9	        BEGIN
                 10	       	       	       PRINT	CONVERT(VARCHAR,	@ID)	+	‘	–	‘	+	@AD
                 11	       	       	       FETCH	NEXT	FROM	curUrun	INTO	ID,	AD
                 12	       	       END
                 13	       	       CLOSE	curUrun
                 14	       	       DEALLOCATE	curUrun

           Örnek 20.1’de Örnek 20’deki PL/SQL ile kullanılan CURSOR yapısnın T-SQL karşılığını görebi-
           lirsiniz.

           Örnek 21: CURSOR Değerlerinin RECORD İçine Atılması

                  DECLARE
                 1	
                  	
                 2	        TYPE	REC_URUN	IS	RECORD	(ID	INTEGER,	AD	VARCHAR2(10));
                  	
                 3	     TYPE	REC_URUN_ARR	IS	TABLE	OF	REC_URUN	INDEX	BY	PLS_
                 INTEGER;
                  	
                 4	        rUrun	REC_URUN;
                  	
                 5	        rUrunArr	REC_URUN_ARR;
                 6		       	       CURSOR	curUrun	IS
                  	
                 7	        	       SELECT
                  	
                 8	        	       	       UrunId,	UrunAdi
                  	
                 9	        	       	       FROM	Urun;
                 10	       	       ROWN	PLS_INTEGER;
                 11	       BEGIN
                 12	       	       OPEN	curUrun;
                 13	       	       ROWN	:=	1;
                 14	       	       LOOP
                 15	       	       	       FETCH	curUrun	INTO	rUrun;
                 16	       	       	       EXIT	WHEN	NOT	curUrun%FOUND;
                 17	       	       	       rUrunArr(ROWN)	:=	rUrun;
                 18	    	     	     DBMS_OUTPUT.PUT_LINE(rUrunArr(ROWN).ID	||	‘	
                 –	‘	||	rUrunArr(ROWN).AD);
                                                                      Oracle Üzerinde Programlama ve PL/SQL   215



      19	       	       END	LOOP;
      20	       	       CLOSE	curUrun;	          	
      21	       END;

Örnek 21’i çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      1	-	Bisküvi
      2 - Çikolata

2 numaralı satırda CURSOR için çalışan SELECT sorgusunun kayıt desenine uygun şekilde bir
RECORD oluşturduk. 3 numaralı satırda da CURSOR üzerinden REC_URUN tipindeki kayıtlarımızı
toplayacağımız değişken uzunluklu, PLS_INTEGER indisli, REC_URUN tipinde bir dizi tipi tanımla-
dık. 4 numaralı satırda CURSOR’dan dönen her satırı tutacağımız kayıt değişkenini tanımladık. 5
numaralı satırda da bu kayıt değişkenlerinin hepsini toplayacağımız diziyi tanımladık. 10 numaralı
satırda REC_URUN_ARR tipindeki dizinin indisini tutmak için PLS_INTEGER tipinde bir değişken
tanımladık. 13 numaralı satırda dizi indisleri 1’den başladığı için ROWN değerini 1 yaptık. 15 nu-
maralı satırda Örnek 20’ye göre farklı olarak CURSOR’dan dönen kaydı olduğu gibi REC_URUN ti-
pindeki rUrun adlı kayıt değişkenine atadık. 17 numaralı satırda da REC_URUN_ARR tipindeki rU-
runArr dizisinin ROWN numaralı indisindeki alana rUrun kaydını yerleştirdik. 18 numaralı satırda
rUrunArr(ROWN).IDverUrunArr(ROWN).AD ifadelerini rUrunArr dizisinin her elemanının
REC_URUN kayıt tipinde olmasından dolayı, kayıt deseninde tanımlı değişkenlerle kullanabildik.

Örnek 22: REF CURSOR Değerlerinin RECORD İçine Atılması

       DECLARE
      1	
       	
      2	        TYPE	REC_URUN	IS	RECORD	(ID	INTEGER,	AD	VARCHAR2(10));
       	
      3	        TYPE	URUN_CUR_TYPE	IS	REF	CURSOR	RETURN	REC_URUN;
       	
      4	        rUrun	REC_URUN;
       	
      5	        cUrunType	URUN_CUR_TYPE;
       BEGIN
      6	
       	
      7	        OPEN	cUrunType	FOR
       	
      8	        	       SELECT
       	
      9	        	       	        UrunId,	UrunAdi
      10	       	       	        	       FROM	Urun;
      11	       	       LOOP
      12	       	       	        FETCH	cUrunType	INTO	rUrun;
      13	       	       	        EXIT	WHEN	NOT	cUrunType%FOUND;
      14	    	          	        DBMS_OUTPUT.PUT_LINE(rUrun.ID	||	‘	–	‘	||	
      rUrun.AD);
      15	       	       END	LOOP;
      16	       	       CLOSE	cUrunType;	 	
      17	       END;

Örnek 22’yi çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      1	-	Bisküvi
      2 - Çikolata

2 numaralı satırda Örnek 21’deki gibi RECORD tipinde kayıt desenimizi tanımladık. 3 numaralı
satırda da REF CURSOR tipimizi tanımladık. 4 ve 5 numaralı satırlarda bu tiplere ait değişkenleri-
mizi oluşturduk. 7, 8, 9 ve 10 numaralı satırlarda URUN_CUR_TYPE adında REF CURSOR tipinde
216   Bölüm 11



           REC_URUN tipinde değer döndüren CURSOR yapımızı hem tanımladık, hem de açtık. Bu yapı T-
           SQL’deki CURSOR yapısına daha çok benzemektedir; ancak T-SQL’de RECORD yapısına benzer
           yapılar olmadığı için bu örneğin bire bir T-SQL karşılığı yoktur. 12 numaralı satırda oluşturduğu-
           muz REF CURSOR tipinin içindeki değeri REC_URUN tipinin içine yerleştirdik. 14 numaralı satırda
           da o satır için rUrun adlı kayıttaki IDveAD alanlarının değerlerini yazdırdık.

           LOB (Large Object) Tipleri
           Yapısal olmayan büyük verilerin tutulması için kullanışlı tiplerdir. En fazla tutabilecekleri veri mik-
           tarı 4GB’tır. Asıl verilerini işaretçi mantığıyla tutarlar.

           BFILE
           BFILE veri tipi, büyük verilerinin veri tabanı üzerinde değil işletim sisteminin üzerindeki dosya
           sistemi üzerinde tutulmasını sağlayan bir tiptir. BFILE aslında bu fiziksel dosyaya ait adresi tutar.
           BFILE tipindeki veri değiştirilemez. Kullanımı transaction mantığı çerçevesinde risklidir; çünkü
           transaction ile çalışan bir tip değildir ve transaction’a dahil edilmezler. Replikasyon ile replike
           edilemezler.

           BLOB (Binary Large Object)
           BLOB veri tipinin BFILE veri tipinden farkları, tuttuğu verinin veri tabanı dosyaları içinde tutulması
           ve transaction’a dahil olması ve replike edilebilir olmasıdır. BLOB veri tipinde veri binary olarak
           saklanır. Microsoft SQL Server 2005 ile birlikte gelen BLOB tipi gibidir.

           CLOB (Character Large Object)
           CLOB veri tipinin BLOB veri tipinden farkı tuttuğu verinin binary yerine alfanümerik olmasıdır. Diğer
           özellikleri BLOB tipi gibidir. Microsoft SQL Server 2005 ile birlikte gelen CLOB tipi gibidir.

           NCLOB
           NCLOB veri tipinin CLOB veri tipinden farkı NCHAR tipinden oluşmasıdır. Bunun anlamı yerel alfa-
           belerin de rahatlıkla kullanılabileceğidir.

           PL/SQL’de Döngü Yapıları
           LOOP Döngüsü
           LOOP döngüsü normalde koşulsuz bir döngü tipidir. EXIT ifadesi işletilene kadar döngü tekrarla-
           maya devam eder. LOOP ile CURSOR konusunda da örnek görmüştük.

           Örnek 23: LOOP Döngüsü

                    DECLARE
                   1	
                    	
                   2	       ix	PLS_INTEGER;
                    BEGIN
                   3	
                    	
                   4	       ix	:=	1;
                    	
                   5	       LOOP
                    	
                   6	       	        IF	ix	!=	5
                    	
                   7	       	        THEN
                    	
                   8	       	        	       ix	:=	ix	+	1;
                    	
                   9	       	        	       DBMS_OUTPUT.PUT_LINE(ix);
                   10	      	        	       ELSE
                   11	      	        	       	        EXIT;
                   12	      	        	       END	IF;
                   13	      	        END	LOOP;
                   14	      END;
                                                                     Oracle Üzerinde Programlama ve PL/SQL   217



Örnek 23’ü çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      2
      3
      4
      5

Bu örnekte dikkat etmemiz gereken en önemli nokta 4 numaralı satırda eğer ix değişkenine de-
ğer ataması yapmazsak 6 numaralı satırdaki karşılaştırmadan beklenmedik şekilde FALSE değeri
üretilmesidir. Bu sebeple LOOP döngü yapısını kullanırken kontrol değişkenine ilk değer ataması-
nı yapmak önemlidir. 5 ile 13 numaralı satırlar arasında tanımlanan LOOP döngüsünden çıkmak
için bu blok içinde kod akışında mutlaka EXIT ifadesinin çalışması gerekir; aksi takdirde sonsuz
döngü oluşacaktır. Örneğimizde eğer ix değişkeninin değeri 5’e eşit olursa 10 numaralı satırdaki
ELSE bloğu çalışır ve EXIT ifadesi de böylece çalışmış olur ve LOOP döngüsü sonlandırılarak
program akışı 13 numaralı satırdan itibaren devam eder.

EXIT WHEN İfadesi
LOOP döngüsünde koşullu çıkışı sağlamak için kullanılan bir ifadedir. IF bloğu yerine kullanıla-
bilir.

Örnek 24: LOOP Döngüsü ve EXIT WHEN İfadesi

       DECLARE
      1	
       	
      2	        ix	PLS_INTEGER;
       BEGIN
      3	
       	
      4	        ix	:=	1;
       	
      5	        LOOP
       	
      6	        	       EXIT	WHEN	ix	=	5;
       	
      7	        	       ix	:=	ix	+	1;
       	
      8	        END	LOOP;
       END;
      9	

Örnek 24’ü çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      2
      3
      4
      5

Bu örnekte LOOP döngüsü her döndüğünde 6 numaralı satırda EXIT WHEN ix = 5 ifadesiyle
karşılaşarak ix değerinin 5’e eşit olup olmadığını kontrol edecektir. Eğer ix 5’e eşitse EXIT ifa-
desi çalışacak ve program akışı 8 numaralı satırdan devam edecektir.

WHILE – LOOP Döngüsü
WHILE – LOOP döngüsü EXIT WHEN ifadesi ile kullanılan LOOP döngüsüne çok benzerdir. Bu
döngü tipinde WHILE ile tanımlanan koşul sağlandığı sürece döngü iterasyona devam eder.

Örnek 25: WHILE - LOOP Döngüsü

       DECLARE
      1	
       	
      2	        ix	PLS_INTEGER;
       BEGIN
      3	
218   Bölüm 11



                  	
                 4	        ix	:=	1;
                  	
                 5	        WHILE	ix	<	5
                  	
                 6	        LOOP
                  	
                 7	        	        ix	:=	ix	+	1;
                  	
                 8	        END	LOOP;
                  END;
                 9	

           Örnek 25’i çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

                 2
                 3
                 4
                 5

           Bu örnekte 5 numaralı satırdaki ix < 5 koşulu sağlandığı sürece program akışı 8 numaralı
           satıra gelmez. Dolayısıyla koşul sağlanana kadar kaç defa çalışacağını bilmediğimiz yapılarda
           kullanılması uygundur. EXIT ifadesinin olmaması sebebiyle koşullu çıkışın sağlanması semantik
           olarak sağlandığı için LOOP döngüsüne tercih edilmelidir. WHILE ifadesinin yanındaki koşulun
           tipi mutlaka BOOLEAN olmalıdır. 0 (sıfır) dışındaki tüm değerler TRUE, 0 (sıfır) FALSE’tur gibi bir
           durum söz konusu değildir.

           FOR – LOOP Döngüsü
           FOR – LOOP döngüsü de WHILE – LOOP döngüsüne benzer yapıdadır; ancak en önemli farkı
           koşula bağlı olmaktan çok iterasyon sayısının bilindiği yapılarda kullanılır. WHILE ile geçişken-
           dir.

           Örnek 26: FOR - LOOP Döngüsü

                  BEGIN
                 1	
                  	
                 2	        FOR	ix	IN	2..5
                  	
                 3	        LOOP
                  	
                 4	        	        DBMS_OUTPUT.PUT_LINE(ix);
                  	
                 5	        END	LOOP;
                  END;
                 6	

           Örnek 26’yı çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

                 2
                 3
                 4
                 5

           Bu örnekte WHILE – LOOP döngüsüne göre kontrol ettiğimizde DECLARE bölümünde bir değiş-
           ken tanımlamaya ihtiyacımız yoktur. 2 numaralı satırdaki FOR ix IN 2..5 ifadesi ile ix değiş-
           keni otomatikman tanımlanmış olur. 2 numaralı satırın anlamı, 2’den 5’e kadar olan sayıları her
           döngüde 1’er artırarak ix değişkenine atama yapmaktır.

           Örnek 27: FOR - LOOP Döngüsü

                  BEGIN
                 1	
                  	
                 2	        FOR	ix	IN	REVERSE	2..5
                  	
                 3	        LOOP
                                                                      Oracle Üzerinde Programlama ve PL/SQL   219



       	
      4	        	       DBMS_OUTPUT.PUT_LINE(ix);
       	
      5	        END	LOOP;
       END;
      6	

Örnek 27’yi çalıştırdığımızda aldığımız DBMS çıktısı şu şekildedir:

      5
      4
      3
      2

Bu örnekte 2 numaralı satırda IN ifadesinden sonra kullandığımız REVERSE ifadesi döngünün
2’den 5’e kadar 1’er artırarak değil, 5’ten 2’ye kadar 1’er eksilterek dönmesini sağlayacaktır ve
her seferinde ix değişkenine 5’ten itibaren 1’er eksilterek değer ataması yapacaktır.

Procedure Oluşturmak
PL/SQL’de procedure olışturmak T-SQL’den çok farklı değildir. PL/SQL’de Procedure’lar T-
SQL’deki SP (stored procedure)’ler gibi IN, OUT ve IN OUT yönlü parametrelere sahiptirler,
PL/SQL’deki procedure’larda RETURN yoktur, bunun yerine FUNCTION kullanılır.

Örnek 28: PL/SQL’de Procedure

       CREATE	OR	REPLACE	PROCEDURE	UrunYaz
      1	
       (
      2	
       	
      3	        ID	IN	PLS_INTEGER,
       	
      4	        AD	IN	VARCHAR2
       )
      5	
       AS
      6	
       	
      7	        RowCount	PLS_INTEGER;
       BEGIN
      8	
       	
      9	        SELECT
      10	       	       	        COUNT(*)	INTO	RowCount
      11	       	       	        FROM	Urun
      12	       	       	        WHERE	UrunId	=	ID;
      13	       	       IF	RowCount	=	0
      14	       	       THEN
      15	       	       	        INSERT	INTO	Urun(UrunId,	UrunAdi)	VALUES(ID,	
      AD);
      16	       	       END	IF;
      17	       END;

Örnek 28’deki kodu çalıştırdığınızda UrunYaz adında bir procedure SYSTEM schema’sı için login
olduğumuz veri tabanı üzerinde daha önceden yazılmamışsa yaratılacaktır, eğer daha önceden
varsa üstüne yazılacaktır. Bunu sağlayan 1 numaralı saturdaki CREATE OR REPLACE ifadesidir.
Bunun yerine sadece CREATE ya da REPLACE de kullanılabilir. 3 ve 4 numaralı satırlarda Urun-
Yaz procedure’ının argümanlarıdır. 3 numaralı satırda ID adında, PLS_INTEGER tipinde, IN yani
dışarıdan gelen bir argüman tanımlanmıştır. 4 numaralı satırda AD adında, VARCHAR2 tipinde, IN
yönünde diğer argüman tanımlanmıştır. 7 numaralı satırda procedure’ın içinde kullanacağımız
RowCount adında, PLS_INTEGER tipinde bir değişken aynı ID’ye sahip tabloda başka kayıt
olup olmadığını kontrol etmek amacıyla, satır sayısını tutmak üzere tanımlanmıştır. 9, 10, 11 ve
220   Bölüm 11



           12 numaralı satırlardali SELECT cümleciğiyle RowCount değerine UrunYaz procedure’ına ID
           argümanıyla gelen değere sahip UrunId’li alanların sayısı atanmıştır. 13 numaralı satırda eğer
           bu ID’ye sahip bir kayıt yoksa 15 numaralı satırdaki INSERT cümleciği çalışması için RowCount
           değişkeninin 0 olup olmadığı kontrol edilmektedir. Eğer RowCount 0 ise INSERT çalışır, aksi
           takdirde procedure sonlanır.

           Bu procedure’ı çalıştırmak için yazmamız gereken kod Örnek – 29’daki gibidir:

           Örnek 29: PL/SQL ile Procedure Çalıştırmak

                  DECLARE
                 1	
                  	
                 2	        IDx	PLS_INTEGER	:=	4;
                  	
                 3	        ADx	VARCHAR2(10)	:=	‘Gofret’;
                  BEGIN
                 4	
                  	
                 5	        UrunYaz(ID	=>	IDx,	AD	=>	ADx);
                  END;
                 6	

           Örnek 29’da 2 ve 3 numaralı satırlarda UrunYaz procedure’ına argüman olarak göndereceğimiz
           değerleri tanımladık. 5 numaralı satırda da UrunYaz procedure’ını bu değerlerle çalıştırdık.

           Örnek 30: PL/SQL ile OUT Parametreli Procedure

                  CREATE	OR	REPLACE	PROCEDURE	UrunYazOut
                 1	
                  (
                 2	
                  	
                 3	        ID	IN	PLS_INTEGER,
                  	
                 4	        AD	IN	VARCHAR2,
                  	
                 5	        EKLENDI	OUT	BOOLEAN
                  )
                 6	
                  AS
                 7	
                  	
                 8	        RowCount	PLS_INTEGER;
                  BEGIN
                 9	
                 10	       	       SELECT
                 11	       	       	       COUNT(*)	INTO	RowCount
                 12	       	       	       FROM	Urun
                 13	       	       	       WHERE	UrunId	=	ID;
                 14	       	       IF	RowCount	=	0
                 15	       	       THEN
                 16	       	       	       INSERT	INTO	Urun(UrunId,	UrunAdi)	VALUES(ID,	
                 AD);
                 17	       	       	       EKLENDI	:=	TRUE;
                 18	       	       ELSE
                 19	       	       	       EKLENDI	:=	FALSE;	
                 20	       	       END	IF;
                 21	       END;

           Örnek 30’da 5 numaralı satırda EKLENDI adında, BOOLEAN tipinde, OUT yönlü bir argüman ta-
           nımladık. Eğer 16 numaralı satırda INSERT işlemine gelinirse EKLENDI değeri TRUE olur; aksi
           takdirde FALSE olur. Örnek – 31’de de UrunYazOut procedure’ının nasıl çalıştırıldığını görebi-
           lirsiniz.
                                                                     Oracle Üzerinde Programlama ve PL/SQL   221



Örnek 31: PL/SQL ile Out Argümanlı Procedure Çalıştırmak

       DECLARE
      1	
       	
      2	        IDx	PLS_INTEGER	:=	4;
       	
      3	        ADx	VARCHAR2(10)	:=	‘Gofret’;
       	
      4	        DURUM	BOOLEAN;
       BEGIN
      5	
       	
      6	        UrunYazOut(ID	=>	IDx,	AD	=>	ADx,	EKLENDI	=>	DURUM);
       	
      7	        IF	DURUM	=	TRUE
       	
      8	        THEN
       	
      9	        	        DBMS_OUTPUT.PUT_LINE(‘Eklendi’);
      10	       	        ELSE
      11	       	        	       DBMS_OUTPUT.PUT_LINE(‘Eklenmedi’);
      12	       	        END	IF;
      13	       END;

Örnek 31’de 4 numaralı satırda UrunYazOut procedure’ından OUT parametre (argüman) yoluyla
gelecek değeri tutmak için bir BOOLEAN değişken oluşturduk. 6 numaralı satırda da IN yönlü ar-
gümanlar gibi OUT yönlü argümanımızı da oluşturduk. 7 numaralı satırdan itibaren IF bloğundan
DURUM değişkeninin değerine göre DBMS çıktısına ‘Eklendi’ ya da ‘Eklenmedi’ yazacaktır.

Fonksiyon Oluşturmak
PL/SQL’de fonksiyonlar T-SQL’deki fonksiyonlara çok benzer özellikler gösterir. IN, OUTveIN
OUT yönlü argümanlarla çalışırlar ve RETURN ifadesi ile bir değer döndürürler. C# ve Java’daki
dönmüş tipi void olmayan metotlar gibidir.

Örnek 32: PL/SQL’de Fonksiyon

       CREATE	OR	REPLACE	FUNCTION	UrunAdiOku
      1	
       (
      2	
       	
      3	        ID	IN	PLS_INTEGER
       )
      4	
       RETURN	VARCHAR2
      5	
       AS
      6	
       	
      7	        AD	VARCHAR2(10);
       BEGIN
      8	
       	
      9	        SELECT
      10	       	        	       UrunAdi	INTO	AD
      11	       	        	       FROM	Urun
      12	       	        	       WHERE	UrunId	=	ID;
      13	       	        RETURN	AD;
      14	       END;

Örnek 32’deki kodu çalıştırdığınızda UrunAdiOku adında fonksiyonumuz eğer daha önce yara-
tılmamışsa yaratılacaktır; aksi takdirde üstüne yazılacaktır. Procedure’lardaki gibi fonksiyonlarda
da CREATEveREPLACE ifadeleri tek başlarına kullanılabilir.
222   Bölüm 11



           Örnek 33: PL/SQL ile Fonksiyon Çalıştırmak

                  DECLARE
                 1	
                  	
                 2	        IDx	PLS_INTEGER	:=	4;
                  	
                 3	        ADx	VARCHAR2(10);
                  BEGIN
                 4	
                  	
                 5	        ADx	:=	UrunAdiOku(ID	=>	IDx);
                  	
                 6	        DBMS_OUTPUT.PUT_LINE(ADx);
                  END;
                 7	

           Örnek 33’de 3 numaralı satırda VARCHAR2(10) tipinde tanımalanan ADx isimli değişken Uru-
           nAdiOku fonksiyonundan dönen değeri tutacak değişkendir. 5 numaralı satırda ADx değişkenine
           UrunAdiOku fonksiyonundan dönen değerin ataması yapılmıştır. Bu atama sırasında tip uyumu
           çok önemlidir. Eğer uyumsuz tipler kullanırsanız istenmeyen sonuçlarla karşılaşabilirsiniz. 6 nu-
           maralı satırda da ADx değişkenine atanan fonksiyon dönüş değeri DBMS çıktısına yazdırılır.

				
DOCUMENT INFO
Shared By:
Tags: java
Stats:
views:70
posted:3/14/2012
language:Turkish
pages:228