+ Yüklə
Transkript
+ Yüklə
Java programming and practices Bilgisayar Mühendisi Okan Bilke JAVA DİLİYLE PROGRAMLAMA Part I © Okan Bilke Web Adresi: www.elektroarge.com Email: [email protected] Location: Türkiye Ders 1 - Java Diline Giriş ................................................................................ 9 Ders 2 - JDK Kurulumu ....................................................................... 15 Ders 3 - Eclipse Kurulumu ................................................................... 18 Ders 4 - Eclipse Ortamını Tanıyalım ..................................................... 19 Ders 5 - Java İle İlk Programımız ......................................................... 32 Ders 6 - Eclipse Üzerinde Debug İşlemleri ............................................. 40 Ders 7 - Paket (Package) Kavramı ........................................................ 45 Ders 8 - Değişkenler ve Veri Tiplerine Giriş........................................... 50 Ders 9 - Değişken Tanımlama Kuralları ................................................ 51 Ders 10 - Primitif Tipler ....................................................................... 53 Ders 11 - Referans Tipler...................................................................... 56 Ders 12 - Boxing ve Unboxing Kavramı ................................................ 62 Ders 13 - Lokal Değişkenler .................................................................. 62 Ders 14 - Sabit Tanımlama ................................................................... 65 Ders 15 - Tip Dönüşümleri.................................................................... 66 Ders 16 - Java'da Kullanılan Anahtar Kelimeler ................................... 71 Ders 17 - Operatörlere Giriş ................................................................. 71 Ders 18 - Atama Operatörleri ............................................................... 71 Ders 19 - İlişkisel Operatörler ............................................................... 76 Ders 20 - Aritmetik Operatörler ........................................................... 78 Ders 21 - Mantıksal Operatörler ........................................................... 83 Ders 22 - Bitsel Operatörler .................................................................. 86 Ders 23 - Tip Karşılaştırma Operatörü ................................................. 90 Ders 24 - Operatör Önceliği .................................................................. 90 Ders 25 - Kontrol Yapıları .................................................................... 92 Ders 26 - Döngüler ............................................................................. 102 Ders 27 - Break ve Continue İfadeleri.................................................. 114 Ders 28 - Metod Nedir? ...................................................................... 116 Ders 29 - Metod Oluşturma ................................................................ 117 Ders 30 - Parametresiz Metodlar ........................................................ 117 Ders 31 - Parametreli Metodlar .......................................................... 121 Ders 32 - Metodlara Dizi Türünden Parametre Geçirmek ................... 127 Ders 33 - Metodları Aşırı Yükleme (Overloading)................................ 131 Ders 34 - Metodlarda Özyineleme (Recursion) .................................... 134 Ders 35 - Static Metodlar .................................................................... 138 Ders 36 - Dizilere Giriş ....................................................................... 142 Ders 37 - Bir Dizinin Boyutu ............................................................... 149 Ders 38 - Dizileri Kopyalama .............................................................. 151 Ders 39 - Dizileri Sıralama.................................................................. 155 Ders 40 - Dizilerde Arama .................................................................. 156 Ders 41 - Dizileri Karşılaştırma........................................................... 158 Ders 42 - Çok Boyutlu Diziler ............................................................. 159 Ders 43 - String[] Args Dizisi............................................................... 166 Ders 44 - Arrays Sınıfı Metodları ........................................................ 171 Ders 45 - Scanner Sınıfına Giriş .......................................................... 176 Ders 46 - JOptionPane Kullanımı ....................................................... 186 Ders 47 - Nesneye Yönelik Programlamaya Giriş ................................ 196 Ders 48 - Sınıf ve Nesne Kavramları.................................................... 196 Ders 49 - Sınıf ve Nesne Değişkenleri ................................................... 203 Ders 50 - Pass By Value - Pass By Reference........................................ 207 Ders 51 - Yapıcılar (Constructor)........................................................ 211 Ders 52 - Kapsülleme (Encapsulation)................................................. 217 Ders 53 - This Anahtar Kelimesi ......................................................... 232 Ders 54 - Static Anahtar Kelimesi ....................................................... 235 Ders 55 - Enum Kavramı.................................................................... 239 Ders 56 - Annotation Kavramı ............................................................ 248 Ders 57 - Garbage Collector (Çöp Toplayıcı) ....................................... 252 Ders 58 - Kalıtım Kavramına Giriş ..................................................... 256 Ders 59 - Super Class ve Sub Class Kavramları ................................... 258 Ders 60 - Super Metodu ile Üst Sınıfın Yapıcısını Çağırmak ................ 263 Ders 61 - Metod Overriding................................................................ 268 Ders 62 - Final Anahtar Kelimesi ........................................................ 278 Ders 63 - Upcasting ve Downcasting Kavramları ................................. 284 Ders 64 - Soyut Sınıflar ve Metodlara Giriş ......................................... 291 Ders 65 - Soyut Sınıf ve Kalıtm Arasındaki İlişki ................................. 292 Ders 66 - Soyut Sınıf Örneği................................................................ 293 Ders 67 - Arayüz Kavramına Giriş ..................................................... 299 Ders 68 - Arayüz Örneği..................................................................... 301 Ders 69 - Arayüzlerde Genişletilme Özelliği......................................... 305 Ders 70 - Arayüz İçerisinde Başka Bir Arayüz Kulanma ..................... 308 Ders 71 - Dahili Sınıflara Giriş ............................................................ 310 Ders 72 - Dahili Üye Sınıflar ............................................................... 311 Ders 73 - Dahili Üye Sınıflar ve Erişim Belirteçleri............................... 313 Ders 74 - Yerel Sınıflar ....................................................................... 321 Ders 75 - İsimsiz Sınıflar ..................................................................... 323 Ders 76 - Çok Biçimlilik (Polimorfizm) Kavramına Giriş..................... 324 Ders 77 - Geç Bağlama ....................................................................... 330 Ders 78 - Instanceof İle Tip Kontrolü .................................................. 333 Ders 79 - Math Sınıfına Giriş .............................................................. 339 Ders 80 - Math.pow Metodu İle Sayının Üssünü Alma ......................... 339 Ders 81 - Math.sqrt Metodu İle Sayının Karekökünü Alma ................. 341 Ders 82 - Math.abs Metodu İle Sayının Mutlak Değerini Alma ............ 341 Ders 83 - Math.floor Metodu İle Sayıyı Alt Değere Yuvarlama ............ 342 Ders 84 - Math.ceil Metodu İle Sayıyı Üst Değere Yuvarlama .............. 344 Ders 85 - Math.max Metodu İle Büyük Sayıyı Bulma .......................... 344 Ders 86 - Math.min Metodu İle Küçük Sayıyı Bulma........................... 345 Ders 87 - Math.random Metodu İle Rastgele Sayı Üretme ................... 346 Ders 88 - Math.toDegrees Metodu İle Radyanı Dereceye Çevirme........ 354 Ders 89 - Math.toRadians Metodu İle Dereceyi Radyana Çevirme ....... 355 Ders 90 - Math.sin Metodu İle Sinüs Bulma ........................................ 356 Ders 91 - Math.asin Metodu İle Ters Sinüs Bulma ............................... 357 Ders 92 - Math.cos Metodu İle Cosinüs Bulma .................................... 357 Ders 93 - Math.acos İle Ters Cosinüs Bulma........................................ 358 Ders 94 - Math.PI İle Pi Sabitini Kullanma ......................................... 359 Ders 95 - Logaritma Metodları ........................................................... 360 Ders 96 - String Sınıfına Giriş ............................................................. 362 Ders 97 - String Nesnesinin Uzunluğu ................................................. 363 Ders 98 - Karakter Katarlarını Birleştirmek ....................................... 364 Ders 99 - String Nesnelerini Karşılaştırma .......................................... 366 Ders 100 - Karakter Metodları............................................................ 374 Ders 101 - String Düzenleme Metodları............................................... 380 Ders 102 - StringTokenizer ve StringBuffer Sınıfları............................ 385 Ders 103 - Exceptions (İstisnalar) ........................................................ 398 Ders 104 - Hata Yakalama (Try - Catch Blokları)................................ 398 Ders 105 - Finally Bloğu...................................................................... 407 Ders 106 - Finally Bloğunda Try - Catch Kullanımı ............................. 408 Ders 107 - Birden Fazla Hata Yakalama ............................................. 410 Ders 108 - Throw Anahtar Kelimesi.................................................... 412 Ders 109 - Throws Anahtar Kelimesi .................................................. 413 Ders 110 - Exception Türü Oluşturma ................................................ 419 Ders 111 - Hata Türleri ...................................................................... 422 Ders 112 - I/O Kavramına Giriş .......................................................... 424 Ders 113 - File Sınıfının Kullanımı ...................................................... 427 Ders 114 - FileReader İle Dosya Oluşturma ......................................... 434 Ders 115 - FileWriter İle Dosyaya Yazma............................................ 437 Ders 116 - FileInputStream İle Dosya Okuma ..................................... 441 Ders 117 - FileOutputStream İle Dosyaya Yazma ................................ 443 Ders 118 - BufferedReader İle Dosyadan Okuma ................................ 444 Ders 119 - BufferedWriter İle Dosyaya Yazma .................................... 447 Ders 120 - BufferedInputStream İle Dosya Okuma.............................. 448 Ders 121 - BufferedOutputStream ile Dosyaya Yazma......................... 450 Ders 122 - Scanner Sınıfı İle Dosya Okuma ......................................... 451 Ders 123 - Scanner Sınıfı Yapıcıları..................................................... 456 Ders 124 - Rastgele Erişimli Dosyalarda Okuma ve Yazma.................. 457 Ders 125 - Object Serialization (Nesne Serileştirme)............................. 462 Ders 126 - Koleksiyonlara Giriş .......................................................... 472 Ders 127 - Collection Arayüzü ............................................................ 473 Ders 128 - Iterator .............................................................................. 476 Ders 129 - Set (Kümeler) .................................................................... 477 Ders 130 - Liste Yapıları (List) ............................................................ 485 Ders 131 - LinkedList (Bağlı Liste)...................................................... 490 Ders 132 - Map Arayüzü .................................................................... 498 Ders 133 - Olay Yönetimine Giriş........................................................ 507 Ders 134 - Olay Sınıfları ..................................................................... 508 Ders 135 - Olay Dinleyicileri (Event Listeners)..................................... 521 Ders 136 - Fare ve Klavye Olay Metodlarının Kullanımı...................... 526 Ders 137 - GUI (Graphical User Interface) Nedir?............................... 530 Ders 138 - GUI Kurulumu .................................................................. 531 Ders 139 - GUI Projesi Oluşturma ...................................................... 533 Ders 140 - Swing ................................................................................ 538 Ders 141 - JFrame .............................................................................. 539 Ders 142 - Container .......................................................................... 542 Ders 143 - JLabel ............................................................................... 544 Ders 144 - JButton.............................................................................. 548 Ders 145 - JTextField ......................................................................... 552 Ders 146 - JComboBox....................................................................... 554 Ders 147 - JRadioButton .................................................................... 557 Ders 148 - JCheckBox ........................................................................ 560 Ders 149 - JToggleButton ................................................................... 563 Ders 150 - JTable ............................................................................... 565 Ders 151 - JList .................................................................................. 568 Ders 152 - JScrollPane........................................................................ 572 Ders 153 - JTabbedPane..................................................................... 574 Ders 154 - JTree ................................................................................. 577 Ders 155 - Layout (Yerleşim Düzenleri)............................................... 581 Ders 156 - Veritabanı Kavramına Giriş............................................... 587 Ders 157 - Veritabanı Yönetim Sistemleri (VTYS) ............................... 589 Ders 158 - JDBC Tanımı .................................................................... 589 Ders 159 - Temel SQL Komutları ....................................................... 591 Ders 160 - MySQL Kurulumu ............................................................ 594 Ders 161 - MySQL İçin JDBC Connector............................................ 596 Ders 162 - JDBC Bileşenleri................................................................ 599 Ders 163 - JDBC İle Veri Sorgulama................................................... 608 Ders 164 - JDBC İle Veritabanına Veri Ekleme ................................... 610 Ders 165 - JDBC İle Veritabanından Veri Silme .................................. 612 Ders 166 - JDBC İle Veritabanındaki Verileri Güncelleme .................. 614 Ders 167 - Navicat Kurulumu ............................................................. 615 Ders 168 - Navicat İle Örnek Uygulama .............................................. 617 Ders 169 - Thread Kavramına Giriş.................................................... 631 Ders 170 - Thread Oluşturma ............................................................. 631 Ders 171 - Thread'i Başlatmak ve Durdurmak .................................... 636 Ders 172 - Thread'i Beklemeye Almak ve Devam Ettirmek.................. 639 Ders 173 - Bir Thread Nesnesine Öncelik Atamak ............................... 641 Ders 174 - Thread'in Çalışıp Çalışmadığının Kontrolü ........................ 644 Ders 175 - MultiThreading ................................................................. 646 Ders 176 - Switch İçerisinde String İfadeleri Kıyaslama ....................... 649 Ders 177 - Sayılarda Altçizgi Kullanarak Sayıları Bölümleme .............. 651 Ders 178 - İkili Tabandaki Sayıları Değişkenlerde Tutma .................... 652 Ders 179 - Hata Yakalamada Yeni Catch Bloğu Sistemi ...................... 654 Ders 180 - Hata Yakalamada Finally Bloğunun Alternatifi .................. 656 Ders 181 - Elmas Operatör İçerisindeki Tanım Zorunluluğu ............... 658 Ders 182 - Safevarags İle Uyarı ve Hata Giderimi ................................ 658 Ders 1 - Java Diline Giriş JAVA DİLİNİN KISA TARİHİ Java, Sun Microsystems firmasının mühendislerinden James Gosling tarafından geliştirilmiş olup, yine Sun Microsystems tarafından 23 Mayıs 1995 yılında piyasaya sürülen, açık kaynak kodlu nesneye yönelik bir programlama dilidir. Java 1.0 ile başlayan serüven, günümüzde Java SE 7.0'a kadar gelmiştir. Kısıtlı özelliklere sahip olan Java 1.0 sürümünde büyük değişiklikler yaparak Java 1.2 çıkarılmıştır ve buna Platform 2 adı verilmiştir. Bu şekilde hızlı ilerlemeler kaydederek Java 7.0'a kadar gelinmiştir. Sun Microsystems, daha sonra Oracle tarafından satın alınmıştır. Java, platformdan bağımsız çalışma gereksinimi sonucunda ortaya çıkmıştır. Eskiden bir program, yazıldığı işletim sisteminin dışında başka bir işletim sistemi üzerinde çalışmıyordu. İleride göreceğimiz JVM sayesinde, artık Java ile yazılmış programlar, her işletim sistemi üzerinde çalışabilecek hale gelmiştir. Java dili, çoğu özelliğini C ve C++ dillerinden almıştır. Nesneye yönelik programlama kısmında C++'a yakındır. Syntax(söz dizimi) olarak ise C diline benzer. C dilini bilenler, Java'nın nesneye yönelik programlama kısmına kadar olan yerleri anlamakta zorluk çekmeyeceklerdir. Java'nın simgesi bilindiği üzere bir kahve fincanıdır. Bu dil ilk geliştirilmeye başlandığında adı Oak olarak belirlenmişti. Fakat bu isimde başka bir dil olduğu fark edilince, o anda bir kahvehanede bulunan Java geliştiricileri grubu, buradaki kahve markasından esinlenerek Java ismini vermişlerdir. JAVA DİLİNİN ÜSTÜNLÜKLERİ Java dilinin en önemli özelliği platformdan bağımsız çalışması, yüksek performanslı, güvenilir ve esnek bir dil olmasıdır. Java, temel olarak güvenliği ön planda tutar. Bu konuyu en önde tutan ilk dildir. Bunun yanında daha birçok özelliği ile Java, masaüstü bilgisayarlardan mobil aygıtlara, akıllı kartlardan oyun konsollarına, yazıcılardan tıbbi cihazlara kadar birçok yerde kullanılmaktadır. Java dili ile profesyonel yazılımlar geliştirildiği zaman bunun karşılığını tam olarak verir ve size yeteneklerini gösterir. Kurumsal uygulamalarda çok kullanılması, bunun en önemli göstergesidir. Diğer dillerin aksine Java dili, derlendikten sonra çıktı olarak byte code oluşturur. Daha sonra JVMsayesinde bu kodlar, yorumlanarak çalışır hale getirilir. Bu özellik Java'nın hem taşınabilir hem de platformdan bağımsız bir dil olmasını sağlamıştır. Bu özelliğe bir kere çalıştır her yerde kullan özelliği denir ve bu şekilde tanınır. Aynı zamanda Java, hem derlenen hem de yorumlanan bir dildir. Java dili ile ayrıca web uyumlu uygulamalar geliştirilebilir. JSP(Java Server Page), Servlet gibi web tabanlı uygulamalarda da kullanılır. JSP, sunucu tarafında çalışan dinamik web uygulamaları geliştirmeye yarayan bir dildir. Servlet ise yazılmış JSP sayfasının Java koduna dönüştürülmüş şeklidir. Java'nın çıkış tarihi ile internetin kendini göstermeye başlaması aynı döneme denk geldiği için Java, ağ sistemleri ile iç içedir. C++ diline yakın olmasına rağmen C++ dilinden basittir. Bu dilden farklı olarak otomatik bellek tahsisi yapar ve işi biten nesneler bellekten silinir. Kullanılmayan nesneler Garbage Collector ile toplanarak bellekte gereksiz kullanım yapılmaz. C++ dilinde bellek kaçakları meydana gelir ve yapısı Java'daki gibi değildir. Ayrıca C++ dili ile yazdığımız programı, Java'da daha az kod satırı ile yazabiliriz. Java'nın önemli bir üstünlüğü de multithreading'e elverişli olmasıdır. Birden fazla işin aynı anda yapılması anlamına gelen bu özellik, Java'nın temel yapısında vardır. Güvenliğin önemsendiği Java dilinde, API'ler sayesinde şifreleme, sayısal imza gibi güvenlik önlemleri alınabilir. Ağ ortamındaki güvenlik derecesi oldukça yüksektir. C dilinde kullanılan pointer kavramının yerini Java'da referans almıştır. Nesne ve değişkenlerin adresi pointer ile tutuluyorken; Java'da bu karmaşıklık kaldırılarak referans kavramı getirilmiştir. Java, çok zengin bir kütüphaneye sahiptir ve bunlar ücretsiz olarak temin edilebilir. Xml, ağ, arayüz gibi konularda uygulama geliştirmek için bize yardımcı olabilecek kütüphaneler mevcuttur. Buna Java API Kütüphanesi denir. Programlama ile ilgilenen bazı arkadaşların dilinde şöyle bir söz vardır: "Facebook bile Php ile yazılmış. O yüzden Php bayağı gelişmiş bir dil ve çok kullanılıyor" diye. Aslında Facebook'un arka planında birçok Java uygulaması çalışır. Java, framework konusunda oldukça gelişmiştir. İhtiyaca göre gerekli framework'lar bulunmaktadır. Bir web uygulaması, oyun, otomasyon gibi projeler için farklı framework'lar kullanılır. Java, dediğimiz gibi platformdan bağımsız çalışır. Nedir bu kavram? Java'da bunu hangi yapı sağlar? Şimdi Java ile ilgili temel kavramları görelim. Bunlar; Java ile program geliştirmeye başlamadan önce bilmemiz gereken temel kavramlardır. JVM(JAVA VIRTUAL MACHINE - JAVA SANAL MAKİNESİ) Java programları derlendikten sonra bilgisayarın anlayacağı dile dönüştürülür. Buna byte kod denir. Byte kod ile java programlarının platformdan bağımsız çalışması sağlanır. Byte kod bir kere oluşturulur ve her işletim sisteminde çalışır. Buna write once run everywhere de denir. Bunu sağlayan yapı JVM(Java Virtual Machine)'dir. Java programlarının çalışma mantığını daha detaylı bir şekilde anlatalım. Java programları nesne ve sınıflardan oluşur. Yazılmış olan sınıfların bulunduğu dosyaların uzantısı .java'dır. Bu .java uzantılı dosyalar, bir derleyici yardımıyla derlenir ve byte kod adı verilen makina kodlarına dönüştürülür. Artık bu dosyaların uzantısı .class olmuştur. Bu işlem yalnızca bir kez yapılır. Bu .class uzantılı byte kodlar, JVM yardımıyla her işletim sisteminde çalışır hale gelmiştir. JVM, bu byte kodları adım adım yorumlar. Yazılan java programlarının diğer işletim sistemlerinde de çalışabilmesi için o makinede JVM kurulu olması gerekir. Hazır olan byte kodları, o makine üzerinde yorumlayarak işletim sisteminin kullanımına sunar. Böylece byte kodları, üzerinde çalıştığı sisteme uygun hale getirir. Günümüzde neredeyse her platform için yazılmış JVM'ler bulunmaktadır. Istisnalar: ! JVM, Java'daki bir kere yaz her yerde çalıştır kavramında başrol oynayarak, Java dilini bir adım öne çıkarmıştır. JVM, sadece java dilinde yazılmış programları değil, byte kod'a dönüştürülebilen her dili çalıştırılabilir. Yukarıdaki şekilde JVM'nin işletim sistemi için önemi gösterilmiştir. Derlenerek Byte kod'a çevrilen kaynak kodlar, JVM sayesinde her işletim sistemi üzerinde çalışabilir. JRE(JAVA RUNTIME ENVIRONMENT - JAVA ÇALIŞMA ORTAMI) Java ile yazılmış olan programları çalıştırmak için JRE kurulu olmalıdır. Bir uygulama geliştirdiğimiz zaman bunu kendi bilgisayarımızda çalıştırmamız için gereklidir. Bunu C# dilinde kod yazdığımızda, bunları çalıştırabilmek için .Net framework'a ihtiyaç duymamıza benzetebiliriz. Java kodları, derlendikten sonra doğrudan bir makine üzerinde çalışamadığı için byte kodlara dönüştürülmesi gerekir. Bunu yapan mekanizma JRE'dir. Dönüştürülen byte kodları ise JVM yorumlar. JRE'nin içerisinde java kütüphaneleri ve JVM sanal makinesi bulunur. JRE yüklediğimiz zaman otomatik olarak JVM de yüklemiş oluruz. JVM kavramını açıklarken, java kodlarının bilgisayarımızda çalışabilmesi için JVM kurulu olmalıdır demiştik. JRE içerisinde JVM bulunduğu için, Java kodlarını çalıştırmak için yalnızca JRE yüklemek yeterlidir. Istisnalar: JDK kullanarak geliştirdiğimiz bir uygulamayı çalıştırmak için gereken JRE sürümü, o uygulamayı geliştirmek için kullanılan JDK sürümünden daha yüksek olmalıdır. JDK 1.4 ile geliştirilen bir uygulama, JRE 1.3 ile çalışmaz, daha yüksek bir sürüm gerekir. JDK(JAVA DEVELOPMENT KIT - JAVA GELİŞTİRME KİTİ) Java'nın inceliklerini ve performansını gördükten sonra bir Java uygulaması geliştirmek isteyebiliriz. Bunun için ihtiyaç duyacağımız tek şey JDK'dır. JDK, Java uygulamaları geliştirmek için bize bütün araçları sunar. İçerisinde Java kütüphaneleri, Java Compiler ve Interpreter, JVM ve JRE içerir. Görüldüğü gibi JDK'lar, JVM ve JRE'yi barındırır. Uygulama geliştirmek istiyorsanız, yalnızca JDK yüklemeniz yeterlidir. Çünkü JDK içerisinde JRE bulunur. JRE içerisinde de JVM bulunur. Istisnalar: ! JDK, uygulama geliştirmeye JRE, uygulama çalıştırmaya yarar. JVM ise platformdan bağımsız bir ortam sağlayarak, derlenen kodların başka platformlarda da çalışmasını sağlar. Java'da ilk JDK sürümü 1.0 ile başlamıştır. Bu sürümde birçok eksiklikleri bulunmaktaydı. Eksiklikler giderilerek sürekli gelişen JDK sürümleri günümüzde JDK 7.0'a kadar gelmiştir. Bu evrede, ileride göreceğimizScanner sınıfları, gelişmiş for döngüleri ve daha bunun gibi birçok yapı eklenmiş ve geliştiricilere sunulmuştur. J2EE, J2SE, J2ME KAVRAMLARI Java'da birçok farklı alanda uygulama geliştirmek mümkündür. Uygulamalar kullanıldığı alanlara göre farklı platformlara bölünmüştür. J2EE (ENTERPRISE EDITION): Kurumsal uygulamalar, web servisleri gibi gelişmiş uygulamalar geliştirmek için kullanılır. Gelişmiş uygulamalar geliştirildiği için n katmanlı mimariler kullanılır. Bünyesinde Servlet, JPA, JSP gibi hizmetler bulunur. J2ME (MICRO EDITION): Bu platform, 1991 yılında tanıtılıp kullanılmaya başlanmıştır. Genellikle mobil cihazlar için kullanılan J2ME teknolojileri, bunun yanında akıllı kartlar, avuç içi bilgisayarlar, kablosuz ve küçük cihazlar için de kullanılır. J2SE (STANDART EDITION): Çok gelişmiş uygulamaların haricinde, kişisel bilgisayarlarda geliştirilen uygulamalardır. J2EE kullanılarak geliştirilen uygulamalar gibi gelişmiş uygulamalar hazırlamaya elverişli değildir. Fakat J2EE ile uygulama geliştirmek için sağlam bir J2SE bilginizin olması gerekir. J2SE, J2EE kadar karmaşık bir yapıya sahip değildir. Ders 2 - JDK Kurulumu Java uygulamaları geliştirmek için bilgisayarınızda JDK'nın kurulu olması gerekmekte. Bunun için JDK'nın herhangi bir sürümünü indiriyoruz. Biz derslerimizde uygulamalarımızı J2SE teknolojisi ile yapacağımız için JDK'nın J2SE için olan sürümlerini indirmemiz gerekiyor. Bunun için http://adf.ly/YbRHk adresinden download'a tıklıyoruz ve anlaşmayı onayladıktan sonra uygun işletim sistemini seçerek indiriyoruz. JDK 7 veya JDK 6sürümünü indirebilirsiniz. PATH AYARLARI Kurulumu yaptıktan sonra test etmek için Başlat simgesinden Çalıştır'a tıkladıktan sonra, cmd yazıp konsol ekranına gitmemiz gerekiyor. Bunu yaptıktan sonra konsol ekranına java yazalım ve Enter'a basalım. Bazı ayarların geldiğini göreceksiniz. Daha sonra javac komutunu yazalım ve Enter'a basalım. Path değişkenini tanımlamadıysanız, bu komut çalışmayacaktır. Bu komutun çalışması için path tanıtmamız gerekiyor. Bunu yapmak için şu adımları izleyelim. Bilgisayarım'a sağ tıklayın.Özellikler - Gelişmiş - Ortam Değişkenleri adımlarını izleyin Kullanıcı Değişkenleri kısmında Yeni butonunu göreceksiniz. Buraya, JDK'mızın kurulu olduğu dizini eklememiz gerekiyor. JDK'nın kurulu olduğu dizin, eğer değiştirmediyseniz Program FilesJava-JavaJDK-bin klasörüdür. Bu adresi kopyalayın (C:\Program Files\Java\jdk1.7.0_45\bin indirdiğiniz sürüme göre değişebilir) Daha sonra ilk anlattığım Kullanıcı değişkenleri kısmında Yeni diyerek Değişken değeri kısmına yapıştırıyoruz. Değişken adı kısmına ise aynen path yazıyoruz. Kullanıcı değişkenleri yerine Sistem değişkenleri kısmından Yeni diyerek ve aynı parametreleri girerek de yapılabilir. Sistem değişkenlerine eklersek, tüm kullanıcılar için geçerli olur. Son olarak Tamam diyerek çıkıyoruz. Bu işlemleri yaptıktan sonra konsol ekranında javac komutunun artık çalıştığını göreceksiniz. Peki, biz bupath değişkenini tanıtarak ne yaptık? Bir önceki bölümde anlattığımız üzere Java kaynak kodları önce derlenerek byte koda dönüştürülüyordu. Bunu javac derleyicisi yapıyor. Biz bu path değişkenini tanıtmadığımız için javac komutu da çalışmadı. Artık bunu tanıttığımız için programlarımız javac komutu ile derlenebilir. Ders 14'te path ve Classpath kavramlarını açıklayacağız. JDK Kurulumumuz tamamdır. Şimdi ise IDE kurulumunu yapalım. Ders 3 - Eclipse Kurulumu Java programlarını geliştirebilmek için IDE'lere ihtiyaç vardır. Bunları kullanmak zorunlu değildir, fakat program geliştirmede çok yardımcı olacaktır. Bunları kurmadan da not defteri üzerinden program yazabiliriz, fakat IDE'ler ile bu çok rahat olur. Not defteri ile yazmak çok zahmetlidir. Bu şekilde de yazılabileceğini göstermek için bu bilgiyi verdik. Java uygulamalarını geliştirmek için en önemli araç elbetteki IDE'dir. Bu her programlama dili için vazgeçilmezdir. Java uygulamaları geliştirmek için Eclipse programını kullanacağız. Eclipse eklenti bakımından çok zengindir. Java uygulamaları için bize göre en iyi IDE, Eclipse'dir. Zaten geliştiricilerin çoğu bunu kullanmaktadır. Şimdi ilk olarak http://adf.ly/YbWjW adresinden en üst kısımda bulunan Eclipse Standartversiyonunun sağında bulunan 32bit veya 64bit seçeneklerinden sisteminize uygun olanı seçin. Daha sonra [Turkey] Linux Kullanicilari Dernegi (http) yazısına tıklayarak indirme işlemini başlatın. Bu işlemleri yaptıktan sonra indirme işlemi başlayacaktır. Eclipse IDE'yi indirdikten sonra klasör içerisinde bulunan eclipse.exe dosyasını çalıştıralım kurulum gerektirmeyen Eclipse açıldığında ilk olarak, yapılan projelerin hangi klasör altında toplanacağını gösteren bir soru ile başlıyor. Burada istersek default(varsayılan) olarak gelen Workspace klasörü ile devam ederiz. Eğer başka bir klasör altında toplansın istiyorsak Browse diyerek bu klasörü seçebiliriz. Aşağıda bulunan kutucuğu işaretlersek, her açılışta bunu sormayacaktır. Fakat işaretlemezsek her açılışta hangi klasöre toplayayım diye soracaktır. Artık IDE'miz hazır. Java ile program geliştirmeye başlayabiliriz. Bir sonraki dersimizde Eclipse ortamını tanıyacağız. Ders 4 - Eclipse Ortamını Tanıyalım ECLIPSE ARAYÜZÜ Eclipse arayüzü yaklaşık olarak 5 temel bölgede incelenir. Bu resimde arayüzünün temel bileşenleri yer almaktadır. Numaralandırılmış bölgelerin açıklamalarını yapalım. 1. Bu bölge projelerimizin gösterildiği yerdir. Eklediğimiz bir proje burada görünür. İstenildiği zaman buradan silinebilir. 2. Bu alanda kodlarımızı yazacağız. Henüz üzerinde çalıştığımız bir proje olmadığı için bu alan kapalıdır. 3. Yazdığımız konsol uygulamalarının çıktısını bu alanda göreceğiz. Bu alanda, uygulamalarımızdaki hataları da görebiliyoruz. Ayrıca Apache Tomcat gibi web serverları da bu kısımdan ekleyebiliriz. 4. Burası perspektif veya platform dediğimiz yerdir. Dilersek Java EE veya DDMS platformlarına da geçebiliriz. Hangi platforma geçersek, arayüzdeki temel bileşenler bizim için ayarlanacaktır. Yeni perspektif eklemek için Window-Open Perspective kısmından farklı perspektifler ekleyerek, ekranınızdaki panellerin buna göre şekillenmesini sağlayabilirsiniz. 5. Bu alan ise bizim menümüzdür. Buradan proje ile ilgili ayarlar yapabilir, yardım alabilir, yeni eklenti yükleyebilir, proje oluşturup silebilir ve bunun gibi daha birçok şeyi yapabiliriz. Buradaki numaralandırılmış bölgeleri yanlışlıkla kapatırsak şu şekilde bunları tekrar açabiliriz. Menüdeki Window kısmından Show View alanına tıklayalım. Burada sağ tarafta açılan panellerden birisine tıklayarak o paneli ekleyebiliriz. Eğer istediğimiz panel burada yoksa Other diyerek listede olmayan başka bir panel ekleyebiliriz. Aşağıda panel ekleme gösterilmiştir. ECLIPSE İÇERİSİNDE JRE AYARLARI Eclipse ile bir proje geliştirebilmek için öncelikle JRE'yi Eclipse'ye tanıtmamız gerekiyor. Bunun için; 1. Eclipse açıkken Windows - Preferences dedikten sonra karşımıza şöyle bir ekran gelecektir. 2. Burada sol tarafta Java sekmesi altında Installed JRE'se tıklayalım. Buradaki alan eğer doluysa yapmanız gereken bir işlem yok fakat bu alan boşsa buraya bir JRE eklememiz gerekiyor. 3. Bunun için sağ tarafta bulunan Add butonuna tıklayalım. 4. Daha sonra Standart VM'yi seçtikten sonra Next diyerek ilerleyelim. Karşımıza aşağıdaki gibi bir alan gelecektir. 5. JRE Home kısmında, Directory'e basarak JRE'nin kurulu olduğu dizini gösteriyoruz. Bu dizini, eğer anlattığımız gibi JDK'yı yüklediyseniz C:\Program Files\Java\jre7 olarak belirleyebilirsiniz. Javaklasörünün altında hangi versiyon kurulu ise onu işaretleyin. JRE Name kısmında JRE versiyonunu yazabilirsiniz yine anlattığımız gibi yüklediyseniz jre7 yazmanız gerekiyor. 6. Son olarak Finish diyerek bitiriyoruz. ECLIPSE ILE PROJE OLUŞTURMA Bize lazım olan temel alanları öğrendiğimize göre artık yeni bir proje oluşturabiliriz. Yeni bir Projeoluşturmak için: File - New - Java Project adımlarını izliyoruz. Bundan sonra karşımıza aşağıdaki gibi bir ekran gelecektir. Buradaki numaralandırılmış yerleri de açıklayalım. 1. Bu alana proje adını giriyoruz. 2. Bu alanda kullanacağımız JRE'yi seçiyoruz. Alttaki seçeneklerde ise kendimiz bir JRE ekleyebiliriz. Bunları yapmadan doğrudan 1.7 versiyonu ile başlayalım. Eğer 1.7 versiyonu seçili değilse seçeneklerden JavaSE-1.7 versiyonunu seçebilirsiniz. 3. Burada da projemiz için ayrı bir klasör oluştururuz. Daha sonra göreceğimiz src ve bin dosyalarını oluşturarak projenin alt dosyalarına ulaşabilmeyi kolaylaştırırız. Daha sonra Next dedikten sonra karşımıza gelen ekrandan Finish diyerek projemizi oluşturuyoruz. Buradaki alanları detaylı olarak Video kısmında anlatacağız. Sol tarafta Project Explorer içerisinde çıkan projemize çift tıklıyoruz. Alt tarafta src ve JRE System Library adlı klasörler gelecektir. Buradaki src klasörü içerisine projemizdeki sınıfları, panelleri, pencereleri ve bunun gibi şeyleri ekleyeceğiz. JRE System Library içerisinde ise jar dosyalarımız bulunur. Bu dosyalar bize hazır olarak gelir. Bu jar dosyaları, programların çalışması için gerekli kütüphaneleri içerir. Arayüz ile ilgili detaylı bilgileri aşağıdaki videoda daha detaylı olarak anlattım. Dilerseniz inceleyebilirsiniz. BİR PROJEYİ ECLIPSE İÇERİSİNE DAHİL ETME Bir Java projesinde Eclipse içerisine Import edip bir proje üzerinde tekrar çalışabiliriz. Bunun için yapmamız gerekenler şu şekildedir: İlk olarak menü kısmından File - Import seçeneğine tıklıyoruz. Tıkladıktan sonra gelen ekrandan General altındaki Existing Project into Workspace kısmına tıklayarak ilerleyin. Bir proje eklemek istediğimiz için bu kısma tıkladık. Ne eklemek istiyorsak ona uygun olan seçeneği işaretlememiz gerekiyor. Bu kısımda da Browse diyerek, projemizin bilgisayardaki yolunu seçiyoruz ve projemiz alt kısma ekleniyor. Finish diyerek projeyi, Eclipse içerisine dahil ediyoruz. Projemizin, Project Explorer içerisindeki görünümü ise şu şekildedir. ECLIPSE KISAYOLLARI Bu dersimizde Eclipse içerisindeki en çok kullanılan kısayolları anlatacağız. Ctrl+N> "Yeni" penceresini açar. Ctrl+S> O an bulunan sayfayı kaydeder. F11> Uygulamayı Debug yapmaya yarar. Ctrl+F11> Uygulamayı derler ve çalıştırır. Ctrl+Shift+O> Uygulamanızdaki import edilmemiş sınıfları otomatik olarak import eder. Örneğin; matematik sınıfını kullanarak bir kod yazdık fakat Math sınıfını uygulamamıza import etmemiz gerekiyor. Bu kısayol, bu işlemi otomatik olarak yapar. Alt+Up / Alt+Down> O anda bulunan satırdaki kodları, aşağı ve yukarı taşımaya yarar. Kes-yapıştır işleminden bizi kurtarır. Ctrl+R> Verilen satır sayısına dallanmaya yarar. Ctrl+D> O an bulunulan satırı siler. Ctrl+/> O an bulunulan satırı açıklama satırına çevirir. Ctrl+\> O an bulunulan açıklama satırını kod satırına çevirir. F14> Projemizin hiyerarşisini gösterir. Shift+Alt+R> İmlecin üzerinde bulunduğu bir değişken, metod ve sınıf ismini projenin tamamında aynı anda değiştirmeye yarar. Ctrl+Space> Kodları otomatik olarak tamamlamaya yarar. Kullanılan temel kısayollar bu şekildedir. Window-Preferences-General-Keys kısmından bu kısayolları değiştirebilirsiniz. JAVA UYGULAMASINI ECLIPSE DIŞINDA ÇALIŞTIRMA Java projelerimizi Eclipse IDE dışında da çalıştırmamız mümkündür. Projemizi Eclipse IDE dışında çalıştırmak için projeyi .jar dosyası olarak dışa aktarmamız gerekmektedir. .jar formatı, Java uygulamalarının standart formatıdır. Projemizi nasıl .jar dosyası olarak dışa aktarıldığını örnek üzerinden inceleyelim. Projemize sağ tıklayıp aşağıda şekilde gösterildiği gibi Export seçeneğini seçin. Açılan pencereden Java açılır seçeneğinin altından JAR File seçeneğini seçin ve Next tuşuna basarak bir sonraki adıma geçin. Açılan pencerede sol üst kısımdaki bölümden projemizi seçtikten sonra, aşağı kısımda yer alan JAR Filebölümünden projemizin .jar dosyasının diskte kaydedileceği alanı ve bu dosyanın ismini belirliyoruz. Bu bilgileri de girdikten sonra Finish tuşuna basıp işlemi sonlandıralım. Tüm işlemleri bitirdikten sonra belirlediğimiz yolun altında belirlediğimiz isimle bir .jar dosyası oluştuğunu göreceğiz. Bu .jar dosyasını Eclipse dışında çalıştırmak için konsola ihtiyacımız var. Bunun için şu işlemleri yapın: Windows komut istemcisini başlatın.(Çalıştır-cmd) Daha sonra işlem(çıkış) klasörünüzü, cd dosyayolu komutu yardımıyla .jar dosyasını kaydettiğiniz klasöre konumlandırın.(Bizim .jar dosyamız, C:\Users\Okan\Desktop altında). Programımızı çalıştırabilmemiz için .jar dosyamızı Java ClassPath'ine dahil etmemiz gerekir. ClassPath, JavaRunTime kütüphanesinde mevcut sınıfları tutar. Jar dosyanızı -jar komut satırına -jar parametresini girerek ClassPath'e ekleyebilirsiniz. Bu örnek için aşağıdaki kodları girdiğinizde resimdeki gibi bir sonuç elde edeceğiz. KOD: TÜMÜNÜ SEÇ java -classpath proje.jar HelloWorld //java -classpath <proje adı> <class adı> Şekilde de görüldüğü gibi Java projemizi, Eclipse dışında başarıyla çalıştırmış olduk. Ders 5 - Java İle İlk Programımız Temel şeyleri öğrendiğimize göre artık ilk Java programımızı yapabiliriz. Bunun için Package Exploreriçerisinde daha önceden oluşturduğumuz projedeki src klasörüne sağ tıklayıp New-Class dedikten sonra aşağıdaki görüntü karşımıza gelecektir. Şimdi buradaki alanları tanıyalım. 1. Burada sınıfımızın olacağı paketi yazıyoruz. Bu konuyu paketler dersinde detaylı olarak göreceğiz. 2. Buraya da sınıfımızın ismini yazıyoruz. Alt tarafta bulunan final, abstract gibi kavramları da işaretlemeyelim şimdilik. Bunları nesneye yönelik programlama konusunda detaylı olarak inceleyeceğiz. 3. Bu kısımda public static void main yeri işaretlediğimiz zaman bize otomatik olarak, bir main metodu ekleyecektir. Alt taraftaki kutucukları işaretlediğimiz zaman ise, yazılı olan alanları otomatik olarak ekleyecektir. Şimdilik bunlara gerek yok. İstenilen bilgileri oluşturduktan sonra Finish diyerek bitirelim. Bu adımları yaptıktan sonra karşımıza aşağıdaki gibi bir kod ekranı gelecektir. Burada dikkatimizi çeken bazı şeyler var. İlk olarak Slash (/) dediğimiz işaretler bulunuyor. Bunlar Java'da açıklama satırı için kullanılır. Açıklama satırları programımızda kodlara kısa notlar düşmemize yardımcı olur. Bunlar derleyici tarafından derlenmez. Bu kodlar, başkasının baktığında anlayabilmesi veya kodu yazan kişinin belli bir zaman sonra tekrar baktığında ne yaptığını hatırlaması için kullanılır. Eğer tek satırlık açıklama yapacaksak, açıklamanın başına sadece / getirmemiz yeterli olacaktır. Birden fazla satır sürecekse, açıklama satırlarını /*...*/ arasına yazmalıyız. Üç nokta ile gösterdiğimiz yere açıklama ekleriz. Örnek verirsek: //Bu bir açıklama 1 satırıdır. 2 /*Burası çok satırlı 3 açıklama satırıdır.*/ Burada bir main metodumuz bulunmaktadır. Programlar ilk olarak bu metod içerisinden başlar. Bu metodstring tipinde bir args dizisini parametre olarak alır. Bu parametreye Diziler konusunda detaylı olarak değineceğiz. main metodunun başında static public void gibi anahtar kelimeler vardır. Bunlara da Metodlarkonusunda değineceğiz. Java'da herşey bir sınıf olduğu için ekrana bir şey yazdırmak için bile bir sınıf oluşturmamız gerekiyor. Buradaki sınıfımızın adı JavaProgrami'dir. Sınıf adı ile dosya adımız aynı olmalı. Sınıf kavramını da detaylı olarakNesneye yönelik programlama konusunda anlatacağız. Şimdi basit bir program yapalım. Bu programımızın kodlarını main metodumuzun içerisine yazmamız gerekiyor. main metodunun dışına da bir şeyler yazabilirsiniz fakat programı çalıştıracak kodlar mainmetodunda bulunmalıdır. Mesela; main metodunun dışında bir metod(fonksiyon) oluşturursak, bu metodu mainmetodu içerisinden çağırmalıyız. İleride daha gelişmiş örnekler yapacağız. Basit bir örnek olarak ekrana birşey yazdıralım. Karşımıza gelen açıklama satırlarını da kaldıralım. //JavaProgrami.java - 03.04.2014 1 2 public class JavaProgrami 3 { 4 public static void main(String[] args) 5 { 6 System.out.println("İlk Java 7 Programı"); 8 } 9 } 10 11 Yazdığımız bu kodu, yukarıda yeşil renkteki butona basarak çalıştıralım. Dosya adımıza sağ tıklayıp Run as - Java Application diyerek de çalıştırabiliriz. Bu programın çıktısı aşağıdaki gibi olacaktır. Ekrana bir yazı yazmak için System.out.println(); metodu kullanılır. Parantez içerisine bir String veyadeğişken yazabiliriz. System.out.println("İlk Java Programı"); //String 1 yazdırdık 2 System.out.println(a); //Değişken yazdırdık Eğer String bir ifade yazdıracaksak çift tırnak içerisinde yazmalıyız. Bir değişken yazacaksak, doğrudan o değişkeni eklemeliyiz. Peki, hem değişken hem de String yazacaksak ne yapmamız gerekir? Bunu basit bir örnekle anlayalım. Videolarımızda bol bol anlatacağız. //JavaProgrami2.java - 04.04.2014 1 2 public class JavaProgrami2 3 { 4 public static void main(String[] args) 5 { 6 int a=5; 7 System.out.println(a+" Okan Bilke 8 ElektroArge"); 9 System.out.println("Okan Bilke" + " 10 ElektroArge"); 11 } 12 } 13 Bu kod, yukarıdaki gibi bir çıktı verecektir. String ile değişkeni veya String ile String'i birleştirmek için + operatörü kullanılır. ! Istisnalar: Java'da her ifade ; ile bitmek zorundadır. INTELLISENSE TEKNOLOJİSİ Intellisense dediğimiz teknoloji ile çoğu IDE'de bulunan özellik burada da bulunmaktadır. Peki, bu özellik nedir ondan bahsedelim. Sys yazıp Ctrl tuşuna basıp Space tuşuna bastığımızda Eclipse, bizim için Sys ile başlayan tüm özellikleri getiriyor. Yapıldığında çıkan sonuç aşağıdaki gibi olacaktır. Bu otomatik tamamlama özelliği, ileride değişkenleri, metodları, sınıf adlarını ve bu gibi şeyleri kendisi tamamlayacaktır. Ayrıca ekrana System.out. yazıp bu şekilde bıraktığımızda, kullanabileceğimiz metodlar listelenecektir. Burada nokta (.)'ya bastığımız yerlerde, o sınıf içerisinde kullanılabilecek metodlar gösterilir. Bunun bir örneği aşağıda gösterilmiştir. Ekrana bir şey yazdırma ile ilgili bir kısa yol verelim. Kod yazarken sysout yazıp Ctrl ve Space tuşlarına basarsanız, otomatik olarak System.out.println(); metodunu getirecektir. Bu metodun içerisine istediğimiz şeyleri yazabiliriz. NOT DEFTERİ İLE JAVA KODU YAZMA VE DERLEME JDK Kurulumunu anlattığımız 2. Dersimizde javac komutuna değinmiştik ve Not defteri ile programların yazılabileceğini, fakat gelişmiş programlar yazmanın neredeyse imkansız olduğunu söylemiştik. Şimdi de dersimizin başında yaptığımı örneği Not defterini kullanarak yapalım. İlk olarak aşağıdaki kodu not defterine yazalım. //Deneme.java - 04.04.2014 1 2 public class Deneme 3 { 4 public static void main(String[] args) 5 { 6 System.out.println("İlk Java 7 Programımız"); 8 } 9 } 10 11 1. Yazdıktan sonra uzantısını .java olacak şekilde Deneme.java adında masaüstüne kaydediyoruz. Sınıf adı ile dosya adı aynı olmak zorundadır. Kodumuzda sınıf adı Deneme olduğu için Deneme adıyla kaydettik. 2. Masaüstüne kaydettiğimiz bu .java uzantılı dosyayı C:\Users\Okan klasörüne atalım. Bu sizde Okan değil de başka bir klasördedir. 3. Daha sonra Başlat'a cmd yazıp DOS ekranına geliyoruz. 4. Burada javac Deneme.java yazıyoruz ve Enter tuşuna basıyoruz. Bu işlem ile programımız javac derleyicisi ile derleniyor ve anlattığımız gibi byte kod üretiliyor. 5. Son olarak java Deneme yazıyoruz ve programımız çalışıyor. Dos ekranındaki işlemler aşağıda gösterilmiştir. Bu dosyayı C:\Users\Okan klasörüne atmamın nedeni şudur. DOS ekranında kök dizinimizC:\Users\Okan klasörü olduğu için dosyanın da tanınması için bu klasörde olması gereklidir. Bu klasör değil de başka bir klasöre atabilirdik. O zaman DOS ekranında, o attığımız dizine gidip oradan çalıştırmamız gerekirdi. Eğer Deneme.java dosyasını masaüstüne atsaydık ve masaüstünde çalıştırmak isteseydik, konsol ekranında yazmamız gereken komutlar aşağıdaki gibi olacaktı. Bu sayede DOS ekranından masaüstü dizinine gelip çalıştırmamız gerekir. Yukarıda java ve javac ile işlemler yaptık. javac ile .java uzantılı kaynak kodlarımızı derledik. Sonunda.class uzantılı byte kodumuz oluştu. Bunu ise java, yani JVM ile yorumladık. Bu byte kodları başka bir işletim sisteminde yine JVM kullanarak yorumlayabilirdik. Ders 6 - Eclipse Üzerinde Debug İşlemleri DEBUG NEDİR? Debug yapmak programın kaynak kodunun etkileşimli olarak çalıştırılması ve bu esnada program değişkenlerinin durumlarının gözlemlenmesi ve bu sayede hataları daha açık görmemize olanak sağlayan bir kod yürütme yöntemidir. Break point'ler aracılığıyla kaynak kod işlenirken belirlenen satır işlendiğinde, programın durmasını sağlayabilirsiniz veya Watch Point'ler aracılığıyla kaynak kodunun belirli bir alanının çalışma esnasında alan okuduğunda veya değiştiğinde o noktada programın durmasını sağlayabilirsiniz. Programı bir noktada durdurduğunuzda işlenen satırdaki değişkenlerin değerlerini gözlemleyebilirsiniz veya bu değişkenlerin içeriğini değiştirip farklı bir değerle programın devam etmesini sağlayabilirsiniz. Eclipse IDE, bize debug yapmak için özel bir görünüm sunuyor. Eclipse'nin özel görünümü olan Debuggörünümünde önceden belirlenmiş debug pencereleri vardır. Bu görünümde işlemin icrasını ve değişkenlerin durumunu görmek daha kolay bir halde sunuluyor. BREAKPOİNT YERLEŞTİRME Kaynak kodumuzun belirli alanlarına breakpoint yerleştirerek programımızın belirli alanlara geldiğinde durmasını sağlayabiliriz. Bu çoğu zaman problemin nereden kaynaklandığı bulmak için başvurduğumuz yöntemlerden en sık kullanılanıdır. Breakpoint yerleştirmek için Java kodunun herhangi bir satırına resimdeki gibi Java kaynak kod düzenleyicisinin sol tarafındaki küçük alana sağ tıklayın ve açılan pencerede Toggle Breakpoint seçeneğine tıklayın. Basit şekilde ASCII tablosundaki büyük harfleri ekrana yazdıracağımız bu örneğimizde; 1 karakter=(char)sayi; ... satırına breakpoint'imizi yerleştirdik. Java kaynak kod düzenleyicisinin yanındaki küçük alana çift tıklayarak da breakpoint yerleştirebiliriz. Java kodumuza breakpoint yerleştirdikten sonra, kodumuzu debug yapabilmemiz için programımızıdebug modunda çalıştırmamız gerekmektedir. Java kodumuzu debug modunda çalıştırabilmek için çalıştıracağınız projeyi sağ tıkladıktan sonra, aşağıdaki şekilde gösterildiği gibi Debug As > Java Applicationseçeneklerini seçin. Eğer breakpoint tanımlamadıysanız program kodunuz debug modunda olmadan normal bir şekilde çalışacaktır. Debug yapabilmek için breakpoint yerleştirmeniz gerekmektedir. Java kodunuzu debug modunda çalıştırdığınızda Eclipse size Debug görünümüne geçmek isteyip istemediğinizi soracak. Evet seçeneğini seçerseniz aşağıdaki resimdeki gibi bir görünümle karşılaşacaksınız. Java kodumuzu Debug modunda çalıştırdıktan sonra kodumuz belirli ölçülere göre ilerleten tuşları kullanırız. Bu tuşlar ve görevleri aşağıdaki gibidir. Tuş Açıklama F5 Halen seçili olan satırı icra eder ve bir sonraki satıra geçer. Seçili satır metod tanımı ise metod F6 Seçili satırı atlar ve bir sonraki satırı icra eder. Metodu çağıran koda gider. Bu işlem icra edilen metodun sonlanmasını ve metodun kendisini F7 sağlar. Bir sonkrai Stop Point(Break Point veya Watch Point)'e kadar olan kodu icra eder ve kodun b F8 durmasını sağlar. Aşağıdaki şekilde bu tuşların Eclipse üzerindeki yeri belirtilmiştir. BREAKPOİNT GÖRÜNÜMÜ VE BREAKPOİNT'LERİ KALDIRMA Breakpoint görünümü bize Stop Point'leri devre dışı bırakmak, Stop Point'leri kaldırmak ve bunlar üzerinde değişiklik yapmamızı sağlayan avantajlar sunar. Şekilde görüldüğü gibi bir stop point'i devre dışı bırakmak için ilgili stop point'in solundaki tik işareti kaldırılır. Tekrar tıklanıldığında stop point aktif hale geçer. Stop point'leri silmek için resimde gösterildiği gibi tek bir stop point silmek için stop point üzerine tıklanıldıktan sonra tek X işaretine basıldığında ilgili stop point silinir. Çift X işaretine tıklanıldığında ise bütün stop pointler silinir. Bütün stop point'leri devre dışı bırakmak için ise Skip All Break Points tuşu kullanılabilir. Bu tuşa tekrar basıldığında bütün stop point'ler tekrar aktif olacaktır. DEĞERLER GÖRÜNÜMÜ VE DEĞİŞKENLERİN DEBUG MODUNDA DEĞERLERİNİ DEĞİŞTİRME Değerler görünümü, Java kodunda bulunan değişkenleri ve bunların aldığı anlık değerleri gösterir. Değerler görünümü ve bu görüdümdeki değişkenler aşağıdaki resimdeki gibidir. Şekilde değişkenlerimizin ismini ve aldığı değerleri görüyoruz. Değişkenlerin diğer özellikleri de bu görünümden görmek mümkündür. Bunun için aşağıdaki resimdeki gibi görünüm penceresinin sağında kalan ok işaretine tıklanıldıktan sonra açılan pencereden, Layout > Select Columns seçenekleri seçilerek açılan pencereden değişkenlerin görüntülenen özellikleri arttırılabilir. Değişkenlerin değerlerini değiştirmek için ise değeri değiştirilmek istenen değişkenin Value özelliği tablodan çift tıklatılarak değiştirilir. Ders 7 - Paket (Package) Kavramı PAKET (PACKAGE) KAVRAMINA GİRİŞ Package kavramı, Java kullanmamış olan kişilere başta yabancı gelebilir. Package kavramını özetle tanımlayacak olursak, Java'da yazdığımız sınıflar arasında bir hiyerarşi sağlar. Aslında Java programları da paketlerden oluşur. Bu kavram, yazılım geliştirirken bize büyük kolaylık sağlar. Örneğin; bir uygulama geliştiriyoruz diyelim. Bu uygulamamızda birçok modül var ve bu modülleri tek bir dosya altında değil de bölümlere ayırarak bu modülleri tek bir dosya altında değil de bölümlere ayırarak bu modülleri gruplayabiliriz. Geliştireceğimiz uygulamalarda veritabanı işlemlerini ayrı bir pakette, arayüzümüzü ayrı bir pakette gruplarsak daha yüksek performans elde edebiliriz ve istediğimiz şeylere kolaylıkla ulaşabiliriz. Bu package, kavramını marketlerdeki reyonlara benzetebiliriz. Java paketinin içerisinde sınıflar ve arayüzler bulunur. Paketler, iyi bir programcılık ve sistematik çalışma için gereklidir. PAKET TANIMLAMASI Java'da geliştireceğimiz uygulamalarda bir paket belirlemezsek; Java bizim için default package adında bir paket oluşturur ve sınıflarımızı bu dosyada tutar. Paket tanımlamaları package anahtar sözcüğü ile şu şekilde yapılır: package 1 com.org.veritabani; Diyelim ki kütüphane ile ilgili bir projemiz olsun. Bu projede belirli alt modüller olsun. Mesela; veritabanıve arayüz. Bu veritabanı modülü için kullanmamız gereken paket kitap.veritabani; olmalıdır. Arayüz içinse bütün sınıflarımızı kitap.arayuz; paketi altında toplamalıyız. Bunlar zorunlu değildir tabi, fakat yapmak her zaman iyi olacaktır. ! Istisnalar: Paket tanımlamaları her zaman sayfamızın en üstünde olmalıdır. Paket tanımlarken kullandığımız nokta(.) ile bir alt klasöre iniyoruz. Biz genelde geliştirdiğimiz uygulamaları veya yaptığımız çalışmaları saklamak için Belgelerim - Workspace adlı klasörü kullanıyoruz. Bu klasörde proje adı ile saklanan çalışmalarımız vardır. Projemizin adının olduğu klasöre girdiğimizde bin adında bir klasör daha bulunur. Burası bizim paketlerimizin saklandığı yerdir. com.org.veritabani adında bir paket tanımladıysak, bu bin klasörünün içerisinde com adında bir klasör, com klasörünün altında org adında bir klasör daha vardır. Son olarak bu org klasörünün altında da veritabani adında bir klasör daha vardır. Ne kadar nokta(.) koyarsak, o kadar alt klasöre iner. Hiyerarşiyi bu nokta sağlar. Paket adları, aynı zamanda klasör adlarına karşılık gelir. Nokta(.) ile oluşturduğumuz her paket adı, hiyerarşik olarak alt dizinde bir klasör oluşturur. Bir örnek verelim ve oluşan klasör yapısını görelim. //Deneme.java - 04.04.2014 1 2 package kitap.deneme; //paket tanımlaması 3 yapıldı 4 5 public class Deneme 6 { 7 public static void main(String[] args) 8 { 9 Scanner s=new Scanner(System.in); 10 } 11 } 12 13 Paketi bu şekilde tanımlarsak klasör yapısı aşağıdaki gibi olacaktır. Bu tanımlama ile resimde de görüldüğü gibi kitap ve deneme adında klasörler oluşturulmuştur. Bunlar hiyerarşik olarak alt dizinlerde yer almaktadır. Workspace dizininde Projemizin adının olduğu dosyaya girdiğimizde bin klasörünün içerisinde bizim paket hiyerarşimiz yer alır. Yine dediğimiz gibi bir a paketinin içerisinde b paketi varsa bu a.b ile gösterilir. Paketlerle ilgili başka bir noktaya değinelim. Diyelim ki kitap1 adında bir paketimiz var ve biz de herhangi bir sınıf üzerinde bir çalışma yapıyoruz. Bu yaptığımız sınıfın üstünde kitap1 paketini tanımlarsak, bu sınıflar ve arayüzler kitap1 paketine eklenir. package kitap1; tanımlaması yaparsak, bunu derledikten sonra artık bu sınıf kitap1 paketine eklenir. Istisnalar: ! Sınıfların aynı pakette olup olmadıkları önemlidir. İleride göreceğimiz nesneye yönelik programlamakonusunda bunun önemini göreceğiz. Temel olması için paket kavramından bu dersimizde başlangıç düzeyinde bahsettik. PAKETLERİ İMPORT ETME Burada bahsedeceğimiz başka bir nokta da başka paketteki sınıfları nasıl kullanacağımızdır. Bir paket içerisindeki herhangi bir sınıf üzerinde işlem yapıyoruz ve bu sınıfta, başka paketteki sınıfa veya başka sınıflara ihtiyacımız olabilir. Bunun için kullanacağımız paketi import etmemiz gerekir. Eğer bir sınıfı import edeceksek... 1 import sınıfın_yolu; ... import anahtar kelimesini yazdıktan sonra sınıfımızın yolunu yazıyoruz. Yoldan kastımız şudur: Diyelim kiveritabanı paketinin altında silme adındaki sınıfı ekleyeceğiz. Bunun için: 1 import kitap.veritabani.silme; Eğer bu veritabani adındaki paket altındaki birden fazla sınıfı kullanacaksak, bunları tek tek eklemek yerine şu şekilde de yapabiliriz: 1 import kitap.veritabani.*; Bu import ile veritabani altındaki tüm sınıfları import edebiliriz, yani tüm sınıfları artık, bulunduğumuz sınıfın içerisinde kullanabiliriz. Bu olay C# dilinde ve birkaç dilde de yapılabiliyor. Kullanılan anahtar kelime farklı olsa da mantık aynıdır. Bu şekilde yapmak programı yavaşlatmaz, çünkü yine sadece gerekli olan sınıf çalıştırılır. Istisnalar: ! import anahtar kelimesini, paket tanımlamasının bir alt satırında kullanarak sınıflar ekleyebiliriz. package ve import anahtar kelimelerinin kullanılmasına bir örnek verirsek, şu şekilde bunları beraber kullanabiliriz. //Deneme.java - 04.04.2014 1 2 package kitap.deneme; //paket tanımlaması 3 yapıldı 4 5 import java.util.Scanner; //Scanner sınıfı import 6 edildi 7 8 public class Deneme 9 { 10 public static void main(String[] args) 11 { 12 Scanner s = new Scanner(System.in); 13 } 14 } 15 Buradaki programımızı kitap klasörü altındaki deneme klasörünün içerisinde oluşturduk. Workspaceiçerisindeki bu klasörlere baktığımızda, bu programımızı görebiliriz. Paket tanımlamasını bu şekilde yaptık. Alt satırda ise Scanner sınıfını import ettik. Yani dedik ki; bu programda Scanner sınıflarını kullanacağız. Bunu C dilindeki include gibi düşünebiliriz. Bu sınıfı programımıza dahil ettik. Şimdi Java'da bizim kullandığımız hazır yazılmış paketlerden birkaçını görelim... java.lang: Bu ana paketimizdir diyebiliriz. Çünkü her Java programında olması gereken bir pakettir. Bu yüzden bu paketi import etmeye gerek yoktur. Yani her program şu paket eklenmiş olarak gelir.java.lang.*; java.util: Tarih, takvim gibi araçları kullanmamıza yarayan sınıflar içerir. java.io: Giriş Çıkış işlemleri için kullanılan sınıfları barındırır. java.awt: GUI dediğimiz arayüzleri kullanmamıza yarar. java.util.regex.*: Düzenli ifadeler eklemek için kullanılır. Istisnalar: ! Aynı paket içerisinde bulunan sınıflar, private elemanlar hariç birbirlerinin diğer tüm elemanlarına erişebilir.private elemanları, Nesneye yönelik programlama konusunda daha detaylı anlatacağız. Ders 8 - Değişkenler ve Veri Tiplerine Giriş Değişkenler, üzerinde veri depolayan sembolik isimlerdir. Verileri birbirinden ayırmak için kullanılırlar. Nasıl insanları isimleri ile ayırt ediyorsak, verileri de kendilerine ait bir değişken isimleri ile ayırırız. Her değişkenin bir tipi vardır. Bu veri tipleri, değişkenlerin tanımlanmasında kullanılan primitive (temel) ve nesne tanımlanmasında kullanılan referans tipleri olmak üzere 2'ye ayrılırlar. Primitive tipler ile oluşturulmuş değişkenler, belleğin stack (yığın) kısmında tutulurlar. Referans tipler ile oluşturulmuş değişkenler ise belleğinheap alanında tutulurlar. Bu kavramları sonraki sayfalarda daha ayrıntılı olarak anlatacağız. Değişken Tanımlama Kuralı: 1 Özel_anahtar_kelime Veri_tipi degisken_adi; 1. Özel anahtar kelimeler public, private, protected, static gibi anahtar kelimeler olabilir. Bunları, nesneye yönelik programlamada daha detaylı göreceğiz. Bunları yazmak zorunlu değildir. Eğer yazmazsak public olarak kabul edilirler. 2. Değişkenleri tanımlarken önce tipi yazılır. Daha sonra değişken adı yazılır. Bunun için uyulması gereken kurallar da anlatılmıştır. Değişkenlerin tanımlaması bu şekildedir. Bir değişken tanımlama örneği verirsek; int x; dediğimizde x adında bir değişken tanımlarız, fakat bir değeri yoktur. Değeri atanmadığı için de bellekte bir yer kaplamaz. Aşağıdaki gibi değişkeni tanımlayarak ona bir değer de verebiliriz. Buna initialization denir. int x=2; // değer atadığımız için bu değişkene bellekte bir yer 1 ayrıldı ! Istisnalar: Java'da tüm değişkenler, Java.lang sınıfından türemişlerdir. Ders 9 - Değişken Tanımlama Kuralları Değişken tanımlanırken uyulması gereken birkaç kurallar ve farklı tanımlama alternatifleri vardır. Bu kurallar programlama dillerinde farklılık gösterir. Biz burada Java'daki kuralları inceleyeceğiz. 1. Her değişken bir tipe sahip olmalıdır. Bir değişkenin sahip olacağı veri tipini tanımlamazsak hata ile karşılaşırız. a=10; // a cannot be resolved to a variable hatası 1 verilir 2 System.out.println(a); 2. Değişkenler, değer atanmadan kullanılamazlar. Bir değişken, değeri atamadan ekrana yazdırılamaz. Bunu yaptığımızda hata alırız. int a; 1 System.out.println(a); // The local variable a may not have been 2 initialized 3. Aynıı tip değişkenler, aynı satırda tanımlanabilir. Aynı tipte değişkenler tanımlayacaksak, aralara virgül koyarak tek satırda tanımlayabiliriz. String a="Okan", b="Onur", c="ElektroArge"; // a, b ve c değişkenleri 1 tanımlandı 4. Değişken isimlerinde Türkçe karakter kullanılmamalıdır. Değişken isimlerinde ı, ö, ü gibi Türkçe karakterler kullanılmamalıdır. Hata vermese de bunları kullanmak uygun değildir. String ö="Okan", ı="ElektroArge"; // Hata vermeyecektir, fakat dikkat 1 edilmelidir. 5. Değişken isimleri sayı ile başlayamaz ve değişken isminde boşluk olmamalıdır. Değişken isimleri sayı ile başlayamaz, fakat _,$ gibi bazı işaretlerle başlayabilir. 1 int $x; // doğru kullanım 2 int _b; // doğru kullanım 3 String degisken adi="Okan Bilke"; // hata verir 4 String 1soyadi="ElektroArge"; // hata verir Istisnalar: ! Java, Case Sensitive bir dildir. Yani büyük küçük harf ayrımı vardır. A ile a değişkeni farklıdır. Istisnalar: ! Verilerimizi değişkenler ile tanıdığımız için değişken isimlerinin anlamlı olmasına dikkat etmeliyiz. Bu, programımızın anlaşılabilirliğini artırır. Kısa programlar için bu çok önemli değildir. Değişken kavramını öğrendiğimize göre şimdi bu değişkenlerin tiplerini inceleyelim. primitive vereferans tipleri olmak üzere 2 veri tipimiz vardır. Şimdi bunları görelim. Ders 10 - Primitif Tipler BYTE 8 bittir. Bellekte 1 byte yer kaplar. Tamsayı türünde -128 ile 127 arasında değerler alır. Küçük değerli sayılar için, int yerine kullanılabilir. Varsayılan değeri 0'dır. byte a=5; 1 byte b=125; // Eğer b'ye 130 verseydik, 12 üst sınırını aşacağından hata 2 verecekti 3 System.out.println(a+b); Istisnalar: ! Bu sayı tiplerinde bir bit, işaret biti olarak kullanılır. Istisnalar: ! Veri tiplerinin varsayılan değerleri, o tipten tanımlanmış bir değişkene değer atanmadığında kullanılan değerdir. SHORT 16 bittir. Byte tipindekilerden daha büyük sayılar alabilir. Tamsayı türünde 32768 ile 32767 arasında değerler alır. Varsayılan değeri 0'dır. short sayi=32767; // bu değerden daha fazlasını alırsa hata 1 verir 2 System.out.println(sayi); INT 32 bittir. Bellekte 4 byte yer kaplar. Tamsayı türünde -231 ile 231-1 arasında değerler alır. Varsayılan değeri 0'dır. 1 int sayi=1453; 2 System.out.println(sayi); LONG Uzunluğu 64 bittir. Tamsayı türünde -263 ile 263-1 arasında değerler alır. Varsayılan değeri 0L'dir. long y=666666399; 1 long z=y*y; 2 System.out.println(z); // değişkeni int olsaydı, bu değer 3 tutulamazdı FLOAT Uzunluğu 32 bittir. Ondalık sayı türünde -3.4*1038 ile 3.4*1038 arasında değerler alır. Varsayılan değeri 0.0f'dir. 1 float a=-5; 2 float b=a/100; 3 System.out.println(b); DOUBLE Uzunluğu 64 bittir. Ondalık sayı türünde -1.7*10308 ile 1.7*10308 arasında değerler alır. Varsayılan değeri 0.0d'dir. 1 double sayi=5.111; 2 double sayi2=sayi/2012; 3 System.out.println(sayi2); Istisnalar: ! Java'da ondalık sayı türünde 2 tane veri tipi vardır. Bunlar; float ve double'dır. Bilgisayarda ondalık sayıları tutabilmek için Java, IEEE 754 standardını kullanır. CHAR Uzunluğu 16 bittir. Karakter türünde değerler alır. İçerisinde yalnızca bir harf, rakam veya işaretgirilebilir. Girilen bu değerler çift tırnak değil tek tırnak arasına yazılmalıdır. Bu veri tipinde de büyüktür - küçüktür gibi karşılaştırmalar da yapılabilir. Varsayılan değeri \u0000'dır. char deger1='M'; 1 char deger2='-'; 2 char deger3='8'; // 88 yazsaydık hata verecekti 3 System.out.println(deger1+" "+deger2+" 4 "+deger3); Şu kullanım yanlıştır: 1 char deger = 'xy'; // hatalı kullanım. tek değer alabilir. BOOLEAN Yalnızca 2 değer alır (true veya false). Bellekte 1 bit yer kaplarlar. Varsayılan değeri false'dur. int a=5; int b=6; boolean x=(a==b); //a ile b karşılaştırılır. a ile b eşit olmadığı için false döner ve bu x'e atanır. System.out.println(x); 1 2 3 4 5 Istisnalar: ! Kullanacağımız değer, hangi veri tipine uygunsa onu kullanmalıyız. Değerimiz 50 ise bunu byte tipinde tutmak daha uygun olacaktır. Aksi halde int tipinde tutarsak, bellekte fazla yer kullanılmış olur. Istisnalar: ! JavaSE-7 ile gelen yenilikle beraber sayısal veri tipleri içerisinde altçizgi (_) kullanılabilmektedir. Ders 11 - Referans Tipler Array, Class ve Interface olarak tutabileceğimiz 3 referans tipi vardır. Bunlara girmeden sadecedeğişkenler kısmına bakalım. Referans tiplerde, değişkenlerin adresleri tutulur. Referans tipler, new anahtar sözcüğü ile tanımlanırlar. Referans tipler, belleğin heap alanında tutulurlar. Referans tiplerinde, primitive tiplerden farklı olarak işlemler değişkenin kendisi ile yapılır. Yani primitive değişkenlerdeki gibi kopya üzerinden değil orjinal değer üzerinden işlem yapıldığı için değeri değişir. Şimdi bir örnek yapalım ve farkı görelim. 1 //VeriTipleri.java - 04.04.2014 2 3 public class VeriTipleri 4 { 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public static void main(String[] args) { Deneme d = new Deneme(); d.x=50; System.out.println("Sayının ilk değeri :"+d.x); carp(d); System.out.println("Sayının ilk değeri :"+d.x); } public static void carp(Deneme d) { d.x=d.x*2; } } class Deneme { public int x; } Bu konuda değişkenleri anlatıyoruz, fakat sınıflardan türetme ve nesne gibi olayları anlatmak zorunda kaldık. Nesneye yönelik programlamayı öğrendikten sonra, tekrar bu dersimize göz atabilirsiniz. Burada ddeğişkenini Deneme sınıfından oluşturduk. Deneme sınıfında ise bir değişkenimiz var. Bu değişkene d.x=50diyerek değer atadık ve doğrudan carp() metoduna gönderdik. Burada d.x değişkenimiz yeni bir değer aldı ve artık d.x değerimiz 100 oldu. Eğer kopyası gönderilseydi, yine 50 sayısını elde edecektik. Referans tiplerde değişkenlerin bellekteki adresleri tutulduğundan orjinal değeri de değişir. STRING VERİ TİPİ string, referans tipindedir. string tipi için, char'ların birleşmesinden oluşmuştur diyebiliriz. char'dan farklı olarak çift tırnak içerisinde tanımlanırlar. Karakter dizilerinin birleşmesinden oluşmuştur. String yazi="Okan Bilke"; 1 String yazi2="ElektroArge"; 2 System.out.println(yazi+" 3 "+yazi2); String ifadeleri, çift tırnak içerisinde tanımlanır. Bir string değere, başka bir string değer eklenebilir. Bunlar tek bir değişkende toplanabileceği gibi yukarıdaki gibi ayrı ayrı birleştirilerek de yazılabilir. Bir string değişkeninin değerinin değiştirilmesine örnek verelim. //Degiskenler.java - 04.04.2014 1 2 package com.org.degiskenler; 3 4 public class Degiskenler 5 { 6 public static void main(String[] 7 args) 8 { 9 String deneme="Elektroarge"; 10 deneme=deneme+" Java 11 Dersleri"; 12 System.out.println(deneme); 13 } 14 } 15 deneme adlı değişkene bir ekleme yaptık ve sonucu ekrana yazdırdık. Eklemeleri + operatörü ile yaptık. PRİMİTİVE TİPLERİ, REFERANS TİPİ ŞEKLİNDE YAZMA Bir değişken, ilkel olarak tanımlanmasının yanında o veri tipinin sınıfı ile de tanımlanabilir. Değişkenlerin veri tipleri, aynı zamanda bir sınıf'tır. Bu da demek oluyor ki bilinen şekilde değişkenleri tanımlamanın yanında,sınıftan türetilen bir nesne şeklinde de tanımlayabiliriz. Bunu bir örnek üzerinde gösterelim. //Degiskenler2.java - 04.04.2014 1 2 package com.org.degiskenler; 3 4 public class Degiskenler2 5 { 6 public static void main(String[] args) 7 { 8 int i=5; // primitive tipteki değişken 9 Integer j=new Integer(6); // referans tipindeki 10 değişken 11 System.out.println(i); 12 System.out.println(j); 13 } 14 } 15 16 int i olarak tanımladığımız bir değişkeni, Integer sınıfından türetilen bir nesne aracılığıyla da türetebiliriz. Burada i değişkeninin değeri 5, j değişkeninin değeri ise 6 olmuştur. Sadece int değil, tüm veri tiplerinde bu geçerlidir. Başka bir örnek verirsek; //Degiskenler3.java - 04.04.2014 1 2 package com.org.degiskenler; 3 4 public class Degiskenler3 5 { 6 public static void main(String[] args) 7 { 8 int i=3; // yerel değişken 9 Integer j=new Integer(4); // referans tipteki değişken 10 String s="Okan Bilke"; // yerel değişken 11 String s1=new String("ElektroArge"); // referans tipteki 12 değişken 13 double x=457.2; // yerel değişken 14 Double y=new Double(378.3); // referans tipteki değişken 15 System.out.println(i); 16 System.out.println(j); 17 System.out.println(s); 18 System.out.println(s1); 19 System.out.println(x); 20 System.out.println(y); 21 } 22 } 23 24 Referans tipteki değişkenleri görüldüğü gibi new ile oluşturduk. Bu şekilde tanımlama yapmanın arasında belirli farklar vardır. Dediğimiz gibi primitive ve referans tipleri arasındaki farklar burada da geçerlidir. Normal değişken tanımlaması yaptığımızda, bu değişken belleğin stack kısmında tutulur. Aynı değişkeni nesne türeterek tanımladığımızda ise heap alanında tutulur. Bunlardan yola çıkarak şunu diyebiliriz ki; int veri tipi, Integer sınıfının bir öğesidir. Yani Integer sınıfı,int tipini sarmalar. Buna wrapper denir. Bu sadece int tipinde değil tüm veri tiplerinde geçerlidir. Buradaki integer ve int tipinde değişken tanımlamadaki farkların birkaçından daha bahsedecek olursak şunları söyleyebiliriz: 1. Integer tipinde tanımlanmış bir değişken, java.lang.Integer sınıfının metodlarını kullanabilirken inttipinde tanımlanmış değişken bunları kullanamaz. 2. Primitive değişkenler(int, byte vs.) serileştirme işlemine tabi tutulamazlar. Bunu daha sonra göreceğiz. 3. Integer tipindeki bir değişkene null değerini verebiliriz, fakat int tipinde bu mümkün değildir. Ders 12 - Boxing ve Unboxing Kavramı Anlattığımız gibi bu değişkenler hem primitive olarak tanımlanır hem de bunun sınıflarındantanımlanabilir. Bu şekilde primitive tiplerin, bu sınıflar içerisine gömülmesine kutulama(boxing) denir. Bunun tersi olarak da sınıf nesnelerinin ilkel tiplere dönüştürülmesine de kutu açma(unboxing) denir. Bunları derleyici otomatik olarak yapar. Bunlara örnek verirsek: public static void main(String[] 1 args) 2 { 3 int a=5; 4 Integer b=new Integer (a); // 5 Boxing 6 int y=b.intValue(); //Unboxing } Tip dönüşümleri konusunu öğrendikten sonra bu unboxing ve boxing işlemlerini daha iyi anlayabilirsiniz. Bu işlemler Java 5.0'da otomatik olarak yapılıyor. Normalde b değişkeni bir nesne olduğu için bunun değerini artıramayız. Bunu yapabilmek için boxing işlemine ihtiyaç vardır. Yani bunu ilkel bir tipe dönüştürmeliyiz. Daha sonra ihtiyaca göre tekrar referans tipine dönüştürebiliriz. Bu gibi işlemler için boxing ve unboxing kullanılır. Ders 13 - Lokal Değişkenler Oluşturduğumuz programlarda 3 tip değişken bulunur. Bunlar orjinal isimleriyle local variables, classvariables ve instance variables'dir. Sınıf (class) değişkenlerini, nesneye yönelik programlama dersinde anlatacağız. Instance değişkenler ise sınıf içerisinde, fakat metodların dışında tanımlanır. Bunlara nesnedeğişkenleri de denir. Her nesne için ayrı ayrı oluşturulur. Bu da nesneye yönelik programlama dersinde anlatılacaktır. Bu başlık altında lokal değişkenleri inceleyeceğiz. Döngü içerisinde veya bir metod içerisinde tanımladığımız değişkenlerin yaşam süresi, o döngü veya metod bloklarından çıkana kadardır. Bloktan çıktığı zaman değişkenin sakladığı değer kaybolur. Burada tanımladığımız bir değişkene dışardan erişemeyiz. Bunlara lokal değişkenler denir. Bir metodun içerisinde tanımladığımız i değişkeni ile başka bir metodda tanımladığımız i değişkenleri birbirinden bağımsızdır. Herhangi birinde yapacağımız değişiklik diğer değişkeni etkilemez. Local değişkenlere bir örnek verelim. //Degiskenler.java - 04.04.2014 1 2 package com.org.degiskenler; 3 4 public class Degiskenler 5 { 6 public static void main(String[] args) 7 { 8 for(int i=0;i<5;i++) 9 { 10 int toplam=1; 11 toplam+=toplam; 12 } 13 System.out.println(toplam); 14 //erişilemez 15 } 16 } 17 18 Bu örnekte toplam değişkeni for döngüsü içerisinde tanımlandığı için döngüden çıkıldığı anda değeri kaybolur ve bellekten silinir. Bu döngü dışında değişkene erişmeye çalıştığımızda hata alacağız. Bu örnekte döngüleri kullandık. Bunun tanında metodlar içerisinde de yerel değişkenler kullanımına örnek verelim. //Degiskenler2.java - 04.04.2014 1 2 package com.org.degiskenler; 3 4 public class Degiskenler2 5 { 6 public static void main(String[] 7 args) 8 { 9 int sayi=4; 10 metod(sayi); 11 System.out.println(sayi); 12 } 13 static void metod(int sayi) 14 { 15 sayi=sayi*5; 16 } 17 } 18 19 Bu örnekte sayımızı 5 ile çarptık, fakat sonuç olarak 4 değeri döndü. Çünkü biz sayi değişkenimizi yerelolarak tanımladık. Bir metod içerisinde, o sayıyı 5 ile çarpsak da metoddan çıkınca, sayımız yine eski değerine döndü. Ders 14 - Sabit Tanımlama Sabitler, değeri değiştirilemeyen değişkenler için kullanılır. Programımızın herhangi bir yerinde değerinin değişmesini istemediğimiz değişkenleri sabit olarak tanımlarız. Java'da sabit tanımlama final anahtar kelimesi ile yapılmaktadır. Bu anahtar kelimenin birçok görevi bulunmaktadır. Biz burada sadece sabitler tanımlamasını anlatacağız. Diğer görevlerini ve final anahtar kelimesinin detaylı anlatımını, Kalıtım bölümünde inceledik. Sabitler ile ilgili söyleyeceğimiz ilk şey, bu değişkenlerin ilk değer atanması zorunluluğu vardır. İlk değerleri atanmadan kullanılamazlar. Ya tanımlandığı ilk anda değeri verilecek ya da yapıcılar ile değeri atanacak. Sabit tanımlamak için değişkenimizin başına final anahtar kelimesini getiriyoruz. Örnek sabit tanımlaması final int x=5; // final ile sabit 1 tanımlaması Eğer ilk değer ataması yapmasaydık, yani aşağıdaki gibi bir kullanım yapsaydık hata alacaktık. final String ad; 1 System.out.println(ad); // hata alırız. ilk değer 2 verilmedi Sabitleri tanımlayıp başka satırda ilk değer vermeye çalışırsak da hata alırız. Eğer sabitimizi metod içerisinde tanımlamadıysak, tanımlandığı satırda değeri verilmelidir. Örnek verirsek; 1 final String a; 2 a="Deneme"; // hatalı kullanımdır Burada bir istisna vardır. Sabitimizi eğer bir metod içerisinde tanımladıysak, başka bir satırda da ilk değer verebiliriz. Şimdi hem main metodu içerisinde hem de metod dışarısında sabit tanımlayalım ve farkını görelim. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 //Degiskenler.java - 04.04.2014 public class Degiskenler { final String x1; // metod dışında tanımlandı x1="Metod dışında"; // hatalıdır public static void main(String[] args) { final String x2; // metod içinde tanımlandı x2="Metod İçinde"; // başka satırda da ilk değer atanabilir } } Yukarıdaki örneğimizde metod içinde ve dışında sabit tanımladık. Metod içinde tanımlarsak, ilk değerini alt satırda da verebiliriz. main de bir metod olduğu için, programımızın başladığı bu yerde de tanımlama yaparsak başka satırda ilk değerini verebiliriz. Sabitlerin değerinin başka bir yerde değiştirilemeyeceğini söylemiştik. Bu şekilde hatalı bir kullanıma örnek verelim ve sabitimizi başka bir yerde değiştirmeye çalışalım. final byte sayi=4; 1 System.out.println(sayi); 2 sayi=40; // sabitlerin değeri 3 değiştirilemez Sabitlere en iyi örnek PI sayısı verilebilir. Sabitlere ilk değer vermenin diğer yolu da yapıcılarkullanmaktır. Bu yöntemi ise Kalıtım dersinde anlatacağız. Bunun için yapıcının da ne olduğunu bilmemiz gerekiyor. final anahtar kelimesinin detaylı kullanımı, Kalıtım dersinde daha detaylı işlenmiştir. Ders 15 - Tip Dönüşümleri Veri tipleri konusunu görmüştük. Kullanım amaçlarına göre farklı veri tipleri vardır. Bu veri tipleri arasında bir dönüşüm ihtiyacı hissedebiliriz. Mesela, nasıl bir ihtiyaç? Diyelim ki kullanıcıdan bir sayı aldık. Bu sayı ile matematiksel işlemler yapmak istiyorsak, bu sayıyı int tipine dönüştürmemiz gerekir. Çünkü kullanıcının girdiği sayı, string tipinde alınır. Başka bir örnek verirsek, küsüratlı bir sayının küsüratlarını almak için de kullanabiliriz. Istisnalar: ! Bir değişkeni kendinden daha büyük tipteki değişkenlere cast ettiğimizde, veri kaybı olmaz. Fakat kendinden daha küçük tipteki bir değişkene cast ettiğimizde, veri kaybı olabilir. Bunu bir valizdeki eşyaların, daha küçük boyuttaki bir valize yerleştirilmesi gibi düşünebiliriz. İlk olarak string int tipine dönüştürmeyi görelim. Bunun için 2 yol vardır. Bunlar parseInt ve valueOfmetodlarıdır. String degisken="5"; 1 int 2 yeni1=Integer.valueOf(degisken); 3 int yeni2=Integer.parseInt(degisken); Burada 5 sayısını string olarak tanımladık. Bunun üzerinde matematiksel işlem yapabilmek için bunu inttipine cast etmemiz gerekiyor. Bunun için Integer sınıfının 2 metodu kullanabiliriz. Bu her iki metod da sayımızıint'e çevirir. Fakat arasında bazı farklar var. valueOf metodu, parseInt metoduna göre daha yavaştır. AyrıcaparseInt metodu int tipinde bir veri tipi döndürürken, valueOf metodu ise integer tipinde bir nesne döndürür. Bir örnek verelim: Eğer bu örnekte degisken adlı değişkenimiz int tipine cast etmeseydik, üzerinde sayısal işlem yapamazdık. Şimdi ise int tipinden string tipine cast işlemini görelim. Bunun için de 2 yöntem vardır. İlki Stringsınıfının valueOf metodudur. Diğeri ise Integer sınıfının toString metodudur. Görüldüğü gibi 2 şekilde de int tipindeki değişkeni string tipine cast ettik. Buradaki metodlarımız içerisine, cast edeceğimiz değişkeni yazıyoruz. Son olarak da göstermek için ekrana yazdırdık. Konuyu anlatırken cast işlemindeki amacın küsuratları yok etmek olduğunu söylemiştik. Bunun için kullanılan cast işlemleri de vardır. Buna örnek olarak double tipini int tipine dönüştürmeyi örnek verebiliriz. //Degiskenler.java - 04.04.2014 1 2 public class Degiskenler 3 { 4 public static void main(String[] 5 args) 6 { 7 double sayi=345.2; 8 int sayi2=(int)sayi; 9 System.out.println(sayi2); 10 } 11 } 12 13 Burada double sayımızı int'e cast ettik. Bunun için değişkenin başına (int) koymamız yeterli. Gördüğünüz gibi int tipinde küsürat olmadığı için sadece tamsayı olan kısmını aldık. Şimdi ise tam tersi, int tipinden double tipine cast işlemi yapalım. Burada da int tipindeki değişkenimizin başına (double) yazmak yeterli oldu. double tipinde virgülden sonraki kısım olduğu için otomatik olarak 0 sayısını koydu ve ekrana 345.0 yazdı. Aynı şekilde float tipinden long tipine cast işlemi ise: Burada da küsüratları yok etme işlemi yaptık, fakat sadece veri tiplerimiz farklı float veri tipi ondalıklı,long tipi ise tamsayı türünde olduğu için sonuç da bir tamsayı oldu ve küsuratlar kaldırıldı. Bunun da tersini görelim. long tipinden float tipine bir cast işlemi yaptığımızda da sonuna küsuratlar geliyor. Çünkü sonuç bir ondalık olmalı. Bunun sebebi de float'a dönüştürme yapmamızdır. float da bir ondalık sayı türüdür. Dönüştürme işlemlerinde son olarak diğer tiplerdeki değişkenleri, string veri tipine dönüştürmeyi anlatalım. //Degiskenler.java - 04.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Degiskenler2 { public static void main(String[] args) { long a=456363; String deger1=String.valueOf(a); // yöntem 1 String deger2=Long.toString(a); // yöntem 2 float b = 311.123f; String deger3=String.valueOf(b); // yöntem 1 String deger4=Float.toString(b); // yöntem 2 byte c=11; String deger5=String.valueOf(c); // yöntem 1 String deger6=Byte.toString(c); // yöntem 2 } } Son örneğimizde ise diğer veri tiplerini, string veri tipine cast etmeyi anlattık. Her biri için iki yöntem var. Birisi String sınıfının metodu, diğeri ise veri tiplerinin kendisine ait sınıfının metodudur. Ders 16 - Java'da Kullanılan Anahtar Kelimeler Java'da kullanılan anahtar kelimeleri aşağıda listeledik. Bunları derslerimizde anlatacağız. abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long navite new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while Bu anahtar kelimelerin tamamı küçük harfle yazılır. goto ve const artık kullanılmıyor olsa da, Java içerisinde bulunurlar. Ders 17 - Operatörlere Giriş Yazacağımız uygulamalarda gerek matematiksel, gerekse karşılaştırma gibi işlemler yapmak isteyebiliriz. Bunlar bir yazılım için olmazsa olmazlardandır. Örnek verirsek, bir login işleminde kullanıcının girdiği kullanıcı adı ve şifre değerlerinin, veritabanındaki değerleri ile karşılaştırılması gerekir. Hem kullanıcı adı hem deşifrenin uyması durumunda login işlemi tamamlanır. Bunlar her yazılım dilinde operatörler ile sağlanır. Bunların yanında birçok temel işlem operatörler ile yapılır. Şimdi Java'da hangi operatörlerin olduğuna değinelim. Ders 18 - Atama Operatörleri Atama operatörleri, bir değişkeni başka bir değişkene atamak veya bir değişkene bir değer atamak için kullanılır. Bu atama işlemi yapılırken, aynı zamanda aritmetik operatörler de kullanılabilir. Temel atama operatörlerine bir göz atalım. = En temel atama operatörüdür. Atamalar her zaman sağdan sola doğrudur. += Soldaki değere, kendi değeri ile beraber sağdaki değeri de ekleyerek tekrar soldaki değere atar. -= Soldaki değerden, sağdaki değeri çıkararak tekrar soldaki değere atar. *= Soldaki değeri, sağdaki değerle çarparak tekrar soldaki değere atar. /= Soldaki değer, sağdaki değere bölerek sonucu tekrar soldaki değere atar. TEMEL ATAMA OPERATÖRÜ( = ) Temel atama işlemleri = operatörü ile yapılır. Sağdaki değer soldaki değişkene atanır. int a = 5; // a değişkenine 5 değerini atadık 1 int b = a; // b değişkenine a değişkeninin değerini 2 atadık 3 7 = a; // hatalı atama. bir değişken, bir değere atanamaz Örnek üzerinde daha detaylı gösterirsek: 1 //Operatorler.java - 04.04.2014 2 3 public class Operatorler 4 { 5 public static void main(String[] 6 args) 7 { 8 String ad = "Mehmet"; 9 int a = 5; 10 int c = a; 11 System.out.println(ad); 12 System.out.println(a); 13 14 15 16 System.out.println(c); } } Ekran çıktısı: 1 Mehmet 2 5 3 5 DİĞER ATAMA OPERATÖRLERİ( +=, -=, *=, /= ) Bu operatörler, soldaki değerle sağdaki değeri işleme tabi tutar ve sonucu tekrar soldaki değere atar. Aradaki operatör hangisi ise o işlem yapılır. int a; 1 a = a + 5;//a değişkenine 5 değerini ekledik.Bunun kısa yolunu ise alttaki gibi 2 yapabiliriz 3 a += 5; //soldaki a değerine, sağdaki 5 değeri eklenerek tekrar a'ya atandı. 4 a *= 5; //a değeri 10 ile çarpılarak sonuç tekrar a değişkenine atandı. Yukarıda int a; tanımlaması yaptığımız için artık bundan sonraki tanımlarda a değişkeninin başına intyazmaya gerek kalmaz. int a = 20; 1 a *= 5; // a = a * 5; 2 System.out.println(a); // bu kod yüz çıktısını 3 verecektir. Bu operatörlere toplu bir örnek yapalım. 1 //Operatorler2.java - 04.04.2014 2 3 public class Operatorler2 4 { 5 public static void main(String[] 6 args) 7 { 8 int a = 10, b = 20, c = 100, d = 9 40; 10 a += 5; 11 b -= 25; 12 c *= 2; 13 d /= 10; 14 15 16 17 18 19 System.out.println(a); System.out.println(b); System.out.println(c); System.out.println(d); } } Ekran çıktısı: 1 15 2 -5 3 200 4 4 Buradaki 4 değişkenimizin yeni değerlerini çıktıda görüyoruz. Aradaki işaret ne ise, ona göre işlem yapıldı ve sonuç tekrar soldaki değişkene atandı. ÇOKLU ATAMA İŞLEMİ Bir değeri diğerine atama işlemi, çoklu atama şeklinde de olabilir. Yani bir değeri diğerine atarken, aynı zamanda bunu başka bir değere de atayabiliriz. Buna bir örnek verelim. //Operatorler3.java - 04.04.2014 1 2 public class Operatorler3 3 { 4 public static void main(String[] 5 args) 6 { 7 int sayi1 = 3; 8 int sayi2 = 5; 9 int k = sayi1 = sayi2; 10 System.out.println(k); 11 System.out.println(sayi1); 12 System.out.println(sayi2); 13 } 14 } 15 16 Ekran çıktısı: 1 5 2 3 5 5 Burada sayi2'yi sayi1'e atarken, sayi1'i de k değişkenine atmış oluyoruz. Dolayısıyla en sağdaki değer olan sayi2, bütün değişkenlere birden atanmış oluyor ve diğer değişkenler de sayi2'nin değerine sahip oluyorlar. İKİ DEĞİŞKENİN DEĞERİNİN TAKAS YAPILMASI Elimizde olan iki değişkenin değerini yer değiştirmek istersek, ne yapmamız gerekir? Mesela; adeğişkeninde 5 değeri var, b değişkeninde ise 10 değeri var. Biz tam tersi a değişkeninde 10, b değişkeninde 5 değerinin olmasını istiyoruz. Bunu atama operatörünü kullanarak nasıl yaparız, şimdi onu görelim. //Operatorler4.java - 04.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Operatorler4 { public static void main(String[] args) { int a = 5; int b = 10; int c; c = a; // c de 5 değeri var a = b; // a da 10 değeri var b = c; // b de 5 değeri var System.out.println("a değeri " + a); System.out.println("b değeri " + b); } } Ekran çıktısı: 1 a değeri 10 2 b değeri 5 Görüldüğü gibi a değeri 5 iken 10 oldu. b değeri de 10 iken 5 oldu. Yani birbirinin değerini değiş tokuş yaptılar. Bunun için c değişkenini kullandık ve bu değişken geçici olarak değer taşıdı. Ders 19 - İlişkisel Operatörler İlişkisel operatörler, veriler arasında karşılaştırma yapmaya yarar. Bunları şöyle sıralayabiliriz. < küçüktür > büyüktür <= küçük eşittir >= büyük eşittir == eşittir != eşit değildir Bu operatörler iki verinin karşılaştırmasını yapar. Dönen değer boolean türündeki true veya false'dur. Basit bir örnek verelim. 1 int a = 10; 2 int b = 6; 3 System.out.println(a > b); Burada a değerimiz b'den büyük olduğu için ekrana true yazar. Eğer aradaki operatörümüz != olsaydı, bu iki değer birbirinden farklı olduğu için yine true dönecekti. Bu örnekte dönen true değeri, doğrudan ekrana yazdırıldı. Ekrana yazdırmak yerine boolean türünde bir değişkene atayıp, buna göre de işlem yaptırabilirdik. Bu anlattığımızı örneklersek: 1 //Operatorler.java - 04.04.2014 2 3 public class Operatorler 4 { 5 public static void main(String[] 6 args) 7 { 8 int a = 5, b = 6; 9 10 11 12 13 boolean sonuc = a < b; System.out.println(sonuc); } } Ekran çıktısı: 1 true sonuc değişkenine true değeri atanacaktır. Bu şekilde de değişkenleri kontrol edip, sonucu doğrudan boolean tipindeki değişkene atayabiliriz. Başka bir örnek verelim: //Operatorler2.java - 04.04.2014 1 2 public class Operatorler2 3 { 4 public static void main(String[] args) 5 { 6 int x = 10; 7 int y = 16; 8 if (x > y) 9 System.out.println("x y'den 10 büyüktür"); 11 if (x < y) 12 System.out.println("x y'den 13 küçüktür"); 14 } 15 } 16 Ekran çıktısı: 1 x y'den küçüktür Bu örnekte de değişkenlerimizin birbirine göre konumları karşılaştırılmıştır. x değişkeni y'den küçük olduğu için ekrana "x y'den küçüktür" yazacaktır. Bunu if else yapıları ile sağladık. Bu yapılar ile herhangi bir operatörü kullanarak işlem yapabiliriz. if else yapısının kullanımından ileriki derslerimzide bahsedeceğiz. İlişkisel, yani karşılaştırma operatörlerinin daha fazlasını kullanarak bir örnek daha yapalım. //Operatorler3.java - 04.04.2014 1 2 public class Operatorler3 3 { 4 public static void main(String[] args) 5 { 6 int sayi1 = 1; 7 int sayi2 = 2; 8 if(sayi1 == sayi2) 9 System.out.println("Sayılar aynı"); 10 if(sayi1 != sayi2) 11 System.out.println("Sayılar farklı"); 12 if(sayi1 < sayi2) 13 System.out.println("sayi1 daha küçüktür"); 14 if(sayi1 > sayi2) 15 System.out.println("sayi2 daha küçüktür"); 16 if(sayi1 >= sayi2) 17 System.out.println("sayi1, sayi2'den büyük ve 18 eşittir"); 19 } 20 } 21 22 Ekran çıktısı: 1 Sayılar farklı 2 sayi1 daha küçüktür Bu son örneğimizde sayi1 ve sayi2'yi karşılaştırdık. Olabilecek çoğu durum için sonuçları inceledik. Sayıların birbirine olan konumlarına göre ekrana çıktılarımızı yazdık. Ders 20 - Aritmetik Operatörler Aritmetik operatörler, matematiksel işlemler yapmak için kullanılır. Bunları şöyle sıralayabiliriz: + Toplama işlemi yapar. - Çıkarma işlemi yapar. * Çarpma işlemi yapar. / Bölme işlemi yapar. % Mod işlemi yapar, işlem sonucunda kalanı verir. ++ Değeri 1 artırır. -- Değeri 1 azaltır. TEMEL ARİTMETİK OPERATÖRLER ( +, -, *, / ) Bu operatörler, bildiğimiz 4 işlem yapan operatörlerdir. İlk olarak 4 işlem ile ilgili örnek yapalım. //Operatorler.java - 04.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Operatorler { public static void main(String[] args) { int x = 8; int y = 5; System.out.println("Toplama işlemi sonucu: " + (x+y)); System.out.println("Çıkarma işlemi sonucu: " + (x-y)); System.out.println("Çarpma işlemi sonucu: " + (x*y)); System.out.println("Bölme işlemi sonucu: " + (x/y)); } } Ekran çıktısı: 1 Toplama işlemi sonucu: 13 2 Çıkarma işlemi sonucu: 3 3 Çarpma işlemi sonucu: 40 4 Bölme işlemi sonucu: 1 Bölme işleminin sonucunda 1 değeri döner. Bunun sebebi; iki int değerinin bölümünün yine true tipinde olmasıdır. Eğer bunun küsüratlı olmasını istiyorsak, iki değerimizden herhangi birini double veya floatyapmamız gerekirdi. Bu örnekte sonuçları ekrana yazdırırken, değerleri parantez içerisine aldık. Bunu yapmazsak hata alırız. Çünkü + operatörü hem değerleri birleştirir hem de toplama yapar. Yani iki ayrı görevi vardır. Bu görevleri birbirinden ayırt etmek için parantez kullandık. MOD OPERATÖRÜ ( % ) Bu operatör, mod işleminden kalanı bize verir. Mod işlemi yapan (%) operatörüne de bir örnek verelim. 1 2 public class Operatorler2 3 { 4 public static void main(String[] args) 5 { 6 int sayi1 = 40; 7 int sayi2 = 6; 8 System.out.println(sayi1 % sayi2); 9 } 10 } 11 12 13 Ekran çıktısı: 1 4 Görüldüğü gibi % operatörü, iki değeri birbirine bölerek kalanı verir. Bu operatör farklı amaçlar için de kullanılabilir. Genelde tek ve çift sayıları bulmada işe yarar. ( - ) OPERATÖRÜ İLE SAYIYI NEGATİF YAPMA Çıkarma işlemi yapan - operatörü, sayıların negatif olmalarını da sağlar. Pozitif olan bir değeri, negatif değerine çevirir. Buna bir örnek verelim ve çıktısını inceleyelim. 1 2 public class Operatorler3 3 { 4 public static void main(String[] 5 args) 6 { 7 int x = 5; 8 x = -x; 9 System.out.println(x+x); 10 } 11 } 12 13 Ekran çıktısı: 1 -10 Değişkenimiz olan x'in başına - operatörünü koyarak negatif olmasını sağladık ve kendisi ile toplayarak sonucu ekrana yazdırdık. ARTIRMA ( ++ ) VE AZALTMA ( -- ) OPERATÖRLERİ Bu operatörler, bir sayının değerini 1 artırır veya 1 azaltır. Fakat değişkenlerin değerini artıran veya azaltan ++ ve -- operatörlerinde bir istisna vardır. Bu operatörler, değişkenin başına veya sonuna gelebilir. Değişkenden önce ve sonra geldiği zaman ne gibi farklılıklar olduğunu bir örnek üzerinde gözlemleyelim. 1 //Operatorler4.java - 04.04.2014 2 3 public class Operatorler4 4 { 5 public static void main(String[] args) 6 { 7 int sayi1 = 10; 8 int a, b; 9 a = sayi1++; 10 b = sayi1; 11 System.out.println("Sona yazılırsa: " + a); 12 System.out.println("Sayının yeni değeri: " 13 + b); 14 15 16 } } Ekran çıktısı: 1 Sona yazılırsa: 10 2 Sayının yeni değeri: 11 Görüldüğü gibi a değerinin 11 olmasını bekliyorduk, çünkü artırma operatörünü kullandık. Fakat buradaki istisna şudur: Eğer ++ operatörünü sona yazarsak, önce sayi1'i a'ya atar. Böylece a değişkenimiz 10 olur. Daha sonra artırma işlemini yapar. Artırma işlemini yaptıktan sonra sayi1 değişkenimiz 11 olur. Fakat bu 11 değeri, alt satırlarda kullanılır, işlem yapılan satıra yansımaz. Bir alt satırda bu değer 11 olmuştur artık. Şimdi daha karmaşık bir örnek verelim ve çıktısını görelim. //Operatorler5.java - 04.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class Operatorler5 { public static void main(String[] args) { int sayi1 = 20; int a, b, c, d, e, f; a = ++sayi1; b = sayi1--; c = --sayi1; d = ++sayi1; e = sayi1++; f = sayi1; System.out.println("A değeri " + a); System.out.println("B değeri " + b); System.out.println("C değeri " + c); System.out.println("D değeri " + d); System.out.println("E değeri " + e); System.out.println("F değeri " + f); } } Ekran çıktısı: 1 A değeri 21 2 B değeri 21 3 C değeri 19 4 D değeri 20 5 E değeri 20 6 F değeri 21 Kod parçacığımızı baştan inceleyelim... 1. İlk olarak sayi1'i önce artırdık. Daha sonra a'ya atadık. Sayımız 21 oldu. 2. Alttaki satırda 21'i önce b'ye atadık. Daha sonra 1 azaltarak 20 yaptık. Sayımız 20 oldu. 3. Bir alt satırda 20'yi azalttık ve c'ye atadık. Sayımız 19 oldu. 4. Sonra 19'u artırdık ve d'ye atadık. Sayımız tekrar 20 oldu. 5. Daha sonra 20'yi önce e'ye atadık. Daha sonra 1 artırdık. Sayımız 21 oldu. Bu 21 sayısı, alt satırda kullanılabilecek. 6. Son olarak da bu değeri f'ye atayarak bütün değerleri ekrana yazdırdık. Ders 21 - Mantıksal Operatörler Dersimizin başında operatörlerden bahsederken login örneğini vermiştik. Orada kullanılan karşılaştırmalar, mantıksal operatörler ile yapılmaktadır. Lojik devrelerde kullanılan kapı işlemleri de bu operatörler ile yapılır. Bu operatörler ihtiyaca göre farklı amaçlar için de kullanılabilir. Login işleminde hemkullanıcı adının hem de şifrenin uyuşması gerekir. Bunu mantıksal operatörler ile yapabiliriz. Bunun dışında çok farklı kullanım alanları vardır. Şimdi bu operatörleri inceleyelim. & Mantıksal VE(AND) işlemi yapar. Verilen değerleri AND işlemine tabi tutar. | Mantıksal VEYA(OR) işlemi yapar. && Koşullu VE işlemi yapar. Karşılaştırılan iki değerden her ikisi de true olduğu sürece, true döndürür. || Koşullu VEYA işlemi yapar. Karşılaştırılan iki değerden en az biri true olduğu sürece, true döndürür. ! Mantıksal NOT(DEĞİL) işlemi yapar. Verilen boolean tipindeki verinin tersini verir. true ise false, falseise true. ^ Mantıksal XOR işlemi yapar. Verilen iki değeri XOR işlemine tabi tutar. Bir örnek verelim: //Operatorler.java - 04.04.2014 1 2 public class Operatorler 3 { 4 public static void main(String[] args) 5 { 6 String kullanici_adi = "elektroarge"; 7 int sifre = 1234; 8 if (kullanici_adi == "elektroarge" && sifre == 9 1234); 10 System.out.println("Giriş Başarılı"); 11 } 12 } 13 14 Ekran çıktısı: 1 Giriş Başarılı Bu örnekte kullanıcı_adı ve şifrenin her ikisinin de uyuştuğu zaman login işlemi yapılıyor. Bunu sağlamak için mantıksal operatörlerden olan && operatörü kullanılıyor. Bu tip örnekleri çoğaltabiliriz. Yalnızca herhangi birinin doğru olduğu zaman bir işlem yapmak istiyorsak, || operatörünü kullanmamız gerekir. Şimdi geniş kapsamlı bir örnek verelim ve tüm mantıksal operatörleri kullanalım. //Operatorler2.java - 04.04.2014 1 2 public class Operatorler2 3 { 4 public static void main(String[] args) 5 { 6 boolean x = false; 7 boolean y = true; 8 System.out.println("x & y = " + (x & y)); 9 System.out.println("x | y = " + (x | y)); 10 System.out.println("x && y = " + (x && y)); 11 System.out.println("x || y = " + (x || y)); 12 System.out.println("x ^ y = " + (x ^ y)); 13 System.out.println("!x = " + (!x)); 14 System.out.println("(x & y) || (x ^ y) = " + ((x & y) || (x 15 ^ y))); 16 } 17 } 18 19 Ekran çıktısı: 1 x & y = false 2 x | y = true 3 x && y = false 4 x || y = true 5 x ^ y = true 6 !x = true 7 (x & y) || (x ^ y) = true Bu örnekte x yerine false, y yerine true yazdığımız zaman sonuçları rahatlıkla bulabiliriz. Bunun için AND,OR ve XOR gibi işlemlerin doğruluk tablolarını bilmemiz gerekiyor. X Y false false false true true false true true X&Y false false false true X|Z false true true true X xor Y false true true false X! true true false false Y! true false true false Ders 22 - Bitsel Operatörler Programlamada pek fazla kullanılmayan bitsel operatörler, bitleri kaydırmak, tersini almak gibi işlemler için kullanılır. Bu bitsel operatörlerin temel olanlarını gösterelim. ~ Bütün bitlerin tersini alır. 1 ise 0 yapar, 0 ise 1 yapar. & Bitsel olarak VE işlemi yapar. | Bitsel olarak VEYA işlemi yapar. ^ Bitsel olarak XOR işlemi yapar. >> Bitsel olarak sayısı istenilen değer kadar sağa kaydırır. << Bitsel olarak sayısı istenilen değer kadar sola kaydırır. Mesela; 3 sayısını düşünelim. Bu sayı 0011'e karşılık gelir. Diğer bir sayı olarak da 14 sayısını düşünelim. Bu da 1110'a karşılık gelir. Biz 3 ile 14 sayısını AND işlemine tabi tuttuğumuzda, bu sayılara karşılık gelen bitler tek tek AND işlemine tabi tutulur. Yani verilen bir sayı, doğrudan işleme tabi tutulmaz. Bu verilen sayının binary karşılığı işleme tabi tutulur. TEMEL BİTSEL OPERATÖRLER ( ~, &, |, ^ ) Konuya giriş yaparken bu operatörlerin ne anlama geldiğini söylemiştik. Şimdi örnekler üzerinde gösterelim. İşleme tabi tutacağımız ilk sayılar 3 ve 14 olsun. Bunun binary karşılıklarını bilmemiz gerekir. AND İşlemi: Istisnalar: ! 1. sayı = 0011 (3) 2. sayı = 1110 (14) Sonuç = 0010 (2) - (&-AND İşlemi) Bunun örneğini verirsek; 1 //Operatorler.java - 04.04.2014 2 3 4 5 6 7 8 9 10 11 public class Operatorler { public static void main(String[] args) { System.out.println(3 & 14); } } Ekran çıktısı: 1 2 Bu örnekte 3 ile 14 sayısını & operatörü ile AND işlemine tabi tuttuk ve tüm bitleri, birbiri ile işlemi soktuktan sonra 2 sayısını (0010) elde ettik. Bu bitsel operatörlerden XOR işlemi yapan ^ operatörüne örnek verelim. AND İşlemi: Istisnalar: ! 1. sayı = 0011 (3) 2. sayı = 1110 (14) Sonuç = 0010 (2) - (&-AND İşlemi) Örnek verirsek: //Operatorler2.java - 04.04.2014 1 2 public class Operatorler2 3 { 4 public static void main(String[] 5 args) 6 { 7 System.out.println(3^14); 8 } 9 } 10 11 XOR işleminde işleme giren bitler farklı ise sonuç 1 oluyordu, ise sonuç 0 oluyordu. Verdiğimiz 3 ve 14sayılarının aslında binary karşılıklarını XOR işlemine tabi tuttu ve çıkan 1101 sayısını da 10'luk tabana çevirdi ve 13 sayısını verdi. ~ İle Bitlerin Tersini Alma: 1 Sayı = 1101 (13) 2 Sonuç = 0010 (2) Bitlerin tersini alan ~ operatörüne de bir örnek verelim. 3 sayısı, 0011 bitlerine karşılık gelir. Bunu ~ ile işleme sokalım. //Operatorler3.java - 04.04.2014 1 2 public class Operatorler3 3 { 4 public static void main(String[] 5 args) 6 { 7 System.out.println(~3); 8 } 9 } 10 11 Ekran çıktısı: 1 -4 3 olan 0011 sayımızın bütün bitlerini terse çevirirsek 1100 olur. En baştaki bit işaret biti olduğu için sonucumuz negatif oldu. Kalan 100 bitleri de 4'e karşılık gelir. KAYDIRMA OPERATÖRLERİ ( >>, << ) Sağa ve sola kaydırma konusunu örnek üzerinde anlatalım. Yapacağımız işlem 9 sayısını 2 defa sola kaydırmak (9 << 2) ve 9 sayısını 2 defa sağa kaydırmak (9 >> 2) olsun. 1 36 2 2 9 sayısı 1001'e karşılık gelir. Bu sayıyı 2 bit sola kaydırdığımızda bütün bitler 2 kere sola kaydırılır ve en sağdan da 2 tane 0 gelir. Yeni sayımız 100100 olur. Bu da 36'ya karşılık gelir. 9 sayısı 1001'e karşılık gelir. Bu sayısı 2 bit sağa kaydırdığımızda en sağdaki 2 bit kaybolur ve kalan bitler 2 basamak sağa kayar. Yeni sayımız 0010 olur ve bu da 2'ye karşılık gelir. Bitsel operatörlere son bir örnek vererek konumuzu kapatalım. //Operatorler4.java - 04.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Operatorler4 { public static void main(String[] args) { byte x = 6; System.out.println("Sayımız : " + x); System.out.println("~x sonucu: " + ~x); System.out.println("x&3 sonucu: " + (x&3)); System.out.println("x<<2 sonucu: " + (x<<2)); System.out.println("x>>2 sonucu: " + (x>>2)); } } Ekran çıktısı: 1 Sayımız : 6 2 ~x sonucu: -7 3 x&3 sonucu: 2 4 x<<2 sonucu: 24 5 x>>2 sonucu: 1 Ders 23 - Tip Karşılaştırma Operatörü Tip karşılaştırma operatörleri, genelde bir nesnenin, bir sınıfın örneği olup olmadığını belirlemek için kullanılır. Sonuç olarak true veya false döndürür. Basit bir örnek vererek olayı açıklayalım. //Operatorler.java - 04.04.2014 1 2 class Sinif1 3 { 4 } 5 class Sinif2 6 { 7 } 8 public class Operatorler 9 { 10 public static void main(String[] args) 11 { 12 Sinif1 s1 = new Sinif1(); 13 Sinif2 s2 = new Sinif2(); 14 15 if(s2 instanceof Sinif2) 16 System.out.println("s2, Sinif2 nin bir örneğidir"); 17 else 18 System.out.println("s2, Sinif2 nin bir örneği 19 değildir"); 20 } 21 } 22 23 Ekran çıktısı: 1 s2, Sinif2 nin bir örneğidir Burada Sinif1 ve Sinif2'den birer nesne oluşturduk. Bunları if else yapısı içerisinde karşılaştırdık. s2nesnesi, Sinif2'den türetildiyse ekrana bilgi mesajı yazılmasını sağladık. Ders 24 - Operatör Önceliği Matematik işlemlerinde olduğu gibi yazılım dillerinde de işlem önceliği vardır. Çarpma ve bölme işlemi,toplama ve çıkarmaya göre daha önceliklidir. Aşağıdaki kod, çıktı olarak 18 verecektir. //Operatorler.java - 04.04.2014 1 2 public class Operatorler 3 { 4 public static void main(String[] 5 args) 6 { 7 System.out.println(7 + 4 * 8 / 2 8 5); 9 } 10 } 11 Ekran çıktısı: 1 18 Öncelikler, bu şekilde olabileceği gibi parantezler ile de yapılabilir. Parantezler ile öncelik yaparsak; sağdan ve soldan öncelik olarak 2 şekilde incelememiz gerekir. Buna bir örnek verelim. //Operatorler2.java - 04.04.2014 1 2 public class Operatorler2 3 { 4 public static void main(String[] args) 5 { 6 System.out.println(4 + (5 + (2 * 6))); // sağdan 7 öncelikli 8 System.out.println(((3 / 1) * 4) - 6); // soldan 9 öncelikli 10 } 11 } 12 Ekan çıktısı: 1 21 2 6 Parantezler ile işlem yapmayı biliyoruz. Programlama dillerinde de bu şekilde bir yapıdır. Sağdan öncelikli işlemlerde önce en sağdaki parantezdeki işlem yapılır ve sola doğru gidilir. Soldan öncelikli işlemlerde ise bunun tersi geçerlidir. Şimdi operatörlerin öncelik sırasını, yüksekten düşüğe doğru yazalım. 1. Parantezler, dizi elemanına erişme( [] ) 2. Sona yazılan ++ ve -- operatörleri 3. Başa yazılan ++ ve -- operatörleri 4. new ile nesne oluşturma 5. Çarpma, bölme, mod alma (*, /, %) 6. Toplama ve çıkarma, String toplama (+, -) 7. Kaydırma operatörleri (<<, >>) 8. İlişkisel operatörler (<, >, <=, >=) 9. Mantıksal operatörler (&, |, ^) Ders 25 - Kontrol Yapıları Kod yazarken bazı şartlara bağlı olarak, belirlediğimiz bir olayın gerçekleşmesini isteyebiliriz. Basit bir not sistemi düşünelim. Öğrenci, 50'den düşük not aldığında dersten geçemesin. Bunu sağlamak için kontrol yapılarını kullanmamız gerekir. Java'da 3 tür kontrol yapısı vardır. Bunlar; if-else, if-else if ve switchyapılarıdır. Yapmak istediğimiz işlemlere hangi kontrol yapısı uygun oluyorsa, onu kullanırız. IF - ELSE YAPISI Bir öğrenci not sistemi düşünelim. Öğrencinin ortalaması 85'ten yukarı olursa AA, 70 ile 85 arası olursa BA gelmiş olsun. Bunun için if - else yapısını kullanmalıyız. If - else yapısında koşul içerisindeki ifadeden truedöndüğü(koşul doğru olduğu) sürece if bloğuna girer ve (a) bloğundaki işlemler yapılır. Eğer koşuldan falsesonucu dönerse, else kısmına girer ve buradaki (b) bloğu işlenir. Eğer else kısmında bir işlem yapılmasını istemiyorsak, else kısmını yazmadan sadece if deyimini kullanabiliriz. If - else yapısının genel yapısı: 1 if (koşul) 2 { 3 // işlemler (a) 4 } 5 else 6 { 7 // işlemler (b) 8 } If - else yapısının akış şeması: Bunu bir örnekle gösterelim: 1 //IfElseYapısı.java - 04.04.2014 2 3 public class IfElseYapısı 4 { 5 public static void main(String[] args) 6 { 7 int not = 88; 8 if (not > 50) 9 System.out.println("Başarılı"); 10 else 11 System.out.println("Başarısız"); 12 } 13 14 15 } Ekran çıktısı: 1 Başarılı Eğer if veya else kısmında yapılacak işlemler tek bir ifade ise, kod bloğunu süslü parantezler { } içine koymaya gerek yoktur. Ekrana "Başarılı" yazdırmasının yanında başka bir ifade de yazacak olsaydık, aşağıdaki gibi süslü parantezler { } içerisine yazmamız gerekecekti. if (not > 50) 1 { 2 System.out.println("Başarılı"); 3 System.out.println("Dersi 4 Geçtiniz"); 5 } Ekran çıktısı: 1 Başarılı 2 Dersi geçtiniz İlk örneğimizde tek bir ifade olduğu için biz süslü parantezler içerisine koymadık. İfadeden kastımız, sonuna noktalı virgül getirilen her şeydir. if içerisinde kullanacağımız değerleri kendimiz vermek yerine, kullanıcıdan da alabiliriz. Bunu Scannersınıfları ile yapıyoruz. Bu konuyu Scanner Sınıfları derslerinden sonra, tekrar bu derse bakarsanız faydalı olacaktır. 1 //IfElseYapısı2.java - 04.04.2014 2 3 import java.util.Scanner; 4 5 public class IfElseYapısı2 6 { 7 public static void main(String[] args) 8 { 9 Scanner s = new Scanner(System.in); 10 System.out.println("İlk sayıyı girin: "); 11 int sayi1 = s.nextInt(); // ilk sayı alındı 12 System.out.println("İkinci sayıyı girin: "); 13 14 15 16 17 18 19 20 21 int sayi2 = s.nextInt(); // ikinci sayı alındı if(sayi1 > sayi2) System.out.println(sayi1 + ", " + sayi2 + "'den büyüktür."); else System.out.println(sayi1 + ", " + sayi2 + "'den küçüktür."); } } Ekran çıktısı: 1 İlk sayıyı girin: 2 4 3 İkinci sayıyı girin: 4 6 5 4, 6'den küçüktür. Bu örnekte kullanıcıdan iki sayı aldık ve karşılaştırdık. Durumlarına göre ekrana bilgilendirme mesajı yazdırdık. Yalnız bu sayıların eşit olmadığını varsayıyoruz. Çünkü onun kontrolü için bir sonraki konu olan if - else if kontrolünü kullanmaya ihtiyacımız var. IF - ELSE IF YAPISI If else dersinde anlattığımız ilk örnekte 2 tane şartımız vardı. Fakat biz geçti kaldı türünden değil de doğrudan harf notunu (AA - BB) göstermek istiyoruz. Bunun için 2 koşul (if ve else) yetmeyecektir. Ortalama 8 tür harf notu olduğunu düşünürsek, 8 tane şartımız olur. Birden fazla koşul kullanmamız gerektiği için if - else if yapısı kullanılmalıdır. Buna bir örnek verelim: 1 //IfElseIfYapısı.java - 04.04.2014 2 3 public class IfElseIfYapısı 4 { 5 public static void main(String[] args) 6 { 7 int not = 76; 8 if (not > 85) 9 System.out.println("Harf Notu 10 AA"); 11 12 13 14 15 16 17 else if (not < 85 && not >= 70) System.out.println("Harf Notu BA"); else if (not < 70 && not >= 60) System.out.println("Harf Notu BB"); } } Ekran çıktısı: 1 Harf Notu BA Bu örnekte if - else yapısını kullansaydık, yalnızca 2 şartı kontrol edebilirdik. 2'den fazla ihtimal olduğu çinif - else if yapısını kullanmalıyız. Istisnalar: ! Şimdiye kadar verdiğimiz örneklerde if koşulunun içerisine büyükse, küçükse gibi şartlar koyduk. Bunların haricinde eşitse (==), büyük eşitse (>=), eşit değilse (!=) gibi şartlar da koyabiliriz. Bir önceki örnekte olduğu gibi koşul içerisinde birden fazla şartımız varsa, mantıksal operatörler de (&&, ||) kullanılabilir. İÇ İÇE IF YAPILARI IF yapılarını iç içe de kullanabiliriz. Koşula bağlı olarak bir bloğa dallandığımızda, o blok içerisinde tekrar bir kontrol daha yapmak isteyebiliriz. Bunu bir örnek üzerinde gösterelim: 1 //IfElseYapısı3.java - 04.04.2014 2 3 public class IfElseYapısı3 4 { 5 public static void main(String[] args) 6 { 7 int hiz = 110; 8 if (hiz > 90) 9 { 10 System.out.println("Radara 11 girdiniz"); 12 if(hiz >= 90 && hiz < 120) 13 14 15 16 17 18 19 20 21 System.out.println("Cezanız 200 TL"); else if (hiz >= 120) System.out.println("Cezanız 400 TL"); else System.out.println("Hızınız Normal"); } } } Ekran çıktısı: 1 Radara girdiniz 2 Cezanız 200 TL Yukarıdaki örnekte sürücünün hızı 90'dan az ise "Hızınız Normal" yazısını gösteriyor. Eğer hızı 90'a eşit ve büyükse "Radara Giriniz" yazısını gösteriyor ve hızının büyüklüğüne göre cezası belirtiliyor. Son olarak if - else if yapısına bir örnek daha verelim: 1 //IfElseYapısı4.java - 04.04.2014 2 3 public class IfElseYapısı4 4 { 5 public static void main(String[] args) 6 { 7 int dogru = 75, yanlis = 25; 8 double net = dogru - (float)yanlis / 9 4; 10 if(net >= 85) 11 System.out.println("Çok 12 Başarılı"); 13 else if(net >= 70 && net < 85) 14 System.out.println("Orta 15 Seviye"); 16 else if(net >= 55 && net < 70) 17 System.out.println("İdare 18 Eder"); 19 else 20 System.out.println("Kötü"); 21 System.out.println("Netiniz = " + net); } } Ekran çıktısı: 1 İdare Eder 2 Netiniz = 68.75 Burada program başlangıcında, 4 yanlışın 1 doğruyu götürdüğünü düşünerek, net hesaplaması yaptık. Burada yanlışı hesaplarken float'a cast ettik. Bunun sebebi, yanlışların küsüratlı sonuçlar üretebilmesidir. Bunu yapmasaydık bütün netleri tam sayı olarak hesaplayacaktı. SWITCH YAPISI Switch kontrolü, if - else yapısının bir alternatifi olarak oluşturulmuştur. Uzun uzun else if şartları koymak yerine, bunu tek bir switch kontrolü ile yapabiliriz. Fakat bir önceki örneğimizde switch yapısı kullanamayız. Switch kontrolleri belirli bir aralık değil de doğrudan değer kontrolü yapar. O yüzden her if - else yerineswitch yapıları kullanamayız. Mesela; günlerden pazartesi ise şunu yap, Salı ise bunu yap diyebiliriz. Eğer bunu if - else if ile yapsaydık, uzun uzadıya kod yazmamız gerekirdi. switch(i) 1 { 2 case a: // eğer i değeri a'ya eşit ise, bu blok işlenir. 3 break; 4 case b: // eğer i değeri b'ye eşit ise, bu blok işlenir. 5 break; 6 default: // eğer i değeri hiçbirine eşit değil ise, bu blok 7 işlenir. 8 break; 9 } Switch Yapısının Akış Şeması: Switch yapılarına bir örnek vererek açıklayalım: //SwitchYapısı.java - 04.04.2014 1 2 public class SwitchYapısı 3 { 4 public static void main(String[] args) 5 { 6 int i = 2; 7 switch(i) 8 { 9 case 1: 10 System.out.println("Sayımız 1'dir"); 11 break; 12 case 2: System.out.println("Sayımız 2'dir"); 13 break; 14 case 3: System.out.println("Sayımız 3'tür"); 15 break; 16 default: System.out.println("Sayımız 1, 2 veya 3 17 değildir"); 18 break; 19 } 20 } 21 } 22 23 Ekran çıktısı: 1 Sayımız 2'dir Bu yapıda switch içerisine kontrol edeceğimiz değişkeni yazarız. case ile de bunları karşılaştırırız. Switch içerisindeki değişkenin değeri ile case'deki değişken eşleştiği zaman, eşleşen case bloğuna girilir. Her caseifadesinden sonra da break; koymamız gerekir. Eğer koymazsak bir sonraki case ifadesine de girer veSayımız 3'tür ifadesini de ekrana yazdırır. Hiçbir case ifadesinden sonra break koymazsak bütün caseifadelerine girer ve her çıktıyı ekrana yazdırır. Break ifadesine daha sonra tekrar deneyeceğiz. En sona yazdığımız default: ise hiçbir case ifadesine girilmediğinde çalıştırılır. Default ifadesinin yazılma zorunluluğu yoktur, isteğe bağlıdır. Break; ifadesini yazmadığımızda meydana gelebilecek duruma bir örnek verelim: //SwitchOrnekler.java - 04.04.2014 1 2 public class SwitchOrnekler 3 { 4 public static void main(String[] args) 5 { 6 byte x = 10; 7 switch (x) 8 { 9 case 10: System.out.println("Sayımız 10 10 dur"); 11 case 20: System.out.println("Sayımız 20 12 dir"); 13 break; 14 case 30: System.out.println("Sayımız 30 15 dur"); 16 break; 17 default: System.out.println("Geçersiz"); 18 break; 19 } 20 } 21 } Ekran çıktısı: 1 Sayımız 10 dur 2 Sayımız 20 dir Görüldüğü gibi ilk case ifadesinde break; koymadığımız için hem kendi bloğundakini hem de bir sonrakicase bloğundaki ifadeleri ekrana yazdırdı. Her case ifadesinin kendine göre işlem yapması için caseifadelerinden sonra break; koyulur. break; ifadesini ileriki derslerimizde detaylı olarak işleyeceğiz. Ayrıca case ifadelerinde ne kadar komut olursa olsun, komutları süslü parantezler içerisine almak gerekmez. Istisnalar: ! switch içerisinde sadece int tipinde değil; short, byte ve char tipinde değişkenler de yazılabilir. Java SE 7 ile gelen bir özellik ile switch içerisinde String değişkenler de kontrol edilebilmektedir. switch yapısında sadece bir case değeri ile karşılaştırma yapılmayabilir. Yani sayımız hem 1 hem 2 iken, şunları yap diyebiliriz. Bu anlattığımıza bir örnek verelim: 1 //SwitchOrnekler2.java - 04.04.2014 2 3 public class SwitchOrnekler2 4 { 5 public static void main(String[] args) 6 { 7 int sayi = 2; 8 switch(sayi) 9 { 10 case 1: case 3: case 5: case 7: 11 case 9: 12 System.out.println("Sayı 13 tektir"); 14 break; 15 case 2: case 4: case 6: case 8: 16 System.out.println("Sayı 17 çiftir"); 18 19 20 break; } } } Ekran çıktısı: 1 Sayı çifttir Yukarıdaki örnekte birden fazla case ifadesi beraber kullanılmıştır. İleriki derslerimizde de switch yapısını kullanarak çok sayıda örnek yapacağız. Istisnalar: ! switch kontrollerinin içerisinde if else yapıları kullanıldığı gibi if else yapılarının içerisinde de switch yapılarını kullanabiliriz. Ders 26 - Döngüler Oluşturacağımız programlarda bazı olayların tekrarlanmasını isteyebiliriz. Tekrarlanan bu olaylar ile işlemlerimizi daha kolay bir şekilde yaparız. Bu döngülerde belirtilen koşul doğru olduğu sürece döngü içerisidneki komutlar çalışır ve komut dışına çıkıldığında ise döngü biter. Döngüden çıkıldığında ise döngü bitiminden itibaren program çalışmaya devam eder. Java'da while, do - while ve for olmak üzere 3 tip döngü vardır. WHILE DÖNGÜSÜ while döngüsünde, tekrar sayısı belli değildir. Döngü içerisinde oluşturacağımız şartlara göre döngü devam eder veya sonlanır. Belirtilen koşulda true değeri döndüğü sürece döngü çalışır ve false değeri dönüp döngüden çıkınca program, döngünün bittiği yerden çalışmasına devam eder. İken anlamına gelen bu döngü türünde, koşul ... iken, şunları şunları yap diyebiliriz.. Genel Kullanım Şekli: 1 2 3 4 while(koşul) { // işlemler } While Döngüsünün Akış Şeması: Bunu bir örnekle açıklayalım: //WhileDongusu.java - 04.04.2014 1 2 public class WhileDongusu 3 { 4 public static void main(String[] args) 5 { 6 int sayi = 5; 7 while (sayi > 0) 8 { 9 System.out.println("Sayı pozitif, değeri: " + 10 sayi); 11 sayi--; 12 } 13 } 14 } 15 16 Sayımız 5'ten büyük olduğu sürece döngümüz çalışır. Döngü içerisinde ise, sayi değerimiz 1 azaltılır. Değer azaltılıp while döngüsünün tekrar başına gelinir ve bu, sayımız 0 olana kadar devam eder. Değişkenimiz 0 olduğunda ise, while döngüsündeki koşula uymadığı için artık döngüye girilmez. Ekran çıktısı: 1 Sayı pozitif, değeri: 5 2 Sayı pozitif, değeri: 4 3 Sayı pozitif, değeri: 3 4 Sayı pozitif, değeri: 2 5 Sayı pozitif, değeri: 1 Bu döngüde, değişkenimizin artış veya azalış miktarı döngü içerisinde belirtilir. while döngüsünde koşul içerisine sadece int değil, boolean türünde değişkenler de verebiliriz. Eğer döngümüzdeki koşul, while(true)olursa sonsuz döngüye girilir ve eğer break; ile döngüden çıkmazsak, sonsuza kadar while içerisindeki blok işlenir. Örnek üzerinde inceleyelim: //WhileDongusu2.java - 04.04.2014 1 2 public class WhileDongusu2 3 { 4 public static void main(String[] 5 args) 6 { 7 while(true) 8 { 9 System.out.println("Döngü"); 10 System.out.println("Döngü"); 11 System.out.println("Döngü"); 12 break; 13 } 14 } 15 } 16 17 Ekran çıktısı: 1 Döngü 2 Döngü 3 Döngü while(true) dediğimizde sonsuz döngüye girilir. break; ile de istediğimiz yerde döngüyü sonlandırabiliriz. Bir başka örnek yapalım: //WhileDongusu3.java - 04.04.2014 1 2 public class WhileDongusu3 3 { 4 public static void main(String[] args) 5 { 6 int i = 10, j = 0, k = 0; 7 while(i > j) 8 { 9 System.out.println("i, j'den büyük"); 10 i -= 2; 11 j += 2; 12 k++; 13 } 14 System.out.println("Artık büyük değil"); 15 System.out.println("Bu döngü " + k + " kere 16 döndü"); 17 } 18 } 19 20 Ekran çıktısı: 1 i, j'den büyük 2 i, j'den büyük 3 i, j'den büyük 4 Artık büyük değil 5 Bu döngü 3 kere döndü Bu döngü i değeri j'den büyük olduğu sürece dönecektir. Döngü içerisinde, dönüş sayısını tutan kdeğerini her seferinde 1 artırdık. Aynı anda i değerini 2 artırıp j değerini de 2 azalttık. Bu değerler her döngüde birbirine yaklaşacaklar ve i değeri j'den küçük olduğu ilk anda döngüden çıkılacak ve döngü dışından çalışmaya devam edilecektir. Daha sonra da döngü dışındaki iki yazımız ekrana yazılacaktır. DO - WHILE DÖNGÜSÜ Bu döngünün while döngüsünden tek farkı, döngüye girildikten sonra koşula bakıldığı için koşul yanlış olsa bile döngüye en az bir defalığına girilir. Genel Kullanım Şekli: 1 do 2 { 3 // işlemler 4 } while(koşul); Do - While Döngüsünün Akış Şeması: do - while döngüsüne basit bir örnek verelim: //DoWhileDongusu.java - 04.04.2014 1 2 public class DoWhileDongusu 3 { 4 public static void main(String[] args) 5 { 6 int sayi = 1; 7 do 8 { 9 System.out.println("Sayı değişkeni: " + 10 sayi); 11 } while(sayi < 0); 12 } 13 } 14 15 Ektan çıktısı: 1 Sayı değişkeni: 1 Görüldüğü gibi sayımız 0'dan küçük değil, fakat döngüye bir defalığına girildi. Çünkü do fonksiyonu, whilekoşulundan daha önce geliyor. Bunu while döngüsü ile yapsaydık, döngüye hiç girilmeyecekti. Bu döngü tipini, koşul yanlış olsa bile bir kere döngüye girilmesini istediğimiz yerlerde kullanırız. do - while döngüsüne bir örnek daha verelim: //DoWhileDongusu2.java - 04.04.2014 1 2 public class DoWhileDongusu2 3 { 4 public static void main(String[] args) 5 { 6 int x = 100, y = 40, i = 0; 7 do 8 { 9 i++; 10 x -= 10; 11 y += 10; 12 } while (x > y); 13 System.out.println("Döngü " + i + " kere 14 döndü"); 15 } 16 } 17 18 Ekran çıktısı: 1 Döngü 3 kere döndü Döngümüzde her seferinde x'in değerini 10 azaltıp y'nin değerini de 10 artırıyoruz. Bu döngü x, y'den küçük olana kadar devam ediyor. Yani x, y'den büyük olduğu sürece devam eder. Her seferinde de ideğişkenimizi artırarak döngü sonunda, döngünün kaç defa başa döndüğünü hesaplıyoruz. FOR DÖNGÜSÜ Bu döngü türünde bir aralık belirtilir ve bu aralık boyunca döngü çalışır. Genel Kullanım Şekli: for (başlangıç değeri; koşul; artım 1 miktarı) 2 { 3 // işlemler 4 } Döngü içerisindeki şartlar sağlandığı sürece döngü devam eder. İlk olarak değişkenimize başlangıç değeri verilir. Daha sonra ifadede koşul belirtilir, koşul doğru olduğu sürece döngü çalışır ve koşul sona erdiğinde döngüden çıkılır. En sonda ise değişkenimizin artım miktarıverilir. Bu döngü türünde, while döngüsündeki gibi değişkenin değerinin blok içerisinde değiştirilmesi gerekmez. Başlangıç değeri, artım miktarı ve koşul toplu olarak ilk satırda verilir. İlk satırda belirtilen değişkenin her değeri için komutlar 1 kez çalıştırılır. Bu döngü tipi, genelde belirli bir değere kadar olan sayıların toplanması, çarpılması ve olayların belirli sayıda tekrar etmesi için kullanılır. İlk olarak basit bir örnek ile başlayalım: //ForDongusu.java - 04.04.2014 1 2 public class ForDongusu 3 { 4 public static void main(String[] args) 5 { 6 for (int i = 1 ; i <= 10 ; i += 2) 7 { 8 System.out.print(i + " "); // sayı aralarında boşluk 9 bırakır 10 } 11 } 12 } 13 14 Ekran çıktısı: 1 13579 Bu döngüde i değişkenimiz 1'den 10'a kadar, 2 şer 2 şer artacaktır. Bu örnekte değerlerimizi println ile alt alta yazmak yerine arada boşluk bırakarak yan yana yazdık. Istisnalar: ! Burada değişkenimiz for içerisinde tanımlanmak yerine döngünün üst satırında int i; diyerek de tanımlanabilirdi. O zaman for içerisine int i; değil de sadece i yazmak yeterli olacaktı. Şimdi ise for döngüsüne daha gelişmiş bir örnek verelim. Bu örnekte ise 1'den 50'ye kadar olan sayılar içerisinden, 7'ye tam bölünen sayıları ekrana yazdırsın. 1 //ForDongusu2.java - 04.04.2014 2 3 public class ForDongusu2 4 5 6 7 8 9 10 11 12 13 14 15 { public static void main(String[] args) { for (int i = 1 ; i <= 50 ; i ++) { if(i % 7 == 0) System.out.println(i + " Sayısı 7'ye Tam Bölünür"); } } } Ekran çıktısı: 1 7 Sayısı 7'ye Tam Bölünür 2 14 Sayısı 7'ye Tam Bölünür 3 21 Sayısı 7'ye Tam Bölünür 4 28 Sayısı 7'ye Tam Bölünür 5 35 Sayısı 7'ye Tam Bölünür 6 42 Sayısı 7'ye Tam Bölünür 7 49 Sayısı 7'ye Tam Bölünür Istisnalar: ! for içerisinde belirttiğimiz başlangıç değeri, koşul ve artış miktarının yazılma zorunluluğu yoktur. Yalnızca birini yazabilir veya hiçbirini yazmayabiliriz. Eğer hiçbirini yazmazsak, sonsuz döngüye girer. Eğer koşulumuzu yazmazsak da döngümüz sonsuz döngüye girer. Örnek: 1 for (int i = 0 ; ; i++) 2 for ( ; ; ) for döngüsünde artımı yapılacak olan değişkenimiz birden fazla da olabilir. Bir değişkenimiz artarken diğer değişkenimiz azalabilir veya senkron olarak çalışabilir, her ikisi de artabilir. Bu değişkenlerin sayısını artırabiliriz. Fakat değişkenlerin arasına virgül koyulur. Şimdi bu özelliği kullanarak bir örnek verelim: 1 //ForDongusu3.java - 04.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class ForDongusu3 { public static void main(String[] args) { int i, j; System.out.println("Döngü başladı"); for(i = 0 , j = 10 ; i < j ; i++ , j--) { System.out.println(i + " değeri " + j + " den küçüktür"); } System.out.println("Döngü sona erdi"); } } Ekran çıktısı: 1 Döngü başladı 2 0 değeri 10 den küçüktür 3 1 değeri 9 den küçüktür 4 2 değeri 8 den küçüktür 5 3 değeri 7 den küçüktür 6 4 değeri 6 den küçüktür 7 Döngü sona erdi Bu döngü, i değeri j değerinden küçük olana kadar devam eder ve her döngüde i değerinin j değerinden küçük olduğu ekrana yazdırılır. Burada i değeri j'den büyük veya eşit olduğu anda döngüden çıkılır. for döngüsünde dikkat ettiyseniz, değişken olarak hep int kullandık. Bunlar çoğaltılabilir. Örnek olarak değişkenimizi char tipinde kullanalım ve bir örnek verelim: 1 //ForDongusu4.java - 04.04.2014 2 3 public class ForDongusu4 4 { 5 public static void main(String[] args) 6 { 7 int i = 1; 8 for (char x = 'a' ; x <= 'e' ; x++) 9 { 10 11 12 13 14 15 16 System.out.println("Alfabenin " + i + ". harfi = " + x); i++; } } } Ekran çıktısı: 1 Alfabenin 1. harfi = a 2 Alfabenin 2. harfi = b 3 Alfabenin 3. harfi = c 4 Alfabenin 4. harfi = d 5 Alfabenin 5. harfi = e Örnekte görüldüğü gibi x değişkenimizin tipi char'dır. GELİŞMİŞ FOR DÖNGÜSÜ for döngüsünde parantezler içerisine yazdığımız artım miktarı, başlangıç değeri gibi ifadeleri yazmak yerine daha kısa bir şekilde bu döngüyü oluşturabiliriz. Diğer dillerde bu yöntemin adı, foreach döngüleridir. Java'da bu döngüye foreach döngüsü denmez, fakat biz akılda kalması için foreach döngüsü diyelim. Bu döngü, for döngüsünün gelişmiş halidir. Aynı işi daha pratik şekilde yapar. Bu döngü türü, Java 5.0 ile gelen enhanced for loop dediğimiz gelişmiş bir for döngüsüdür. Bir dizinin içerisindeki elemanları listelediğimizi düşünelim. Bunu for döngüsü ile yapmak isteseydik; başlangıç olarak dizinin ilk indisini, bitiş değerini ve artış miktarını vererek dizinin her elemanını ekrana yazmamız gerekirdi. Bunun daha kolay bir yolu olan foreach dediğimiz döngüler ile bu işlemi daha az kod ile yapabiliriz. Bu örnekte, konunun anlaşılması açısından dizileri de kullanmak zorundayız. Dizileri ileriki derslerimizde anlatacağız. 1 //ForeachDongusu.java - 04.04.2014 2 3 public class ForeachDongusu 4 { 5 6 7 8 9 10 11 12 13 public static void main(String[] args) { int [] dizi ={1, 2, 3, 4, 5}; for(int i: dizi) System.out.print(i + " "); } } Buradaki i değişkeni, dizimiz içerisindeki her bir elemanı gösterir. for döngüsünde ise bu, indisi gösterecekti. Ekran çıktısı: 1 12345 foreach döngüsüne bir örnek daha vererek döngüler dersimizi bitirelim. //ForeachDongusu2.java - 04.04.2014 1 2 public class ForeachDongusu2 3 { 4 public static void main(String[] args) 5 { 6 int[] dizi = new int[5]; 7 for(int a = 0 ; a < 5 ; a++) 8 { 9 dizi[a] = 3 * a + a * a; 10 } 11 int b = 1; 12 for (int a : dizi) 13 { 14 System.out.println("Dizinin " + b + ". elemanı = " 15 + a); 16 b++; 17 } 18 } 19 } 20 21 Ekran çıktısı: 1 Dizinin 1. elemanı = 0 2 3 4 5 Dizinin 2. elemanı = 4 Dizinin 3. elemanı = 10 Dizinin 4. elemanı = 18 Dizinin 5. elemanı = 28 İlk for döngüsünde dizimizin içini doldurduk. Diğer for döngümüzde foreach yapısını kullanarak, dizinin elemanlarını ekrana yazdırdık. Burada i değeri, dizinin içerisindeki elemanı gösterir. for döngüsündeki gibi adeğerini artırıp dizi[a] diyerek ekrana yazdırmadık. Buradaki a değeri, döngü içerisinde arka planda artıyor ve her döngüde, dizinin bir sonraki elemanını gösteriyor. Bu örneklerimize dizileri de kullanmak zorunda kaldık. Diziler dersimizden sonra bu örnekleri tekrar incelemeniz yararlı olacaktır. Ders 27 - Break ve Continue İfadeleri break ve continue ifadeleri döngümüzün, if else veya switch yapımızın herhangi bir yerinde kullanılabilir. Örneğin; bir for döngüsünün 1'den 10'a kadar gittiğini düşünelim. Biz 5'ten sonraki değerleri yazdırmak istemiyorsak break ifadesini kullanmalıyız. break ifadesi ile bloktan çıkıldığı gibi döngü de sona erdirilir. breakifadesine switch yapısında çok rastlanır. Eğer sayı 5'e geldiğinde 5'i atlayarak 6'dan devam edilsin istiyorsak, continue kullanmamız gerekir.continue ise istenmeyen değerler için döngünün çalıştırılması istenmiyorsa kullanılır. break ve continue ifadelerinin kullanımına örnek verelim: 1 //Break.java - 04.04.2014 2 3 public class Break 4 { 5 public static void main(String[] args) 6 { 7 int i = 0; 8 while(true) // sonsuz döngü 9 { 10 if (i == 6) 11 { 12 13 14 15 16 17 18 19 20 21 22 System.out.println("i değeri 6 ya eşit oldu"); break; } else { System.out.println("i değeri: " + i); i++; } } } } Ekran çıktısı: i değeri: 0 1 i değeri: 1 2 i değeri: 2 3 i değeri: 3 4 i değeri: 4 5 i değeri: 5 6 i değeri 6 ya eşit 7 oldu Yukarıdaki break örneğinde while (true) ile sonsuz döngüye girdik. Değişkenimiz 6'ya eşit ise; eşit olduğu ekrana yazdırıldı ve çıkıldı. Eğer eşit değilse, değişkenin o anki değeri ekrana basıldı ve değeri 1 artırıldı. Bu döngü sayımız 6 olana kadar dönüyor. Aşağıdaki continue örneğinde ise, 1'den 10'a kadar for döngüsü kuruldu. Değişkenimiz olan i sayısı eğer 2'ye tam bölünmüyorsa; continue ile for döngüsünün bir sonraki değerine atlandı. Eğer 2'ye tam bölünüyorsa değişkenimizin 2'ye bölünebildiği, yani çift sayı olduğu ekrana bastırıldı. 1 //Continue.java - 04.04.2014 2 3 public class Continue 4 { 5 public static void main(String[] args) 6 { 7 int i = 0; 8 for (i = 1 ; i <= 10 ; i++) 9 { 10 11 12 13 14 15 16 17 18 if(i % 2 == 1) continue; else System.out.println(i + " sayısı 2'ye bölünür"); } } } Ekran çıktısı: 2 sayısı 2'ye bölünür 1 4 sayısı 2'ye bölünür 2 6 sayısı 2'ye bölünür 3 8 sayısı 2'ye bölünür 4 10 sayısı 2'ye 5 bölünür for döngüsünden önce i değişkeni tanımlandığı için döngünün içerisinde int i diye belirtmedik. Eğer ideğişkeni 2'ye tam bölünüyorsa, continue ile i'nin o anki değeri atlanıp, doğrudan i'nin bir sonraki değerine geçildi. Ders 28 - Metod Nedir? Metodlar, bir programın ayrılmış küçük parçacıkları olarak adlandırılır. Yapılacak işlemleri, metodlar ile ayrı bir yerde yapabiliriz. Yapılacak olan bu işlemlerden herhangi bir değer dönebilir veya doğrudan bu işlemler yapılıp bitirilebilir. Örneğin; kullanıcıdan iki değer alınsın ve bunlar toplansın, daha sonra ekrana yazdırılsın istiyoruz. Bu işlemleri bir metod ile yapabiliriz. Bu işlemleri metod içerisinde tanımladıktan sonra, bize sadece o metodu çağırmak kalır. Burdaki metoda, kullanıcıdan aldığımız iki değeri göndermemiz gerekir. Çünkü bu iki değeri kullanarak işlem yapması gerekir. Bu tür metodlara parametreli metodlar denir. Eğer biz bu metoda herhangi bir değer göndermeden işlem yaptırmak istiyorsak, kullanacağımız metodlara parametresiz metodlar denir. Şimdi metod kavramını daha yakından inceleyelim. Ders 29 - Metod Oluşturma Genel olarak bir metodun oluşturulma şekli şöyledir: 1 Erişim_Belirleyici Dönüş_Tipi Metod_Adı (parametre listesi) 2 { 3 // Metod gövesi 4 } Erişim Belirleyici: Metoda nasıl erişileceğini belirtir. Yazmak zorunlu değildir. Detaylarını ileriki derslerimizde göreceğiz. Dönüş Tipi: Metoddan dönecek olan değerin tipidir. Bu int, string, Object gibi tipler olabilir. Metod eğer geriye bir değer döndürmüyorsa, void olarak tanımlanmalıdır. Eğer döndürüyor ise, dönüş tipi mutlaka yazılmalıdır. Metod Adı: Metoda verilecek olan isimdir. Daha sonra bu metodu çağırmak istediğimizde bu ismi kullanarak çağıracağız. Parametre Listesi: Bir metoda, kullanılması için göndereceğimiz değerlerdir. Bu değerlerin sırası ve tipi önemlidir. Gönderilecek olan bu değerlerin tipi de belirtilmelidir. Metod Gövdesi: Buraya metodun yapacağı işler yazılır. Ders 30 - Parametresiz Metodlar Parametre almayan metodlar, herhangi bir parametre değeri almadan bir kod bloğunu işleyen metodlardır. Bu metodlar herhangi bir metni ekrana yazabilir, bir değer döndürebilir ve bunun gibi birçok işlemi yapabilir. Şimdi parametresiz metodlara bir örnek vererek örnek üzerinden anlatalım: 1 //Metodlar.java - 02.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Metodlar { public static void main(String[] args) { EkranaYaz(); } static void EkranaYaz() { System.out.println("Bu metod çağırıldı"); } } Ekran çıktısı: 1 Bu metod çağırıldı Bu örnekte main metodumuzun dışında bir metod oluşturduk. Değer döndürmediği için tipini void olarak gösterdik. Yani aynı zamanda bu parametre almayan bir metoddur. Sadece ekrana bir yazı yazdı. Metodumuzun ismi EkranaYaz olarak belirlendi. Bu metod, ekrana bir yazı yazdırıyor. Metodumuzu oluşturduktan sonra main metodu içerisinde bu metodu çağırdık. Çünkü programın başlangıç noktası her zaman main metodudur ve programlar buradan okunmaya başlar. Parametre almayan metodlara başka bir örnek verelim: 1 //Metodlar2.java - 02.04.2014 2 3 public class Metodlar2 4 { 5 public static void main(String[] 6 args) 7 { 8 carp(); 9 } 10 11 static void carp() 12 { 13 System.out.println(3 * 5); 14 15 16 } } Ekran çıktısı: 1 15 Bu programımızda ise carp adında bir metodumuz var. Bu metod; 3 ile 5'i çarparak ekrana yazdırıyor. Parametre alan metodlarda, bu çarptığımız sayıları metoda parametre olarak göndereceğiz. Parametre almayan, fakat geriye değer döndüren metodlara da bir örnek verelim: //Metodlar3.java - 02.04.2014 1 2 public class Metodlar3 3 { 4 public static void main(String[] 5 args) 6 { 7 String isim = yaz(); 8 System.out.println(isim); 9 } 10 11 static String yaz() 12 { 13 return "Mehmet"; 14 } 15 } 16 17 Ekran çıktısı: 1 Mehmet Parametre almadan da geriye değer döndürülebilir. Eğer geriye değer dönecekse dönüş tipi, metodun başına yazılmalıdır. Biz burada void yerine String yazdık, çünkü geriye dönen değer String tipindedir. Daha sonra dönen değeri isim değişkenine attık ve bunu ekrana yazdırdık. Geriye dönmesini istediğimiz değerireturn ile kullanıyoruz. Metodun çağrıldığı yere bu return değeri atanıyor. Bu değeri istersek, doğrudan ekrana yazdırabilirdik. Bu örnekte dönen değeri değişkene attık. Ders 31 - Parametreli Metodlar Bir metoda, kullanması için değerler gönderdiğimizde, bu metod parametreli metod olur. Aldığı bu parametreler ile işlem yapar. Parametre alan metodlarda, parantez içerisine parametrenin önce tipi, sonra da adı yazılır. Birden fazla parametre kullanılacaksa, aralara virgül(,) koyulur. Parametre alan metodlara ilk örneğimizi verelim: //Metodlar.java - 02.04.2014 1 2 public class Metodlar 3 { 4 public static void main(String[] args) 5 { 6 hesapla(5, 7); // metoda parametre gönderdik 7 } 8 9 static void hesapla(int a, int b) // metod parametre aldı 10 { 11 System.out.println(a * b); // parametreler çarpılıp ekrana 12 yazıldı 13 } 14 } 15 16 Ekran çıktısı: 1 35 Bu örnekte, parametre alan bir metod kullandık. main metodumuz içerisinde metodu çağırdık ve parametre olarak 5 ve 7 sayılarını gönderdik. Yani metoda, bu sayıları al ve işlem yap dedik. İstediğimiz kadar parametre gönderebilirdik. Parametre gönderirken değerlerin tipini belirtmek zorunda değiliz. Fakat metodda bu değerleri alırken, parametrelerin tipini belirtmek zorundayız. Bu örnekte de olduğu gibi alınan parametreler int tipindedir. Aldığı bu değerleri çarparak ekrana yazdırır. Bir metod bir parametre alabilir, fakat geriye bir değer döndürme zorunluluğu yoktur. Parametre alan metodlara başka bir örnek verelim: 1 //Metodlar2.java - 02.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class Metodlar2 { static int x, y; public static void main(String[] args) { int a = 5, b = 2; islem (a, b); yaz(); } static void islem(int a, int b) // parametre alan metod { x = a; y = b; } static void yaz() // parametre almayan metod { System.out.println("x değeri: " + x); System.out.println("y değeri: " + y); } } Ekran çıktısı: 1 x değeri: 5 2 y değeri: 2 Bu örnekte islem() adındaki metod, aldığı parametreleri x ve y değişkenlerine atıyor. yaz() metodu ise bu değerleri ekrana yazdırıyor. main metodunda ise bu metodları çağırdık. Şimdi ise parametre alarak değer döndüren metodlara bir örnek verelim: 1 //Metodlar3.java - 02.04.2014 2 3 public class Metodlar3 4 { 5 static int buyuksayi; 6 public static void main(String[] args) 7 { 8 int x = hesapla(7, 2); 9 10 11 12 13 14 15 16 17 18 19 20 21 22 System.out.println("Büyük olan sayı: " + x); } static int hesapla(int a, int b) { if (a > b) buyuksayi = a; else if (a < b) buyuksayi = b; return buyuksayi; } } Ekran çıktısı: 1 Büyük olan sayı: 7 Bu örnekte hesap adındaki metodumuz iki parametre alıyor. Aldığı bu değerlerden büyük olanıhesaplayacak. Bunun için metodun gövdesinde gövdesinde if yapıları ile bunu sağladık. Hangi sayı büyükse, onu buyuksayi adlı değişkene atıyor. Daha sonra metod sonunda bu değeri return buyuksayi; diyerek geri döndürüyor. main metodu içerisinde, bu metodu içerisinde, bu metodu çağırıyoruz ve bize döndürdüğü değeri, aynı satırda x adlı değişkene atıyoruz. Son olarak da bu x değişkenini ekrana yazdırıyoruz. Değer döndüren metodların mantığı bu şekildedir. Yine bu örnekte buyuksayi adlı değişkenimizi static yaptık. Bunun sebebi ise; yine static metodlar içerisinden, aynı zamanda da static olmayan bir değer geri döndürülememesidir.Static Metodlar konusunda bunu daha detaylı anlatacağız. String tipindeki parametreli alıp işlem yapan basit bir örnek verelim: 1 //Metodlar4.java - 02.04.2014 2 3 public class Metodlar4 4 { 5 static String adi, soyadi; // değişkenler static 6 tanımlandı 7 public static void main(String[] args) 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 { DegerAl("Okan", "Bilke"); yazdir(); } static void DegerAl(String ad, String soyad) { adi = ad; soyadi = soyad; } static void yazdir() { System.out.println("Tam isim :" + adi + " " + soyadi); } } Ekran çıktısı: 1 Tam isim: Okan Bilke Yukardaki örnekte DegerAl metodu, aldığı parametreleri adi ve soyadi değişkenlerine atıyor. yazdir()metodu ise, bu String değişkenleri birleştirerek ekrana yazdırıyor. Şimdi ise daha detaylı bir örnek verelim: 1 //Metodlar5.java - 02.04.2014 2 3 public class Metodlar5 4 { 5 public static void main(String[] args) 6 { 7 KokBul(1, 0, -9); 8 } 9 static void KokBul(int a, int b, int c) 10 { 11 double delta = b * b - 4 * a * c; // değişkenler static 12 tanımlandı 13 if(delta > 0) 14 { 15 double x1 = ((-b + Math.sqrt(delta)) / (2 * a)); // ilk kök 16 bulundu. 17 18 19 20 21 22 23 24 25 26 double x2 = ((-b - Math.sqrt(delta)) / (2 * a)); // ikinci kök bulundu. System.out.println("2 kök var kökler: " + x1 + " ve " + x2); } else if (delta == 0) { double x1 = (-b) / (2 * a); // 1 kök bulundu System.out.println("1 kök var kök: " + x1); } else if (delta < 0) System.out.println("Kök yok"); } } Ekran çıktısı: 1 2 kök var kökler: 3.0 ve -3.0 Bu örnekteki metodumuz, 2 dereceli bir denklemin delta yöntemiyle köklerini bulmaktadır. mainmetodumuzda fonksiyona gönderdiğimiz parametreler, denklemin katsayılarıdır. Doğru sonucu bulması için de a2 - 9'un katsayılarını verdik. Bu denklemin köklerini 3 ve -3 olarak bize gösterdi. Eğer deltamız 0'dan büyükse, 2 kökü de buldu. Eğer delta 0 ise; tek olan kökü buldu ve ekrana gösterdi. Bu metod görüldüğü gibideğer döndürmemektedir ve tipi void'dir. Yukarıdaki örnekte a değişkenimiz 1, b değişkenimiz 0 ve c değişkenimiz ise 9'dur. Şimdiye kadar parametreleri kendimiz verdik. Bir de Scanner sınıfını kullanarak kullanıcıdan değer alalım ve işlem yapalım: 1 //Metodlar6.java - 02.04.2014 2 3 import java.util.Scanner; 4 5 public class Metodlar6 6 { 7 public static void main(String[] args) 8 { 9 Scanner s = new Scanner(System.in); 10 System.out.println("Bir sayı girin"); 11 int deger = s.nextInt(); 12 long sonuc = hesapla(deger); 13 14 15 16 17 18 19 20 21 22 23 24 25 26 System.out.println("Çarpım Değeri: " + sonuc); } static long hesapla(int sayi) { int carpim = 1; for(int i = 1 ; i <= sayi ; i++) { carpim *= i; } return carpim; } } Ekran çıktısı: 1 Bir sayı girin 2 6 3 Çarpım Değeri: 720 Bu örnekte aslında faktöriyel işlemi yaptık. Scanner sınıfı ile kullanıcıdan aldığımız değeri degerdeğişkenine attık. Bunu da hesapla() metoduna parametre olarak gönderdik. hesapla() metodunda ise, o sayıya kadar olan tüm sayıları çarptık ve geriye carpim adlı değişkeni döndürdük. Son olarak da bunu ekrana yazdırdık. Scanner sınıfını kullanarak metodlara parametre gönderme örneklerini çoğaltabiliriz. Parametre alan ve almayan metodlar için özetleyici bir örnek yapalım. 1 //Metodlar7.java - 02.04.2014 2 3 public class Metodlar7 4 { 5 static void metod1() 6 { 7 System.out.println("Bu metod parametre almıyor ve değer 8 döndürmüyor"); 9 } 10 static int metod2() 11 { 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 System.out.println("Bu metod parametre almıyor fakat değer döndürüyor"); return 5; } static void metod3(int a) { System.out.println("Bu metod parametre alıyor fakat değer döndürmüyor"); } static int metod4(int x) { System.out.println("Bu metod parametre alıyor ve değer döndürüyor"); return x; } public static void main(String[] args) { metod1(); metod2(); metod3(5); metod4(10); } } Ekran çıktısı: Bu metod parametre almıyor ve değer döndürmüyor 1 Bu metod parametre almıyor fakat değer 2 döndürüyor 3 Bu metod parametre alıyor fakat değer 4 döndürmüyor Bu metod parametre alıyor ve değer döndürüyor Bu örnekte 4 farklı kombinasyonu kullandık. Parametre alıp almamasına ve değer döndürüp döndürmemesine bağlı olarak 4 adet metod yazdık. Daha sonra sırasıyla hepsini tek tek çağırdık ve çağrılan metodların yaptığı işe göre çıktılarını aldık. Ders 32 - Metodlara Dizi Türünden Parametre Geçirmek Metodlara sadece int, double, String tipinde parametreler gönderilmez. Bu örneğimizde de parametre olarak dizi gönderelim: //Metodlar1.java - 02.04.2014 1 2 public class Metodlar1 3 { 4 public static void main(String[] 5 args) 6 { 7 int dizi[] = new int[] {1, 4, 7}; 8 IslemYap(dizi); 9 for(int i: dizi) 10 System.out.println(i); 11 } 12 static void IslemYap(int dizi[]) 13 { 14 for(int i = 0 ; i < 3 ; i++) 15 { 16 dizi[i] = i * i; 17 } 18 } 19 } 20 21 Ekran çıktısı: 1 0 2 1 3 4 main metodunda bir dizi tanımladık ve elemanlarını atadık. Daha sonra bu diziyi IslemYap() metoduna gönderdik. Bu metodda da tüm dizinin elemanlarını, indisinin karesi olacak şekilde değiştirdik. Son olarakmain metodunda yeni diziyi foreach döngüsü ile yazdırdık. Dizi türünden parametre geçirme ile ilgili bir örnek daha verelim: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 //Metodlar2.java - 02.04.2014 import java.util.Scanner; public class Metodlar2 { public static void main(String[] args) { String dizi[] = new String[3]; // 3 elemanlı dizi tanımlaması Scanner s = new Scanner(System.in); for(int i = 0 ; i < 3 ; i++) { System.out.println((i + 1) + " . ismi girin: "); dizi[i] = s.nextLine(); // girilen isimler, diziye atıldı. } yazdir(dizi); // dizi, yazdir() metoduna parametre olarak gönderdik } static void yazdir(String dizi[]) { System.out.println("İsimler: "); for(String i: dizi) // diziyi ekrana yazdırdık System.out.println(i); } } Ekran çıktısı: 1 1 . ismi girin: 2 Okan 3 2 . ismi girin: 4 Onur 5 3 . ismi girin: 6 Göksu 7 İsimler: 8 Okan 9 Onur 10 Göksu Bu son örneğimizde de kullanıcıdan alınan isimleri diziye attık ve bu diziyi metoda gönderdik. Bu metodda da isimleri ekrana yazdırdık. Kullanıcıdan veri alma işlemini Scanner sınıfı ile yaptık. Bunu ilerleyen konularda tekrar anlatacağız. Istisnalar: ! Bir dizi bir metoda gönderilebileceği gibi herhangi bir elemanı da değiştirilmek üzere metoda gönderilebilir. Ders 33 - Metodları Aşırı Yükleme (Overloading) Her bir metod farklı görevler üstlenir ve üstlendiği göreve göre metodlarımızı isimlendiririz. Fakat farklı işlevler yapan, ama aynı isime sahip olan metodlar oluştur oluşturmak istediğimizde karşımıza bir konu daha çıkıyor. Örneğin; int tipinde iki sayıyı çarpan bir hesapla() metodu yapmıştık. Fakat double tipinde de çarpma yapan bir hesapla metodu oluşturmak istiyoruz. İşte burada Overloading kavramı ortaya çıkıyor. İki metodumuzun da isimleri aynı oluyor. Overloading kavramına göre, aynı isimli iki metod olabilir. Fakat bu metodların parametre tipleri, parametre sıraları ve sayılarından herhangi birinin farklı olması gerekir. Şimdi buna bir örnek verelim: //Metodlar.java - 02.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Metodlar { static int metod1(int sayi) { return sayi; } static int metod1(int sayi1, int sayi2) { return sayi1; } public static void main(String[] args) { System.out.println(metod1(5)); System.out.println(metod1(3, 5)); } } Ekran çıktısı: 1 5 2 3 Burada metod1 adında iki tane metod oluşturduk. Aynı isimli metodlar oluşturmak için bunların parametre sıralarının veya parametre sayılarının veya tiplerinin farklı olması gerektiğini söylemiştik. Burada biz iki metodumuzun da parametre sayılarını farklı tuttuk. İlk metod bir parametre, ikinci metod ise iki parametre almaktadır. Parametre sayılarını değil de parametre tiplerini de farklı tutabilirdik. Her iki metod da bir parametre alırdı, fakat birisi int tipinde diğeri ise double tipinde parametre alabilirdi veya sıraları farklı olurdu (double - int). Bu şekilde de Overloading olurdu. main metodunda bu iki metodu da ayrı ayrı çağırdık. İlk çağırma işleminde tek parametre olan 5 değerini gönderdik. Yukarıda da tek değer alan metod çalıştı ve geriye sayi değişkenini döndürdü. Diğer satırda ise iki parametre alan metoda 3 ve 5 değerini gönderdik. Yukarıda ise iki parametre alan metod çalıştı ve bu metod da bize sayi1'i gönderdi. sayi1 ise gönderdiğimiz 3 ve 5 değerlerinden ilki olan 3'tür. Istisnalar: ! Overloading yaparken metodların döndürdüğü değerin bir önemi yoktur. Metodların herşeyi aynı sadece döndürdükleri değer farklı olsaydı Overloading olmazdı. Overloading kavramına bir örnek daha verelim: 1 //Metodlar2.java - 02.04.2014 2 3 public class Metodlar2 4 { 5 static int metod1(int sayi1, double sayi2) 6 { 7 return sayi1; 8 } 9 static int metod1(double sayi1, int sayi2) // parametre sırası 10 farklı 11 { 12 return sayi2; 13 } 14 public static void main(String[] args) 15 { 16 System.out.println(metod1(5, 3.6)); 17 18 19 20 System.out.println(metod1(6.8, 5)); } } Ekran çıktısı: 1 5 2 5 Bu örnekte metod1 adındaki metodumuzu aşırı yükledik. Her iki metod da iki parametre alıyor, fakat parametrelerin sıraları farklı olduğundan metodların aşırı yüklenmesine ters bir durum yoktur. mainmetodunda ise ilk olarak 5 ve 3.6 sayılarını gönderiyoruz. Yani ilk perametresi int, diğer parametresi doubletüründe olan metod çalışacaktır. Bir sonraki satırda ise 6.8 ve 5 değerini gönderiyoruz. Burada da ilk parametresi double, ikinci parametresi int olan 2. metod çalışıyor. Eğer parametre sıraları farklı olmasaydı, hangi metodun kullanılacağı bilinemezdi. Overloading yapmanın amacı da budur. Sadece döndürdükleri değerleri olan metodların aşırı yüklenmeyeceğini söylemiştik. Şimdi bir örnek verelim: 1 //Metodlar3.java - 02.04.2014 2 3 public class Metodlar3 4 { 5 static int metod1() 6 { 7 return 6; 8 } 9 static int metod1() 10 { 11 return 5; // hatalı kullanım 12 } 13 public static void main(String[] 14 args) 15 { 16 System.out.println(metod1()); 17 System.out.println(metod1()); 18 } 19 } 20 Bu örnekte metodlarımızın dönüş tipi aynıdır (int), fakat döndürdüğü değerlerin farklı olması Overloadingiçin yetmiyor. Bu hatalı bir kullanımdır ve hata verecektir. Ders 34 - Metodlarda Özyineleme (Recursion) Recursion, bir metodun belli bir şart sağlanana kadar kendini sürekli olarak çağırmasıdır. Faktöriyel örneğini verirsek, normalde for döngüsü ile bir sayıya kadar olan tüm sayıları çarparak faktöriyel buluyorduk. Bunu recursive metodlar ile de yapabilmemiz mümkündür. Recursive metodlar, döngülerin yerine kullanılabilir. n! = 1 * 2 * 3 * 4 * ... * (n-1) 1 *n Bu faktöriyel örneğinde en üst sayıdan başlanır ve 1 eksiği ile çarpılır. İlk olarak faktöriyel örneğini verelim: //Metodlar.java - 02.04.2014 1 2 public class Metodlar 3 { 4 static int faktoriyel(int sayi) 5 { 6 if(sayi == 1) 7 return 1; 8 else 9 return (sayi*(faktoriyel(sayi 10 1))); 11 } 12 13 public static void main(String[] 14 args) 15 { 16 System.out.println(faktoriyel(5)); 17 } 18 } 19 faktoriyel adlı metodda alınan parametre, eğer 1 ise return 1 ile 1 değeri döndürülüyor. Çarpma işleminde etkisiz eleman 1 olduğu için eğer sayımız 1 ise; sonuç olarak 1 döner ve döngü durur. Eğer 1 değilse gönderdiğimiz parametre ile bu parametrenin 1 eksiğini çarpmak için faktoriyel(sayi 1) yapıyoruz. Bu sayı gittikçe 1'e ulaştığında tekrar return 1 kısmına giriyor ve döngüden çıkılıyor. Recursive metodlar ile yaptığımız bu örneği normal bir döngü ile yapalım: //Metodlar2.java - 02.04.2014 1 2 public class Metodlar2 3 { 4 static int hesapla(int x) 5 { 6 int deger = 1; 7 for(int i = x ; i > 0 ; i--) 8 { 9 deger *= i; 10 } 11 return deger; 12 } 13 public static void main(String[] 14 args) 15 { 16 System.out.println(hesapla(5)); 17 } 18 } 19 20 Ekran çıktısı: 1 120 Bu tür metodlara da iterative metodlar denir. Faktöriyel programını, normal metod ve döngüler ile bu şekilde yapabiliriz. Aynı şekilde bir de gönderilen parametreye kadar olan sayıları toplayan bir recursive metod oluşturalım: 1 //Metodlar3.java - 02.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Metodlar3 { static int topla(int sayi) { if(sayi == 0) return 0; else return (sayi + (topla(sayi - 1))); // kendini sürekli çağırır. } public static void main(String[] args) { System.out.println(topla(10)); } } Ekran çıktısı: 1 55 Bu örnekte de parametre olarak 10 değeri gönderiyoruz. Eğer parametremiz 0 ise return 0 ile döngüden çıkıyoruz. Nasıl ki çarpmada etkisiz eleman 1 ise, toplama da etkisiz eleman 0 olduğu için 0 yaptık. Daha sonra eğer sayımız 0 olmadıysa , bu sayı ile sayının 1 eksiğini topluyoruz. Bunun için de return(sayi - 1) diyerek, sayımızın 1 eksiğini metoda tekrar gönderiyoruz ve böylece kendi içerisinde dönüyor. ! Istisnalar: Recursive metodlar, stack mantığına göre çalışır. Istisnalar: ! Recursive fonksiyonların her çağrılışında, değişkenler için bellekte yeni bir yer ayrılır. Tabiki bu sadece yerel değişkenler için geçerlidir. Bu recursive metodlar için en çok verilen örneklerden birisini daha inceleyelim. Fibonacci sayılarını recursive fonksiyonları ile bulabiliriz. İlk olarak Fibonacci sayılarını recursive fonksiyonlarını ile bulabiliriz. İlk olarak fibonacci sayılarının ne olduğundan bahsedelim. 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 1 55... ... şeklinde giden sayılardır. Her sayı, kendinden önceki iki sayının toplamı şeklinde yazılır. Mesela; 21 sayısı, 13 ile 8'in toplamıdır. Burada 0. eleman 0'dır. 1. eleman 1'dir. 10. eleman ise 55'tir. Bu şekilde devam eder. Biz istenilen indeksteki sayıyı bulmaya çalışacağız. Yani 23. sayımız hangisi olduğunu bulmak istersek, nasıl bir recursive metodu yazmamız gerekir şimdi bunu gösterelim. //Metodlar4.java - 02.04.2014 1 2 public class Metodlar4 3 { 4 static int fibonacci(int x) 5 { 6 if (x <= 1) 7 return x; 8 else 9 return fibonacci(x - 1) + fibonacci(x - 2); 10 } 11 12 public static void main(String[] args) 13 { 14 System.out.println("6. sayı: " + 15 fibonacci(6)); 16 System.out.println("23. sayı: " + 17 fibonacci(23)); 18 } 19 } 20 Ekran çıktısı: 1 6. sayı: 8 2 23. sayı: 28657 Eğer metoda gönderdiğimiz değer 1 ve 1'den küçükse, sonuç olarak gönderdiğimiz değer dönecektir. Eğer 1'den büyükse sayının 1 eksiği ve 2 eksiğinin toplamını geriye değer olarak gönderecektir. mainmetodumuzda ise, kaçıncı indeksteki sayıyı bulmak istiyorsak, onu parametre olarak göndeririz. Recursive metodların başka tipleri olsa da temel mantığı bu şekildedir. Daha karışık ve zor örnekler de verilebilir. Ders 35 - Static Metodlar Static metodların iki kullanım amacı vardır. İlk kullanım amacı, her nesne için aynı işi yapan static bir metod tanımlanır ve bütün nesneler için ayrı ayrı oluşturulmaz. Böylece bellekten kazanç sağlanır. Diğer kullanım amacı ise; nesne oluşturmadan sınıf içerisindeki metoda erişmektir. Bu ön bilgiyi verdikten sonra konumuza giriş yapalım. Nesne oluşturmadan doğrudan metodlara erişmeye bir örnek verelim: //Metodlar.java - 03.04.2014 1 2 public class Metodlar 3 { 4 public static int metod(int a, int b) 5 { 6 return a * b; 7 } 8 public static void main(String[] args) 9 { 10 System.out.println(Metodlar.metod(3, 11 5)); 12 } 13 } 14 15 Ekran çıktısı: 1 15 Yukarıdaki örneğimizde statik bir metod oluşturduk ve bu metoda doğrudan sınıfadı.metodadı ile erişebildik. static anahtar kelimesinin bu amaç için kullanılmasına en iyi örnek Math sınıfının metodlarıdır. Mathsınıfının metodları, static olarak tanımlanmıştır ve bu metodlara sınıf adı ile erişebiliriz. Hemen bir örnek verelim: //Metodlar2.java - 03.04.2014 1 2 public class Metodlar2 3 { 4 public static void main(String[] args) 5 { 6 int a = 3, b = 4; 7 System.out.println((int)Math.pow(a, 8 b)); 9 } 10 } 11 12 Ekran çıktısı: 1 81 Math sınıfının metodları kendi içinde static olarak tanımlanmıştır ve sınıf adı ile erişebiliriz. Yukarıdaki örneğimizde de üs alma işlemi yapan pow() metodunu, nesne oluşturmadan doğrudan Math.pow() ile çalıştırabildik. Şimdi de static metodunun başka bir kullanım amacına bakalım. Statik metodlar, her nesne için ayrı ayrı oluşturulmaz. Bir statik metod tanımlanır ve tüm nesneler bu metodu ortak olarak kullanır. Şimdi buna bir örnek verelim: 1 //Metodlar3.java - 03.04.2014 2 3 public class Metodlar3 4 { 5 public static int x; 6 public static void metod(int a) 7 { 8 x = a; 9 } 10 11 12 13 14 15 16 17 18 19 20 21 public static void main(String[] args) { Metodlar3 m1 = new Metodlar3(); Metodlar3 m2 = new Metodlar3(); m1.metod(5); m1.metod(9); System.out.println(m1.x); System.out.println(m2.x); } } Ekran çıktısı: 1 9 2 9 Yukarıdaki örneğimizde static bir metod tanımladık. Oluşturduğumuz iki nesne ile bu metoda eriştik ve parametre gönderdik. Fakat bu iki nesne için x değerini yazdırmak istediğimizde ikisini de 9 yazdı. Normalde birine 5 diğerine 9 vermiştik. Bunun sebebi; static metodların nesneye değil, sınıfa ait olmalarıdır. En son hangi değeri verirsek, artık o değişkenin değeri o olur. Istisnalar: ! Eğer herhangi bir yerde, alt sınıflarda bu metodun aynısının oluşturulmasını istemiyorsak, bu metodlar staticolarak tanımlanmalıdır. Statik metodların başka bir kullanım amacı da budur. Fakat bunu ileriki derslerimizde göreceğiz. Çünkü bunun için kalıtım konusunu iyi bilmemiz gerekiyor. Istisnalar: ! ! Statik bir metoddan, static olmayan bir metoda erişilmez. Statik bir metoddan ise static olan bir metoda erişilebilir. Istisnalar: Statik metodlar override ve overload edilmezler. MAIN METODU NEDEN STATIC? Program çalıştığında ilk olaran main metodu çalıştırılır ve bu main metodu da bir sınıf içerisinde bulunur. Program ilk çalıştığında herhangi bir nesne oluşturulmaz. Nesne yokken main metoduna erişebilmek için destatic olarak tanımlanması gerekir ki, doğrudan sınıf adını kullanarak metod netodu çalışabilsin. Bu yüzdenmain metodu her zaman static olmalıdır. main metodumuzun public olarak tanımlanmasının sebebi ise; kodu çalıştıran JVM'nin, bu metoda dışarıdan erişebilmesi gerekliliğidir. Buraya kadar oluşturduğumuz static metod ve değişkenleri static olarak tanımlamamızın sebebi; başka yerde oluşturulmasın diye değildi. main metodumuzdan bu metodlara erişebilmek için o metodun da staticolması gerekiyordu. Çünkü biliyoruz ki main metodumuz her şartta static olmalıdır(Bunun sebebini açıklamıştık). Programların başlama noktası da bu main metodudur. Bu main metodundan başka metodlara erişmek gerekiyor. Sadece erişebilmek için metodları static tanımladık. static olan bu main metodundan,static olmayan bir metoda veya değişkene erişilemez. O zaman şöyle bir not ekleyebiliriz: 1 //Metodlar4.java - 03.04.2014 2 3 class Sinif1 4 { 5 static int x = 26; 6 static int y = 64; 7 static void yazdir() // static metod tanımlandı 8 { 9 System.out.println("x ve y değişkenleri: " + x + " ve " 10 + y); 11 } 12 } 13 14 class Sinif2 15 16 17 18 19 20 21 { public static void main(String[] args) { Sinif1.yazdir(); } } Ekran çıktısı: x ve y değişkenleri: 26 ve 1 64 static anahtar kelimesini, nesneye yönelik programlamayı bitirdikten sonra daha iyi anlayacaksınız. Şuan nesne kavramını bilmiyor olabilirsiniz. O yüzden bu örneklerde ne demek istediğimiz karmaşık gelebilir. Nesneye yönelik programlama derslerimizde de Static Metodlara tekrardan bakacağız. Ders 36 - Dizilere Giriş Dizi, klasik tanımı ile bünyesinde aynı tip verilerin tutulduğu bir yapıdır. Diziler ile veriler daha kolay yönetilebilir ve gruplanan bu elemanlara erişim daha kolay olur. Java'daki diziler, diğer dillerden farklı olarak birer nesnedir. Bu özelliği ile yüksek performans ve güvenlik sağlar. Diziler sayesinde aynı tipte olan bu verilerin yönetilmesini kolaylaşır. Günümüzde dizinin yerine, birçok farklı yapılar olsa da dizilere ihtiyaç duyulmaktadır. DİZİ TANIMLAMA ŞEKİLLERİ Java'da dizi tanımlaması şu şekilde yapılır: int[] dizi; // dizi için referans 1 tanımlandı Dizi tanımlarken ilk olarak dizideki elemanların tipi belirtilir (int, String, byte...). Bu dizinin türünü int olarak belirledikten sonra başka türde veri ekleyemeyiz. Daha sonra köşeli parantezler koyulur. Bu köşeli parantezler de değişkenimizin bir dizi olduğunu gösterir. Son olarak dizimizin adı belirlenir. İlerde değişkenlerimize bu dizinin adı ile erişeceğiz. Köşeli parantez, dizi adından sonra da yazılabilir. Burada dizimizin adı dizi'dir. Birkaç dizi tanımlamasına daha örnek verelim. 1 int dizi1[]; 2 String dizi2[]; 3 Object dizi3[]; 4 byte dizi4[]; Birden fazla dizi tanımlaması yapmak istiyorsak, bunu aynı satırda yapabiliriz. Bunun için: 1 int dizi1[], int dizi2[]; Diziyi tanımladık ve şimdi içerisini doldurmamız gerekiyor. Bunun için iki yol var. Öncelikle diziyi tanımladığımız anda içini dolduralım. Bunun için kullanacağımız yapı: int[] dizi = {1, 2, 3, 6, 11, 25, 61, 1 33}; Dizideki elemanları bu yöntemle doldurmak istiyorsak, bunu tanımlandığı satırda yapmamız gerekir. Aksi halde şu kullanım yanlıştır. String dizi[]; 1 dizi = {"Okan", "Bilke"}; 2 // bu derleme hatasına sebep olur. İlk satırda dizi 3 doldurulmalıydı Bu yanlış kullanımda da görüldüğü gibi bu şekilde dizi oluşturmak ve doldurmak yanlıştır. Bunun için bu yöntemde dizi oluşturacaksak, ilk satırda diziyi doldurmalıyız. String dizi[] = {"Okan", 1 "Bilke"}; Dizi oluşturmanın bir diğer yöntemi de new anahtar sözcüğünü kullanmaktır. int[] dizi = new int[10]; // dizi doldurulmadıysa eleman sayısı 1 belirtilir Oluşturduğumuz dizinin 10 elemanlı olduğunu gösterdik ve nesnemizi oluşturduk. Diziyi new ile oluşturursak eleman sayısı belirtmemiz zorunludur. Artık programımızın istediğimiz yerinde dizimize eleman atayabiliriz. Java'da diziler referans tipli nesneler oldukları için new anahtar sözcüğü ile de oluşturulabilirler. Yani diziler nesne oldukları için nesne oluşturmada kullanılan new ile de dizileri oluşturabiliriz. Dizi doldurmada anlattığımız ilk yöntemde, dizi elemanlarını ilk satırda doldurmamız gerektiğini söylemiştik. Eğer ilk satırda doldurmazsak, herhangi bir satırda new anahtar sözcüğünü kullanarak da doldurabiliriz. Bunun için: int dizi[]; // referans oluşturuldu 1 dizi = new int[] {1, 4, 7, 2, 9}; // dizi doldurulduysa eleman sayısı 2 belirtilmez Burada görüldüğü gibi ilk satırda elemanları doldurmadık. Başka bir satırda doldurabilmek için new ile nesne oluşturmalıyız. Normalde diziyi sadece tanımlarsak, dizi için bir referans oluşturmuş oluruz. Daha sonra new ile diziyi oluşturunca da dizi için bir nesne oluşturmuş oluruz. DİZİ ELEMANINA ERİŞME Dizideki her elemanın bir indisi vardır. Dizideki elemanlara bu indis ile erişilir. Dizilerin indisi 0'dan başlar. Bir dizinin elemanına erişmek için parantez içerisine, erişmek istenen elemanın indisi yazılır. int[] dizi = {1, 2, 3, 6, 11, 25, 61, 1 33}; Örnek verirsek: 1 //DizilereGiris.java - 04.04.2014 2 3 public class DizilereGiris 4 { 5 6 7 8 9 10 11 12 public static void main(String args[]) { int[] dizi = {1, 2, 3, 6, 11, 25, 61, 33}; System.out.println(dizi[3]); // 4. elemana erişildi } } Ekran çıktısı: 1 6 Dizinin 3. indisine erişmek istiyoruz. Diziler 0. indisten başladığı için aslında bu, 4. elemana karşılık geliyor. Şimdi de new ile ayrı bir satırda dizimizi doldurarak, dizi içerisindeki bir elemana erişelim: //DizilereGiris2.java - 04.04.2014 1 2 public class DizilereGiris2 3 { 4 public static void main(String args[]) 5 { 6 int dizi[]; 7 dizi = new int[] {1, 2, 3}; // new ile ayrı satırda 8 doldurulabilir. 9 System.out.println(dizi[1]); 10 } 11 } 12 13 Ekran çıktısı: 1 2 Bu örnekte görüldüğü gibi dizimizi tanımladık ve new ile dizimizi ayrı bir satırda doldurduk. Daha sonra da dizimizin 1. indisli elemanına, yani 2. elemanına ulaştık. Normalde köşeli parantezler içerisine dizimizin kaç elemanlı olduğunu yazıyorduk, fakat bu örnekte zaten elemanları doğrudan belirlediğimiz için eleman sayısını yazmasak da hata vermez. DİZİ ELEMANLARINI LİSTELEME İçerisi doldurulmuş bir dizinin elemanlarını basit olarak bir for döngüsü ile listeleyebiliriz. Örnek verirsek: //DizilereGiris3.java - 04.04.2014 1 2 public class DizilereGiris3 3 { 4 public static void main(String 5 args[]) 6 { 7 int dizi[] = new int[5]; 8 dizi = new int[] {1, 6, 9, 3, 2}; 9 for(int a = 0 ; a < 5 ; a++) 10 { 11 System.out.println(dizi[a]); 12 } 13 } 14 } 15 16 Ekran çıktısı: 1 1 2 6 3 9 4 3 5 2 Bu örnekte dizimizin eleman sayısını 5 olarak belirlediğimiz için döngümüzü 5'e kadar devam ettirdik. İlerde dizinin uzunluğunu bulmayı anlattıktan sonra uzunluğunu kullanarak da elemanları listeleyeceğiz. Dizilerin elemanlarına bir for ile eriştik. for döngüleri ile erişmenin yanında kısa yol olan foreach döngüleri ile de erişilebilir. Buna bir örnek verelim: 1 //DizilereGiris4.java - 04.04.2014 2 3 public class DizilereGiris4 4 { 5 public static void main(String args[]) 6 7 8 9 10 11 12 13 14 15 16 17 { int array[] = {11, 22, 33, 44}; for(int i: array) System.out.println(i); String array2[] = {"Okan", "Bilke", "ElektroArge"}; for(String i: array2) System.out.println(i); } } Ekran çıktısı: 1 11 2 22 3 33 4 44 5 Okan 6 Bilke 7 ElektroArge Bu örnekte for döngüsünü kurduk ve döngünün içinde bir değişken tanımladık. Bu değişken dizinin elemanlarını tutuyor. Normal for döngüsünde indis tuttuğu için array[i] diyerek elemana erişebiliyorduk. Dizimiz String ise for içerisindeki değişkenimiz de String olmalı. Yani dizimizin tipi ile değişkenimizin tipi aynıolmak zorundadır. Çünkü int tipindeki bir değişken String tipli tanımlanmış bir dizideki elemanı tutamaz. Istisnalar: ! 1 2 3 4 Java'da int ve byte tipindeki diziler için bir istisna vardır. Bu tipteki dizilere, ' (tek tırnak) içerisinde bir karakteri eleman olarak ekleyebiliriz. Bu elemanı ekrana bastırmak istersek, ASCII kodunu gösterecektir. //DizilereGiris5.java - 04.04.2014 public class DizilereGiris5 { 5 6 7 8 9 10 11 12 public static void main(String args[]) { int dizi[] = new int[] {1, '2', 3}; System.out.println(dizi[1]); } } Ekran çıktısı: 1 50 Bir önceki örnekteki değerleri değiştirerek yeni bir örnek yazdık. Notumuzda anlattığımız gibi bir elemanı tek tırnak içerisinde yazdık. Daha sonra bu elemanı ekrana yazdırdığımızda ASCII kodunu çıktı olarak aldık. Istisnalar: ! Java dilinde diziler, referans tipli oldukları için belleğin heap alanında tutulurlar. OBJECT SINIFINDAN DİZİ OLUŞTURMA Dizilerimizde aynı tipten verileri tutabiliriz demiştik. Fakat bir istisna var. Java'da her sınıf Objectsınıfından türetildiği için karşımıza bu istisna çıkıyor. Eğer dizimizi Object sınıfından oluşturursak içerisine farklı tipte verileri ekleyebiliriz. Örnek vererek gösterelim: 1 //DizilereGiris6.java - 04.04.2014 2 3 public class DizilereGiris6 4 { 5 public static void main(String args[]) 6 { 7 Object dizi[] = new Object[3]; 8 dizi[0] = "Mehmet"; 9 dizi[1] = 2; 10 dizi[2] = 444.3; 11 12 for(int a = 0 ; a < 3 ; a++) 13 14 15 16 17 System.out.println((a + 1) + ". eleman: " + dizi[a]); } } Ekran çıktısı: 1 1. eleman: Mehmet 2 2. eleman: 2 3 3. eleman: 444.3 Dizimizi Object sınıfından oluşturduk. Böylece dizimizde farklı tipteki verileri barındırdık. Java'da basit bir örnek için oluşturduğumuz sınıf bile Object sınıfından türemiştir. Ders 37 - Bir Dizinin Boyutu Bir dizinin boyutu, o dizideki eleman sayısıdır. Dizinin boyutunu bulmak için dizilerin length özelliği kullanılır. Aşağıdaki kod, dizinin boyutunu ekrana basacaktır. //BirDizininBoyutu.java 1 04.04.2014 2 3 public class BirDizininBoyutu 4 { 5 public static void main(String 6 args[]) 7 { 8 int dizi[] = {1, 2, 'a', 5}; 9 System.out.println(dizi.length); 10 } 11 } 12 Ekran çıktısı: 1 4 Dizimizde 4 eleman olduğu için çıktımızı 4 olarak aldık. Fakat dediğimiz gibi 4 elemanlı bir dizinin en fazla 3. indisine ulaşabiliriz. Bunun sebebinin ise; dizilerin indisinin 0'dan başlaması olduğunu söylemiştik. Şimdi dizilerin boyutunu kullanarak bir örnek yapalım: //BirDizininBoyutu2.java - 04.04.2014 1 2 public class BirDizininBoyutu2 3 { 4 public static void main(String args[]) 5 { 6 int dizi1[]; 7 dizi1 = new int[6]; 8 for(int a = 0 ; a < 6 ; a++) 9 { 10 dizi1[a] = a * a; 11 } 12 for(int a = 0 ; a < dizi1.length ; a++) 13 System.out.println("Dizinin " + a + ". elemanı: " + 14 dizi1[a]); 15 } 16 } 17 18 Ekran çıktısı: Dizinin 0. elemanı: 0 1 Dizinin 1. elemanı: 1 2 Dizinin 2. elemanı: 4 3 Dizinin 3. elemanı: 9 4 Dizinin 4. elemanı: 5 16 6 Dizinin 5. elemanı: 25 Yukarıdaki örnekte dizi1 adında bir dizi tanımladık ve ilk değer ataması yapmadık, sadece tanımını yaptık. Bu yüzden bu diziye eleman yerleştirmek istediğimizde new anahtar sözcüğü ile referans ataması yapmamız ve dizi boyutunu vermemiz gerekir. O satırda diziyi doldurmayacaksak boyut verilmez. Daha sonra for döngüsü içerisinde dizinin her elemanına, o elemanının indisinin karesini değer olarak verdik. Diziyi doldurma işlemini tamamladıktan sonra dizinin uzunluğu kadar döngü kurarak elemanları yazdırdık. Bir dizinin uzunluğunun dışında bir işlem yaptığımızda uyarı ile karşılaşırız. Mesela; 3 elemanlı bir dizinin 3. indisli elemanına ulaşmak istersek, hata verir. Bu hata java.lang.ArrayIndexOutOfBoundsExceptionhatasıdır. Bunu örnek üzerinde gösterelim: //BirDizininBoyutu3.java 1 04.04.2014 2 3 public class BirDizininBoyutu3 4 { 5 public static void main(String 6 args[]) 7 { 8 String dizi[] = {"a", "b", "c"}; 9 System.out.println(dizi[3]); 10 } 11 } 12 Ekran çıktısı: Exception in thread "main" 1 java.lang.ArrayIndexOutOfBoundsException: 3 2 at BirDizininBoyutu2.main(BirDizininBoyutu2.java:8) Burada 3 elemanlı bir String dizimiz var. Fakat diziler 0. indisten başladığı için en son elemanın indisi 0 olur. Biz ise 3. indise ulaşmak istediğimiz için hata aldık. Ders 38 - Dizileri Kopyalama Java'da dizileri başka bir diziye kopyalamak isteyebiliriz. Bunu yapabilmek için iki yöntem vardır. İlk yöntem klasik olarak for döngüsü ile bir dizinin elemanlarını diğer diziye atarak yapılır. Anlattığımız ilk yöntem ile ilgili bir örnek verelim: //DizileriKopyalama.java 04.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class DizileriKopyalama { public static void main(String args[]) { int dizi1[] = new int[4]; for(int a = 0 ; a < dizi1.length ; a++) dizi1[a] = a + a; int[] dizi2 = new int[dizi1.length]; for(int a = 0 ; a < dizi1.length ; a++) dizi2[a] = dizi1[a]; for(int a = 0 ; a < dizi2.length ; a++) System.out.println(dizi2[a]); } } Ekran çıktısı: 1 0 2 2 3 4 4 6 Yukarıdaki örnekte diziyi doğrudan kopyaladık. İlk for döngüsünde dizi1'in içini doldurduk. İkinci fordöngüsünde dizi2'nin içerisini, dizi1'in eleman sayısı kadar döngü kurarak doldurduk. Son for döngüsünde ise yeni dizinin elemanlarını yazdırdık. SYSTEM.ARRAYCOPY METODU İLE DİZİYİ KOPYALAMA Dizi kopyalamadaki 2. yöntem ise; System.arraycopy() metodudur. Şimdi bu yönteme bir örnek verelim: 1 //DizileriKopyalama2.java - 04.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class DizileriKopyalama2 { public static void main(String args[]) { int dizi1[] = {1, 3, 5, 7, 9}; int dizi2[] = new int[5]; System.arraycopy(dizi1, 0, dizi2, 0, 5); // hazır metod for(int a = 0 ; a < dizi2.length ; a++) System.out.println("Yeni dizinin " + a + ". elemanı: " + dizi2[a]); } } Ekran çıktısı: 1 Yeni dizinin 0. elemanı: 1 2 Yeni dizinin 1. elemanı: 3 3 Yeni dizinin 2. elemanı: 5 4 Yeni dizinin 3. elemanı: 7 5 Yeni dizinin 4. elemanı: 9 System.arraycopy(dizi1, 0, dizi2, 0, 5}; metodu ile tek satırda kopyalama yaptık. Bu Metodun Kullanım Şekli: System.arraycopy(kaynak dizi, kaynak dizinin başlangıç 1 indisi, hedef dizi, hedef dizinin başlangıç indisi, adedi); Şimdi buradaki kavramları açıklayalım. Kaynak dizi = Kaynak dizinin adı yazılır. Kaynak dizinin başlangıç indisi = Kaynak dizinin kaçıncı indisli elemanından itibaren kopyalanacağı belirtilir. Biz ilk elemandan itibaren kopyalanmasını istediğimiz için 0 yazdık. Hedef dizi = Hangi diziye kopyalayacaksak o dizinin adı yazılır. Hedef dizinin başlangıç indisi = Kaynak diziyi, hedef dizinin kaçıncı indisinden itibaren kopyalanacağını belirtir. Biz bu örnekte kopyalamayı, hedef dizinin ilk indisinden başlayarak yapsın istedik. Adedi = Kopyalanacak olan dizi elemanlarının sayısını belirtir. Ders 39 - Dizileri Sıralama Dizileri sıralamak için birçok yöntem ve algoritma vardır. Biz bu konuyu Array.sort() metodunu kullanarak anlatacağız. ARRAY.SORT METODU İLE DİZİYİ SIRALAMA Dizileri sıralamak için Arrays sınıfının sort() metodu kullanılır. Bu metodu kullanmak istediğinizde Eclipse, sizden java.util.Arrays paketini import etmenizi isteyecektir. Bu metodu kullanabilmek için bu paketi importetmek gerekir. Şimdi dizileri sıralamaya örnek vererek açıklayalım: 1 //DizileriSıralama.java - 04.04.2014 2 3 import java.util.Arrays; // import Edildi 4 5 public class DizileriSıralama 6 { 7 public static void main(String args[]) 8 { 9 int[] dizi = {1, 6, 8, 3}; 10 Arrays.sort(dizi); // dizi sıralandı 11 for(int a = 0 ; a < dizi.length ; a++) 12 System.out.println(dizi[a]); 13 } 14 } 15 16 Ekran çıktısı: 1 1 2 3 3 6 4 8 Dizi içerisinde karışık olarak verilmiş sayıları küçükten büyüğe sıraladık. Arrays sınıfının başka metodları kullanılarak diziler üzerinde işlemler yapılabilir. Bu metod diziyi baştan sona sıralar. Fakat çok kullanılmasa da dizinin belirli bir kısmını sıralamak istersek ne yapmamız gerekir. Yine aynı metodu kullanacağız fakat birkaç parametre vereceğiz. //DizileriSıralama2.java - 04.04.2014 1 2 import java.util.Arrays; // import Edildi 3 4 public class DizileriSıralama2 5 { 6 public static void main(String args[]) 7 { 8 int[] dizi = {1, 8, 6, 3, 7, 2}; 9 Arrays.sort(dizi, 1, 4); // parametre verilerek dizi 10 sıralandı 11 for(int a = 0 ; a < dizi.length ; a++) 12 System.out.println(dizi[a]); 13 } 14 } 15 16 Ekran çıktısı: 1 1 2 3 3 6 4 8 5 7 6 2 Burada verdiğimiz 1 ve 4 parametreleri, 1. ile 4. elemanlar arasındakileri sıralar. Kalan değerler sırasızolarak yazılır. Görüldüğü gibi ilk dört elemanı sıraladı ve kalan iki elemanı sırasız bir şekilde aynen yazdı. Dizileri sıralamak için hazır metodları kullanmak yerine kendimiz de bir algoritma geliştirebiliriz. Ders İçinde Yazılmış Tüm Programlar ve Kodları Ektedir: Ders 40 - Dizilerde Arama Java'da diziler içerisinde bir elemanı aratmak için kullanacağımız yöntem binarySearch yöntemidir. BİNARYSEATCH YÖNTEMİ İLE DİZİLERDE ARAMA İŞLEMİ Bu metod ile aratılan elemanın dizideki indisi bulunur. Eğer eleman dizide yoksa negatif bir değer döner. Kullanacağımız metod Arrays sınıfına ait binarySearch() metodudur. Bu hazır bir metoddur. Bunun yanında farklı arama algoritmaları geliştirilebilir. Bu metod ile dizilerde arama yapmak istersek dizilerin sıralı olması gerekir. Yani bir diziyi önce sıralayıp daha sonra arama yapmamız gerekir. Tabi bu yöntemle arama yapacaksak bu geçerlidir. Eğer sıralamazsak istediğimiz elemanı bulamaz. Bulduğu elemanın indisi, sıralandıktan sonraki indisidir. //DizilerdeArama.java - 04.04.2014 1 2 import java.util.Arrays; 3 4 public class DizilerdeArama 5 { 6 public static void main(String args[]) 7 { 8 int dizi[] = {3, 4, 12, 9, 2, 5}; 9 Arrays.sort(dizi); // önce dizi sıralandı 10 int deger = Arrays.binarySearch(dizi, 12); // 12 elemanı 11 aranıyor 12 if (deger < 0) 13 System.out.println("Bulunamadı"); 14 else 15 System.out.println("Bulundu ve indisi: " + deger); 16 } 17 } 18 19 Ekran çıktısı: 1 Bulundu ve indisi: 5 Bu örnekte önce diziyi sıraladık. Daha sonra Arrays.binarySearch(dizi, 12) metodunu kullanarak 12 değerini dizi adlı dizide arattık. Bize bir değer dönecek. Bu değeri de deger değişkenine attık. Eğer elemanımız dizide yoksa; negatif bir değer dönecektir ve biz de bunu if ile kontrol ettik. Eğer negatif ise "Bulunamadı" diye bir çıktı yazdırdık. Burada bize 5 değeri döndü. Bu değer, dizi sıralandıktan sonra, 12değerinin yeni indisidir. Ders 41 - Dizileri Karşılaştırma Herhangi bir yerde iki diziyi karşılaştırmak isteyebiliriz. Dizileri karşılaştırabilmek için karşılaştıracağımız iki dizinin de aynı tipte olması gerekir. Boolean, byte, char, Ooject, int, long, short ve float tipindeki dizileri karşılaştırabiliriz. Dizileri karşılaştırmak için yine Arrays sınıfının equals() metodunu kullanmamız gerekir. ARRAYS.EQUALS METODU İLE DİZİLERDE EŞİTLİK KONTROLÜ Bu metodu kullanmamız için java.util.Arrays paketini import etmemiz gerekir. Bu metod, dizileri karşılaştırdıktan sonra eşitse true; değilse false döndürür. Dizi karşılaştırmaya örnek verirsek: //DizileriKarsilastirma.java - 04.04.2014 1 2 import java.util.Arrays; 3 4 public class DizileriKarsilastirma 5 { 6 public static void main(String args[]) 7 { 8 char[] dizi = {'r'}; 9 char[] dizi2 = {'y'}; 10 System.out.println(Arrays.equals(dizi, 11 dizi2)); 12 } 13 } 14 15 Ekran çıktısı: 1 false Bu örnekte karşılaştırma yapmak istediğimiz dizinin tipini char olarak ayarladık ve karşılaştırma yapıp sonucu doğrudan ekrana yazdırdık. Başka tipte bir dizi örneği verelim: //DizileriKarsilastirma2.java - 04.04.2014 1 2 import java.util.Arrays; 3 4 public class DizileriKarsilastirma2 5 { 6 public static void main(String args[]) 7 { 8 int[] dizi = {43, 12}; 9 int[] dizi2 = {43, 12}; 10 System.out.println(Arrays.equals(dizi, 11 dizi2)); 12 } 13 } 14 15 Ekran çıktısı: 1 true Dizilerin eşit olabilmesi için hem eleman sayılarının hem de elemanlarının aynı olması gerekir. Ders 42 - Çok Boyutlu Diziler Önceki dizi derslerimizde tek boyutlu diziler kullandık. Boyut kavramını şu şekilde anlatalım. Matrislerde satırlar ve sütunlar vardır. 4x4'lük bir matrisin bütün elemanlarını bir diziye koyarsak, 2. satırın 3. elemanına erişmek isteseydik, bunu tek boyutlu diziler ile yapamazdık. Yapsak bile özel fonksiyonlar oluşturmamız gerekirdi. Bunu uzay sistemindeki x ve y koordinatları gibi düşünebiliriz. Buna 2 boyutlu dizi denir. Dizideki satırlar dizinin bir indisini, sütunlar ise dizinin diğer indisini oluşturur. Eğer bu 2. satır 3. sütundaki elemanın da kendi içerisinde bir dizi oluşturduğunu düşünürsek, bu şekilde oluşan dizilere de n boyutlu dizi denir. ÇOK BOYUTLU DİZİ TANIMLAMASI Örnek olarak Java'da 2 boyutlu dizi tanımlamasını verelim. int dizi[][] = new int[3][3]; // 3 satır 3 sütunlu iki boyutlu bir dizi 1 tanımlandı Kaç boyutlu bir dizi kullanacaksak, o kadar köşeli parantez kullanmalıyız. Tek boyutlu diziler için [], 2 boyutlu diziler için [][], 3 boyutlu diziler için ise [][][] kullanılır. 3 boyutlu olanlardan daha fazlası genelde kullanılmaz. 3 boyutlu bir dizi tanımlaması yapacak olursak: 1 byte UcBoyutluDizi[][][] = new byte [2][3][4]; Bunu 3 boyutlu uzay gibi düşünürsek x'i 2, y'yi 3 ve z boyutunu ise 4 karşılar. Çok boyutlu diziler, dizi içinde dizi gibidir. Dizideki bir elemanın içerisinde birkaç eleman varsa bu çok boyutlu dizi olur. ÇOK BOYUTLU DİZİ ELEMANLARINA ERİŞİM Çok boyutlu dizi elemanlarına erişmek için matris örneğini verelim. Çok boyutlu dizi elemanlarına erişim, tek boyutlu dizilerdeki erişime benzer yapıdadır. Köşeli parantezler içerisine indeksler yazılır. //CokBoyutluDiziler.java - 04.04.2014 1 2 public class CokBoyutluDiziler 3 { 4 public static void main(String args[]) 5 { 6 int matris[][] = new int [][] {{3, 6}, {5, 7 7}}; 8 // çok boyutlu dizi tanımlaması 9 System.out.println(matris[1][1]); 10 } 11 } 12 13 Ekran çıktısı: 1 7 Matrisi tanımladıktan sonra matris[1][1] ile matris adındaki bir dizinin bir nevi 1. indisli elemanının tekrar 1. indisli elemanına eriştik. Dizimizde iki eleman var. İlk eleman {3, 6}'dır. Bunun indisi 0'dır. İkinci elemanımız ise {5, 7}'dir. Bunun indisi ise 1'dir. Java'da dizilerde indislerin sıfırdan başladığını söylemiştik. Daha sonramatris[1][1] ile 1. indisli eleman olan {5, 7}'nin içerisinde 1. indisli eleman olan 7'ye ulaştık. Yani çok boyutlu dizilerde dizinin elemanı içerisinde tekrar başka bir elemanına erişebiliyoruz. Matris mantığı da bu şekildedir. 2 boyutlu dizi içinde konuşursak, satırlar dizinin bir elemanı, bu satırlar içerisindeki elemanlar da (sütun) dizinin 2. elemanıdır. Buna bir örnek verirsek: //CokBoyutluDiziler2.java - 04.04.2014 1 2 public class CokBoyutluDiziler2 3 { 4 public static void main(String args[]) 5 { 6 String dizi[][] = {{"okan", "bilke"}, {"1", 7 "2"}}; 8 System.out.println("Dizinin 2. elemanları: "); 9 System.out.println(dizi[1][0] + " ve " + 10 dizi[1][1]); 11 } 12 } 13 Ekran çıktısı: 1 Dizinin 2. elemanları: 2 1 ve 2 Dizimizde iki eleman var. Bunlardan ilki okan ve bilke'dır. Diğer eleman ise 1 ve 2'dir. Biz 2. elemana ulaşmak istiyoruz, yani 1 ve 2'ye. Bunun için indis olarak 1 yazmamız lazım. Bu 2. elemanının içerisinde de elemanlar olduğu için bu elemanların her birine de 0 ve 1 indisleri ile ulaşmamız gerekiyor. ! Istisnalar: Eğer değeri atanmamış bir elemana erişmek istersek, o dizinin tipi ne ise o tipin default değeri yazdırılır. Bu anlattığımız özelliği örnek üzerinde gösterelim: //CokBoyutluDiziler3.java 05.04.2014 1 2 public class CokBoyutluDiziler3 3 { 4 public static void main(String 5 args[]) 6 { 7 int dizi1[] = new int[1]; 8 String dizi2[] = new String[1]; 9 boolean dizi3[] = new 10 boolean[1]; 11 System.out.println(dizi1[0]); 12 System.out.println(dizi2[0]); 13 System.out.println(dizi3[0]); 14 } 15 } 16 Ekran çıktısı: 1 0 2 null 3 false Bu örnekte üç farklı tipten üç tane dizi oluşturduk ve hiçbirine eleman atamadık. Daha sonra bu dizileri ekrana yazdırmak istediğimizde int tipi için 0, String tipi için null, boolean tipi için ise false değerini ekrana yazdırdı. Çünkü bunlar, bu tiplerin varsayılan değerleridir. Yani bunlar için bir eleman belirlemezsek, varsayılan olanları kullanır. Tabi burada şunu söyleyelim. Dizilerimiz new ile oluşturuldukları için bu şekilde default değer atandı. Eğer new ile oluşturmayıp ekrana yazdırmak isteseydik, aşağıdaki gibi altını çizecekti. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 //CokBoyutluDiziler3.java - 05.04.2014 public class CokBoyutluDiziler3 { public static void main(String args[]) { int dizi1[[]; String dizi2[]; Boolean dizi3[] System.out.println(dizi1[0]); System.out.println(dizi2[0]); System.out.println(dizi3[0]); } } ÇOK BOYUTLU DİZİLERİ LİSTELEME Çok boyutlu dizilere erişme mantığı, tek boyutlu dizilere erişme ile aynıdır. Şuana kadar anlattığımız özelliklerin de olduğu bir örnek verelim ve çok boyutlu dizimizi listeyelim: 1 //CokBoyutluDiziler4.java - 05.04.2014 2 3 public class CokBoyutluDiziler4 4 { 5 public static void main(String args[]) 6 { 7 int dizi[][] = new int[3][3]; 8 for(int a = 0 ; a < 3 ; a++) 9 for(int b = 0 ; b < 3 ; b++) 10 { 11 dizi[a][ b] = a + b; 12 System.out.println("Dizi[" + a + "][" + b + "] =" + 13 dizi[a][ b]); 14 } 15 for(int a = 0 ; a < 3 ; a++) 16 { 17 for(int b = 0 ; b < 3 ; b++) 18 { 19 System.out.print(dizi[a][ b] + "\t"); 20 // \t ile 8 karakter boşluk bırakıldı 21 } 22 23 24 25 26 System.out.println(""); } } } Ekran çıktısı: 1 Dizi[0][0] =0 2 Dizi[0][1] =1 3 Dizi[0][2] =2 4 Dizi[1][0] =1 5 Dizi[1][1] =2 6 Dizi[1][2] =3 7 Dizi[2][0] =2 8 Dizi[2][1] =3 9 Dizi[2][2] =4 10 0 1 2 11 1 2 3 12 2 3 4 Bu örnekte iç içe olan ilk iki for döngüsünde, dizinin her elemanına değer olarak, bulunduğu satır ve sütun indislerinin toplamını verdik. Daha sonraki iç içe iki for döngüsünde ise elemanları 3x3 matris şeklinde yazdırdık. Çok boyutlu diziler için söyleyeceğimiz başka bir özellikten bahsedersek çok boyutlu dizilerde diziler tanımlandıktan sonra tek boyutlu dizilerdeki gibi eleman ekleyebiliriz. Bunun için new anahtar sözcüğünü kullanmamız gerekiyor. 1 //CokBoyutluDiziler5.java - 05.04.2014 2 3 public class CokBoyutluDiziler5 4 { 5 public static void main(String args[]) 6 { 7 String dizi[][]; // dizi için referans tanımlaması 8 dizi = new String[2][2]; // new ile dizi nesnesi 9 oluşturuldu 10 dizi[0][0] = "Okan"; 11 dizi[0][1] = "Bilke"; 12 dizi[1][0] = "Elektro"; 13 dizi[1][1] = "ARGE"; 14 System.out.println("Dizinin elemanları: "); 15 16 17 18 19 20 21 22 23 24 25 for(int a = 0 ; a < 2 ; a++) { for(int b = 0 ; b < 2 ; b++) { System.out.print(dizi[a][ b] + "\t"); } System.out.println(""); } } } Ekran çıktısı: 1 Dizinin elemanları: 2 Okan Bilke 3 Elektro ARGE Burada dizimiz için referans tanımlaması yaptıktan sonra new ile nesne oluşturduk ve dizimizin kaç elemanlı olacağını belirledik. Daha sonra her elemana bir değer atadık. Daha sonra for döngüsü ile de dizimizin elemanlarını matris şeklinde yazdırdık. ÇOK BOYUTLU DİZİNİN UZUNLUĞU Tek boyutlu dizilerde uzunluk bulmayı anlatmıştık. Çok boyutlu dizilerde de bu yöntem aynıdır. Uzunluk bulmak için length özelliği kullanılır. Fakat farklı olarak, dizilerdeki her eleman içerisinde birçok eleman olduğu için bu elemanların da uzunluğunu bulabiliriz. Bunu bir örnekle açıklayalım: 1 3 2 2 3 2 4 3 Burada dizi adındaki dizimiz 3 elemanlıdır. O yüzden ilk çıktımızda 3 verecektir. Dizimizin 0. ve 1. indisli elemanları kendi içerisinde 2 elemana sahiptir, bu yüzden diğer iki çıktı ise 2 olacaktır. Son elemanımızın içerisinde de 3 eleman olduğu için son çıktımız 3'tür. Ders 43 - String[] Args Dizisi Programlarımızı ilk olaran main metodu içerisinden başlar. main metodumuz ise String tipinde argsadında bir tek boyutlu diziyi parametre parametre olarak alır. Bunu argüman olarak yazmadığımızda, yani main metodunda parantezler içerisini boş bıraktığımızda programlarımız çalışacak mı? Bir örnek ile başlayalım. 1 //MainParametresi.java - 05.04.2014 2 3 public class MainParametresi 4 { 5 public static void main() // parametre vermedik 6 { 7 System.out.println("Main Metodu"); 8 } 9 } 10 11 Ekran çıktısı: Error: Main method not found in class MainParametresi, please define the main 1 method as: 2 public static void main(String[] args) Görüldüğü gibi hiçbir parametre vermediğimiz zaman hata ile karşılaşıyoruz. main parametresi, Stringtipinde bir tek boyutlu diziyi parametre olarak almak zorundadır. Peki, bu argümanımızın adı args olmak zorunda mı? Dizimizin adı önemli değildir. Herhangi bir isim vererek parametre geçirebiliriz. Aşağıdaki gibi tanımlama yapabiliriz. 1 //MainParametresi2.java - 05.04.2014 2 3 public class MainParametresi2 4 { 5 public static void main(String[] dizi) // args yerine dizi adı 6 verildi 7 { 8 System.out.println("Main Metodu"); 9 } 10 11 } Peki, bu dizimizin içerisinde hangi elemanlar var? Biz bu parametre içerisindeki elemanları yazdırmak istersek, ne ile karşılaşacağız? //MainParametresi2.java - 05.04.2014 1 2 public class MainParametresi2 3 { 4 public static void main(String[] dizi) // args yerine dizi adı 5 verildi 6 { 7 System.out.println(dizi[0]); 8 } 9 } 10 11 Ekran çıktısı: Exception in thread "main" 1 java.lang.ArrayIndexOutOfBoundsException: 0 2 at MainParametresi2.main(MainParametresi2.java:7) Bu örnekte String tipindeki dizinin ilk elemanını yazdırmak istiyoruz ve hata ile karşılaşıyoruz. Yani bu da demek oluyorki; bu dizimizin içerisinde eleman yok. Bu diziye eleman eklemek için şu adımları takip edelim. 1. Üstteki menüden Run'a tıklayıp Run Configurations diyoruz. Karşımıza aşağıdaki gibi bir ekran gelecektir. 2. Yukarıdaki pencerelerden Arguments'e tıklıyoruz ve Program Arguments kısmına istediğimiz argümanları yazıyoruz. 3. Daha sonra Apply diyerek penceremizi kapatıyoruz. Şimdi ise aşağıdaki programı çalıştırıp çıktısına bakabiliriz. 1 //MainParametresi3.java - 05.04.2014 2 3 public class MainParametresi3 4 { 5 6 7 8 9 10 11 12 13 public static void main(String[] dizi) // args yerine dizi adı verildi { System.out.println(dizi[0]); System.out.println(dizi[1]); System.out.println(dizi[2]); } } Ekran çıktısı: 1 Okan 2 Bilke 3 Elektroarge Argümanları verdikten sonra artık dizimizin elemanlarını ekrana yazdırabiliriz. Bu argümanlar sadece bu proje için geçerlidir. Argümanları girdiğimiz ekranda sol tarafta hangi proje üzerinde çalıştığımızı göreceksiniz. Diğer projeler için bu argümanlar geçerli olmayacaktır. Aşağıdaki resimde görüldüğü yerde hangi proje üzerinde çalıştığımızı görebilirsiniz. Yaptığımız bu çalışma, MainParametresi ve MainParametresi2 projesi üzerinde etki etmeyecektir. Argümanları girerken bir istisnadan bahsedelim. İsimleri girerken soyadları da girdiğimizde bir istisna ile karşılaşırız. Soyadlar için boşluk bıraktığımızda bunlar farklı bir argüman olarak algılanır. Bunu örneğimizde gösterelim. Girdiğimiz argümanlar aşağıdadır. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 //MainParametresi4.java - 05.04.2014 public class MainParametresi4 { public static void main(String[] dizi) // args yerine dizi adı verildi { System.out.println(dizi[0]); System.out.println(dizi[1]); System.out.println(dizi[2]); System.out.println(dizi[3]); System.out.println(dizi[4]); System.out.println(dizi[5]); System.out.println(dizi[6]); } } Ekran çıktısı: 1 Okan 2 Bilke 3 Onur 4 Bilke 5 Göksu 6 Tuna 7 Elektroarge Örnekte de gösterdiğimiz gibi boşluktan sonrasını başka bir dizi elemanına alıyor. Eğer biz bunu bir bütün olarak görsün istiyorsak, ne yapmamız gerekir? Bunun için tahmin ettiğiniz gibi elemanları tırnak içerisindeyazmamız gerekir. Hemen eklediğimiz argümanları gösterelim ve çıktımıza bakalım. Elemanları tırnak içerisinde yazdığımız zaman, bunu bir bütün String olarak algılıyor ve bunu bir argüman olarak görüyor. Çıktıda bir şeye dikkat ettiyseniz, 2014 sayısını girdik. Yani verdiğimiz argümanlar int tipinde bile olsa, onu String'e cast ederek depoluyor. Istisnalar: ! main metodu yalnızca String tipinde argüman alabilir. Bu args adındaki dizinin adının, herhangi bir şey olmasında sakınca yoktur, hata vermez. Ders 44 - Arrays Sınıfı Metodları Arrays sınıfının bazı metotlarını önceki derslerimizde anlatmıştık. Bu dersimizde Arrays sınıfımızın diğer önemli metodlarını anlatacağız. ARRAYS.ASLIST METODU İLE DİZİYİ LİSTE YAPISINA KOPYALAMA Dizimizin içeriğini Arrays sınıfının asList() metodu yardımıyla bir liste yapısına aktarabiliriz. Metodumuz parametre olarak bir dizi alır ve geriye bir liste yapısı verir. Metodumuzu daha iyi anlamak için bir örnek yapalım: 1 //ArraysOrnekleri.java - 05.04.2014 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.List; 6 7 public class ArraysOrnekleri 8 { 9 public static void main(String[] args) 10 { 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 String dizi[] = {"Edirne", "İstanbul", "Lüleburgaz", "Tekirdağ"}; Integer dizi1[] = {22, 34, 39, 59}; // dizilerimizi oluşturduk List ListeYapisi = new ArrayList(); List ListeYapisi1 = new ArrayList(); // liste yapılarımızı oluşturduk ListeYapisi = Arrays.asList(dizi); ListeYapisi1 = Arrays.asList(dizi1); // dizilerimizi asList() metodu ile liste yapısına dönüştürdük System.out.println(ListeYapisi.get(1)); System.out.println(ListeYapisi); System.out.println(ListeYapisi1.get(0)); System.out.println(ListeYapisi1); } } Ekran çıktısı: 1 İstanbul 2 [Edirne, İstanbul, Lüleburgaz, Tekirdağ] 3 22 4 [22, 34, 39, 59] Yukarıdaki örneğimizde oluşturduğumuz dizilerimizi asList() metodu yardımıyla liste yapısına kopyalamış olduk. Liste yapımızı ekrana yazdırdığımızda dizinin elemanlarının sıralı bir biçimde liste yapısına aktarılmış olduğunu gördük. ARRAYS.COPYOF METODU İLE DİZİNİN BELLİ BÖLÜMÜNÜ KOPYALAMA Dizimizi başka bir diziye kopyalayabileceğimiz bir diğer metot Arrays sınıfının copyOf() metodudur. Bu metod, özel bir dizi kopyalama metodudur. Bu metod ile dizimizin belli bir bölümünü başka bir diziye kopyalayabiliriz. Metodumuz iki parametre alır ve geriye bir dizi döndürür. Metodumuzun aldığı ilk parametrekopyalanacak dizidir, ikinci parametre ise diziden kaç eleman kopyalanacağını belirten bir integer değerdir. Metodumuzu şimdi bir örnek üzerinde deneyerek daha iyi anlamaya çalışalım: //ArraysOrnekleri2.java - 05.04.2014 1 2 import java.util.Arrays; 3 4 public class ArraysOrnekleri2 5 { 6 public static void main(String[] args) 7 { 8 char dizi[] = {'E', 'l', 'e', 'k', 't', 'r', 'o', 'a', 'r', 'g', 'e'}; 9 char yeniDizi[]; 10 11 System.out.print("Kopyalanacak dizi: "); 12 for(int j = 0 ; j < dizi.length ; j++) 13 { 14 System.out.print(dizi[j]); 15 } 16 // kaynak dizimizi ekrana yazdırdık 17 18 yeniDizi = Arrays.copyOf(dizi, 3); 19 // kaynak dizimizden belirttiğimiz kadar eleman 20 kopyaladık 21 22 System.out.print("\nOluşan yeni dizi: " ); 23 for(int k = 0 ; k < yeniDizi.length ; k++) 24 { 25 System.out.print(yeniDizi[k]); 26 } 27 } 28 } 29 30 Ekran çıktısı: 1 Kopyalanacak dizi: Elektroarge 2 Oluşan yeni dizi: Ele Yukarıdaki örneğimizde oluşturduğumuz char tipte bir dizinin copyOf() metodunu kullanarak, üç adet elemanını yeni oluşturduğumuz diziye kopyaladık. ARRAYS.COPYOFRANGE İLE İKİ İNDİS ARASINDAKİ ELEMANLARI KOPYALAMA Dizimizi başka bir diziye kopyalayabilen özelleşmiş metotlardan birisi de Arrays sınıfının copyOfRange()metodudur. Bu metodumuz, üç parametre alır. İlk parametre de kopyalanacak kaynak dizi belirtilir, ikinci parametrede dizinin hangi elemanından kopyalamaya başlanılacağını belirten bir değer belirtilir. Son parametrede ise dizinin hangi elemanına kadar kopyalamanın devam edeceğini gösteren bir değer belirtiriz. Şimdi metodumuzu örnek üzerinde deneyelim: //ArraysOrnekleri3.java - 05.04.2014 1 2 import java.util.Arrays; 3 4 public class ArraysOrnekleri3 5 { 6 public static void main(String[] args) 7 { 8 int dizi[] = {14, 53, 19, 23, 20, 12}; 9 int yeniDizi[]; 10 11 System.out.println("Kopyalanacak dizi: "); 12 for(int j = 0 ; j < dizi.length ; j++) 13 { 14 System.out.print(dizi[j]); 15 } 16 // kaynak dizimizi ekrana yazdırdık. 17 18 yeniDizi = Arrays.copyOfRange(dizi, 2, 6); 19 // kaynak diziden 2 ve 6 indis değerleri arası 20 kopyalandı. 21 22 System.out.println("\nYeni oluşan dizi: "); 23 for(int k = 0 ; k < yeniDizi.length ; k++) 24 { 25 System.out.print(yeniDizi[k]); 26 } 27 // yeni oluşan diziyi ekrana yazdırdık. 28 } 29 } 30 31 Ekran çıktısı: 1 Kopyalanacak dizi: 2 145319232012 3 Yeni oluşan dizi: 4 19232012 Örneğimizde görüldüğü gibi oluşturduğumuz dizinin elemanlarını copyOfRange() metodu ile ikinci dizimize kopyalamayı başardık. Örneğe dikkat edersek; bizim dizimizde 6 indis değerli eleman yoktur, ama dizimizi kopyalarken indis değerimize 6 değerini verdik. Burada verdiğimiz değerler eleman sırasıdır ve verdiğimiz alt sınır işleme dahil değildir. Örneğimizde alt verdiğimiz alt sınırın bir fazlasından (3. eleman) başlayarak üst sınıra kadar olan elemanları kopyaladık. ARRAYS.FILL METODU İLE DİZİYE ELEMAN ATAMAK Dizimizin belli bir bölümüne veya tamamına Arrays sınıfının fill() metodu ile değer atayabiliriz. Bu metod, kendisine verilen değeri dizinin tüm elemanlarına veya belirttiğimiz indisler arasındaki elemanlara atar. Metodumuzun genel olarak iki formu vardır. Bunlar şöyledir: 1 fill(Object array[], Object value) 2 fill(Object array[], int baslangic, int bitis, Object value) Metodumuz ilk formda tüm diziyi, parametre olarak verilen değer ile doldurur. İkinci form da ise yine parametre olarak verilen değeri, belirttiğimiz indis değerleri arasındaki bölüme yazar. Metodumuzu örnek üzerinde göstererek daha iyi anlamaya çalışalım: 1 //ArraysOrnekleri4.java - 05.04.2014 2 3 import java.util.Arrays; 4 5 public class ArraysOrnekleri4 6 { 7 public static void main(String[] args) 8 { 9 int dizi[] = {0, 0, 0, 0, 0}; 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 int dizi1[] = {1, 1, 1, 1, 1}; Arrays.fill(dizi, 1); Arrays.fill(dizi1, 2, 4, 0); // dizilerimize elemanları doldurduk System.out.println("Eleman doldurduğumuz ilk dizi: "); for(int j = 0 ; j < dizi.length ; j++) { System.out.print(dizi[j]); } // ilk dizimizi ekrana yazdırdık. System.out.println("\nEleman doldurdugumuz ikinci dizi: "); for(int k = 0 ; k < dizi1.length ; k++) { System.out.print(dizi1[k]); } // ikinci dizimizi ekrana yazdırdık } } Ekran çıktısı: 1 Eleman doldurduğumuz ilk dizi: 2 11111 3 Eleman doldurdugumuz ikinci dizi: 4 11001 Yukarıdaki örneğimizde oluşturduğumuz dizilere fill() metodu ile verdiğimiz değerleri doldurduk. İlk bölümde fill() metodumuzun birinci formunu kullanarak, bütün diziyi verdiğimiz değer ile doldurduk. İkinci bölümde ise dizinin 2 - 4 arasındaki bölümüne verdiğimiz değerleri doldurduk. Ders İçinde Yazılmış Tüm Programlar ve Kodları Ektedir: Ders 45 - Scanner Sınıfına Giriş Bir programlama dilinde, kullanıcıdan veri girişi yapmasını isteyebiliriz. Kullanıcının girdiği bu verilere göre işlem yapabilir, bunları ekrana yazdırabilir veya herhangi bir yere parametre olarak verebiliriz. Bunu Java'daScanner sınıfları ile yapıyoruz. Sınıfın ne demek olduğu konusunda Nesneye Yönelik Programlamaderslerimizde tekrar değineceğiz. Scanner sınıfı, java.util paketinde yer alır. Scanner sınıflarını kullanabilmek için java.util.Scanner sınıfını import etmemiz gereklidir. Sadece bu sınıfı değil de java.util paketindeki tüm sınıfları da import ederek,Scanner sınıfını kullanabiliriz. Bunun için de java.util.* diyerek bu paketteki sınıfları import edebiliriz. Scanner sınıfı ile klavyeden veri okumak için öncelikle bu sınıftan bir nesne oluşturmak gerekir. Scanner veriAl = new Scanner(System.in); // veriAl nesnesi 1 oluşturuldu Scanner sınıfının yapıcısına System.in InputStream kaynağı verilir(Standart Input Stream - Klavyeden Veri Girişi) Daha sonra oluşturduğumuz bu veriAl nesnesi üzerinden Scanner sınıfının metodlarına erişeceğiz. Eğer kullanıcıdan alacağımız veri int tipindeyse bunun için: 1 int sayi = veriAl.nextInt(); // int tipinde bir sayı alır Bu metod ile kullanıcıdan bir int tipinde sayı girmesi beklenecektir. Kullanıcı sayıyı girip Enter tuşuna bastığında bu değer alınıp sayi değişkenine atanacaktır. Eğer kullanıcının gireceği değer int değil de başka bir tipte olacaksa, bunun için kullanılacak olan metodlar şunlardır: nextByte(): Klavyeden byte türünde değerler okur. nextShort(): Klavyeden short türünde değerler okur. nextFloat(): Klavyeden float türünde değerler okur. nextDouble(): Klavyeden double türünde değerler okur. nextBoolean(): Klavyeden mantıksal değerler okur. nextLine(): Klavyeden String değerler okur. Eğer String içerisinde boşluk olsa bile cümlenin tamamınıokur. next(): Klavyeden String değerler okur. Eğer bu String içerisinde boşluk olursa boşluğa kadar olan kısmı alır. Boşluk yoksa tamamını bir değişkene atar. Artık, kullanıcıdan veri girişinin nasıl yapıldığını öğrendikten sonra if else, switch ve döngüleri kullanarak örnekler verebiliriz. SCANNER SINIFI İLE İLGİLİ ÖRNEKLER Scanner sınıfını kullanarak birkaç örnek verelim ve olayı daha iyi kavrayalım: //ScannerSinifi.java - 05.04.2014 1 2 import java.util.Scanner; 3 4 public class ScannerSinifi 5 { 6 public static void main(String[] args) 7 { 8 System.out.println("3 sayı girin"); 9 Scanner veriAl = new Scanner(System.in); // nesne 10 oluşturuldu 11 int veri1 = veriAl.nextInt(); // girilen veriler alınıyor 12 int veri2 = veriAl.nextInt(); 13 int veri3 = veriAl.nextInt(); 14 System.out.println("Girdiğiniz sayılar:"); 15 System.out.println(veri1); 16 System.out.println(veri2); 17 System.out.println(veri3); 18 } 19 } 20 21 Ekran çıktısı: 1 3 sayı girin 2 4 3 1 4 88 5 Girdiğiniz sayılar: 6 4 7 1 8 88 Basit bir örnek ile başladık. Kullanıcıdan sayı alıyoruz ve ekrana yazdırıyoruz. Başka bir örnek verelim: 1 //ScannerSinifi2.java - 05.04.2014 2 3 import java.util.Scanner; 4 5 public class ScannerSinifi2 6 { 7 public static void main(String[] args) 8 { 9 System.out.println("Bir cümle girin"); 10 Scanner veriAl = new Scanner(System.in); 11 for(int a = 0 ; a < 10 ; a++) 12 { 13 String veri1 = veriAl.next(); 14 System.out.println(veri1); 15 } 16 } 17 } 18 19 Ekran çıktısı: 1 Bir cümle girin 2 Elektroarge; Elektronik Araştırma Geliştirme Platformu 3 Elektroarge; 4 Elektronik 5 Araştırma 6 Geliştirme 7 Platformu Bu örnekte kullanıcının klavyeden String tipinde bir cümle girmesini istedik ve bunu next() metodu ile aldık. Bu metod, boşluğa kadar olan kısmı alıyordu. Bu metodu her çağırışımızda bize cümleyi kelimeler halinde ayırdı ve biz de bunları ekrana yazdık. Bu girilen cümlemiz 10 kelimeden fazla olmasın diyerek döngümüzü 10 kere çalıştırdık. Her seferinde boşluğa kadar olan kısmı aldı. Şimdiki örneğimizde ise kullanıcıdan farklı tipte veriler alalım: 1 //ScannerSinifi3.java - 05.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.Scanner; public class ScannerSinifi3 { public static void main(String[] args) { Scanner s1 = new Scanner(System.in); System.out.println("int tipinde bir veri girin"); int deger1 = s1.nextInt(); System.out.println("String tipinde bir veri girin"); String deger2 = s1.next(); System.out.println("Boolean tipinde veri girin"); boolean deger3 = s1.nextBoolean(); System.out.println("Girilen değerler:"); System.out.println(deger1); System.out.println(deger2); System.out.println(deger3); } } Ekran çıktısı: 1 int tipinde bir veri girin 2 2014 3 String tipinde bir veri girin 4 Okan 5 Boolean tipinde veri girin 6 false 7 Girilen değerler: 8 2014 9 Okan 10 false Bu örnekte söylememiz gereken bir şey var. Boolean tipinde değer istendiği zaman biz bundan başka bir tipte veri girersek, hata verecektir. Bir başka örnek verelim: 1 //ScannerSinifi4.java - 05.04.2014 2 3 import java.util.Scanner; 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class ScannerSinifi4 { public static void main(String[] args) { Scanner s1 = new Scanner(System.in); System.out.println("Notunuzu giriniz"); int not = s1.nextInt(); // not alındı if(not > 50) // karşılaştırmalar yapılıyor System.out.println("Geçtiniz"); else System.out.println("Kaldınız"); } } Ekran çıktısı: 1 Notunuzu giriniz 2 66 3 Geçtiniz Bu örneğimizde de girilen nota bakarak geçip geçmediğimizi ekrana yazıyoruz. Başka bir örnekte, kullanıcıdan alınan 2 değeri kullanarak işlem yapılmasını görelim: 1 //ScannerSinifi5.java - 05.04.2014 2 3 import java.util.Scanner; 4 5 public class ScannerSinifi5 6 { 7 public static void main(String[] args) 8 { 9 int toplam = 0; 10 Scanner veriAl = new Scanner(System.in); 11 System.out.println("Lütfen ilk tamsayıyı girin:"); 12 int sayi1 = veriAl.nextInt(); // başlangıç değeri alındı 13 System.out.println("Lütfen ikinci tamsayıyı girin:"); 14 int sayi2 = veriAl.nextInt(); // bitiş değeri alındı 15 for(int a = sayi1 ; a <= sayi2 ; a++) 16 { 17 toplam += a; // başlangıç ve bitiş arasındaki sayılar toplandı 18 19 20 21 22 23 } System.out.println("İki değer arasındaki sayıların toplamı: " + toplam); } } Ekran çıktısı: 1 Lütfen ilk tamsayıyı girin: 2 3 3 Lütfen ikinci tamsayıyı girin: 4 7 5 İki değer arasındaki sayıların toplamı: 25 Bu örnekte kullanıcıdan alınan 2 değer arasındaki (bu değerler de dahil) sayılar toplanarak ekrana yazdırıldı. Eğer bu alınan değerlerin dahil olmasını istemeseydik, a değerini sayi1 + 1'den başlatırdık ve bitiş değerinde ise a < sayi2 yapardık. Scanner sınıfı ile kullanıcıdan değer almaya bir örnek daha verelim. 1 //ScannerSinifi6.java - 05.04.2014 2 3 import java.util.Scanner; 4 5 public class ScannerSinifi6 6 { 7 public static void main(String[] args) 8 { 9 int toplam = 0; 10 Scanner s1 = new Scanner(System.in); 11 while(true) // sonsuz döngü 12 { 13 System.out.println("Değer Giriniz"); 14 int a = s1.nextInt(); 15 if(a > 0) 16 toplam += a; 17 else 18 break; 19 } 20 System.out.println("Sayıların toplamı: " + 21 toplam); 22 } 23 24 } Ekran çıktısı: Değer Giriniz 1 6 2 Değer Giriniz 3 9 4 Değer Giriniz 5 2 6 Değer Giriniz 7 -1 8 Sayıların toplamı: 9 17 Bu örnekte while(true) ile sonsuz döngüye girdik. Her seferinde kullanıcıdan bir sayı istedik. Eğer bu sayı 0'dan büyükse, girilen her değeri toplayacak. Eğer 0 ve negatif ise döngüden çıkacak ve girilmiş olan tüm sayıların toplamını ekrana yazacak. Bir de diziler ile ilgili örnek yapalım: 1 //ScannerSinifi7.java - 05.04.2014 2 3 import java.util.Scanner; 4 5 public class ScannerSinifi7 6 { 7 public static void main(String[] args) 8 { 9 Scanner s = new Scanner(System.in); 10 int dizi[][] = new int[2][2]; 11 System.out.println("Dizinin 1. satır 1. sütununu 12 girin:"); 13 dizi[0][0] = s.nextInt(); 14 System.out.println("Dizinin 1. satır 2. sütununu 15 girin:"); 16 dizi[0][1] = s.nextInt(); 17 System.out.println("Dizinin 2. satır 1. sütununu 18 girin:"); 19 dizi[1][0] = s.nextInt(); 20 System.out.println("Dizinin 2. satır 2. sütununu 21 girin:"); 22 23 24 25 26 27 28 29 30 dizi[1][1] = s.nextInt(); for(int j = 0 ; j < 2 ; j++) { for(int k = 0 ; k < 2 ; k++) // diziyi ekrana yazdırdık { System.out.print(dizi[j][k] + "\t"); } System.out.println(""); } } } Ekran çıktısı: Dizinin 1. satır 1. sütununu girin: 1 6 2 Dizinin 1. satır 2. sütununu 3 girin: 4 1 5 Dizinin 2. satır 1. sütununu 6 girin: 7 88 8 Dizinin 2. satır 2. sütununu 9 girin: 10 -5 6 1 88 -5 Bu örnekte ise 2 boyutlu bir dizi oluşturduk. Kullanıcıdan aldığımız int tipindeki verileri bu diziye atadık ve daha sonra da bu elemanları matris şeklinde ekrana yazdırdık. Bir de sayı tahmin oyunu yapalım: 1 //ScannerSinifi9.java - 05.04.2014 2 3 import java.util.*; // Scanner ve Random sınıflarını 4 import ettik 5 6 public class ScannerSinifi8 7 { 8 public static void main(String[] args) 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 { int deger = 1; Random r = new Random(); int sayi = r.nextInt(10); // rasgele sayı ürettik Scanner s = new Scanner(System.in); while(true) { System.out.println("Tahmin Girin (0-10):"); int tahmin = s.nextInt(); // tahmin alınıyor if (tahmin == sayi) // tahmin sayıya eşit mi? { System.out.println(deger + ". tahminde bildiniz"); break; } else deger += 1; // her tahminde bunu artırdık } } } Ekran çıktısı: 1 Tahmin Girin (0-10): 2 3 3 Tahmin Girin (0-10): 4 5 5 Tahmin Girin (0-10): 6 7 7 Tahmin Girin (0-10): 8 8 9 Tahmin Girin (0-10): 10 4 11 5. tahminde bildiniz Yine bu örnekte sonsuz döngüye girdik ve tahmini bulduğumuz anda döngüden çıktık. Her tahminde detahmin sayısını 1 artırdık ve sonunda kaçıncı tahminde sayının bulunduğunu yazdık. Random sınıfını kullanarak programın başında bir rastgele değer üretmiştik bu değeri bulmaya çalıştık. Ders 46 - JOptionPane Kullanımı JOptionPane, Java'ya yeni başlayanların adını ilk defa duydukları bir kavram olabilir. JOptionPane, kullanıcı ile iletişimi sağlar. Yani kullanıcıdan veri alır veya kullanıcıya bir mesaj gösterir. Bu veri alıp gösterme işlemini, bir pencere yardımıyla yapar. Konsol uygulamalarının yerine form uygulaması özelliği getirmiştir. Bunu kullanabilmek için ilk olarak javax.swing.JOptionPane sınıfını import etmemiz gerekir. Şimdi ilk olarak kullanıcıdan veri almayı görelim. KULLANICIDAN VERİ ALMA JOptionPane ile kullanıcıdan bir pencere yardımıyla veri almak için kullanacağımız metod: 1 JOptionPane.showInputDialog(Buraya mesaj yazılacak); Şimdi basit bir örnek ile başlayalım: //JOptionPaneKullanimi.java - 05.04.2014 1 2 import javax.swing.JOptionPane; // import ettik 3 4 public class JOptionPaneKullanimi 5 { 6 public static void main(String[] args) 7 { 8 String sayi = JOptionPane.showInputDialog("Bir sayı 9 girin"); 10 } 11 } 12 13 Ekran çıktısı: Şekilde görüldüğü gibi bir pencere açılıyor ve kullanıcıdan veri girişi yapılması isteniyor. Hemen burada bir not düşelim. Istisnalar: ! JOptionPane ile kullanıcıdan veri istendiğinde, girilen değer String tipindedir. Notumuzda anlattığımız gibi örnek üzerinde de doğrudan String tipindeki bir değişkene attık. Peki, bu girilen sayı üzerinde matematiksel işlem yapmak istiyorsak ne yapacağız? Bunu önceki konulardan biliyoruz artık. Değişken üzerinde casting işlemi yapacağız. Hemen buna da bir basit örnek verelim: //JOptionPaneKullanimi2.java - 05.04.2014 1 2 import javax.swing.JOptionPane; 3 4 public class JOptionPaneKullanimi2 5 { 6 public static void main(String[] args) 7 { 8 String sayi = JOptionPane.showInputDialog("Bir sayı 9 girin"); 10 int yeniSayi = Integer.parseInt(sayi); // cast işlemi 11 } 12 } 13 14 Bu şekilde yaparak alınan bir sayıyı int'e cast edebiliriz. Artık yeniSayi değişkenimizi matematiksel işlemlerde kullanabiliriz. BİLGİ MESAJI GÖSTERME Bir pencere yardımıyla kullanıcıya mesaj göstermek isteyebiliriz. Bu mesaj, doğrudan bir String ya da buString verinin yanında değişkenlerin de yazılmış bir şekli olabilir. İlk olarak mesaj göstermek için kullanacağımız metodu verelim. 1 JOptionPane.showMessageDialog(null, mesajımız); Yukarıdaki metodu kullanarak kullanıcıya bilgilendirme mesajı yazabiliriz. Bu metodun ilk parametresinull'dur. Diğer parametresi ise, vermek istediğimiz mesajdır. Şimdi basit bir örnekle başlayalım: //JOptionPaneKullanimi3.java - 05.04.2014 1 2 import javax.swing.JOptionPane; 3 4 public class JOptionPaneKullanimi3 5 { 6 public static void main(String[] args) 7 { 8 JOptionPane.showMessageDialog(null, "Bilgilendirme 9 Mesajı"); 10 } 11 } 12 13 Ekran çıktısı: Bu metodumuz 2 parametrenin yanında 4 parametre de alabilir. Parametrelerden birisi, çıkan pencereninbaşlığıdır. Diğer parametre ise pencerede ise pencerede çıkan bilgilendirme resmidir. Şimdi bu parametreleri kullanarak başka bir örnek yapalım: //JOptionPaneKullanimi4.java - 05.04.2014 1 2 import javax.swing.JOptionPane; 3 4 public class JOptionPaneKullanimi4 5 { 6 public static void main(String[] args) 7 { 8 JOptionPane.showMessageDialog(null, "Bilgilendirme Mesajı", 9 "Sonuç", JOptionPane.OK_OPTION); 10 } 11 } 12 13 Ekran çıktısı: Burada Sonuç adındaki parametremiz, penceremizin başlığını oluşturur. Son parametre ise, sol tarafta bulunan ikondur. Bu resmi değiştirebiliriz. En sonda bulunan parametreyi değiştirdiğimizde ikon da değişir. Bu parametrelerin sırası değiştirilemez. Şimdi soldaki ikonu değiştirdiğimiz farklı bir örnek verelim: 1 //JOptionPaneKullanimi5.java - 05.04.2014 2 3 import javax.swing.JOptionPane; 4 5 public class JOptionPaneKullanimi5 6 { 7 public static void main(String[] args) 8 { 9 int a = 5; 10 11 12 13 14 JOptionPane.showMessageDialog(null, a, "Sonuç", JOptionPane.WARNING_MESSAGE); } } Ekran çıktısı: Bu örnekte de 2. parametremiz mesajımız olduğu için biz mesajımızı int tipindeki bir değişken olarak verdik. Herhangi bir String olarak da verebilirdik. 3. parametre yine pencere adı oldu. Son parametre ise, bu sefer başka bir mesaj ikonu olarak belirlendi. Duruma göre bunu değiştirebiliriz. Aşağıdaki listeye baktığımızda kullanabileceğimiz mesaj resimlerini görebiliriz. Yukarıdaki gibi klavyede . (nokta) tuşuna bastığımızda, kullanabileceğimiz şekillerin adları çıkmaktadır. JOPTIONPANE İLE İLGİLİ ÖRNEKLER Şimdi anlattığımız bu 2 özellik(veri alma ve gösterme) ile ilgili örnekler verelim: //JOptionPaneKullanimi6.java - 05.04.2014 1 2 import javax.swing.JOptionPane; 3 import java.util.Random; 4 5 public class JOptionPaneKullanimi6 6 { 7 public static void main(String[] args) 8 { 9 int i = 1; 10 Random r = new Random(); 11 int sayi = r.nextInt(10); // bilinecek olan sayı belirlendi 12 while(true) // sonsuz döngü kuruldu 13 { 14 String tahmin = JOptionPane.showInputDialog("Tahmin 15 Gir:"); 16 int t = Integer.parseInt(tahmin); 17 if(t == sayi) // tahmin ile sayı tutuyorsa 18 { 19 String mesaj = "Tahmin doğru! - " + i + ". tahminde 20 bildiniz"; 21 JOptionPane.showMessageDialog(null, mesaj); 22 break; 23 } 24 else 25 i++; // tutmuyorsa sayacı artır, başa dön 26 } 27 } 28 } 29 Ekran çıktısı: Örneğimizde ilk olarak Random sınıfı ile 0 - 10 arasında rastgele bir sayı belirledik. Daha sonra tahminler ile bunu bulmaya çalıştık. Bulduğumuz zaman kaçıncı tahminde bulduğumuzu gösteren bir kontrol koyduk. Eğer tahmin yanlış ise, sadece sayacı artırdık. Doğru bildiğimizde break; ile sonsuz döngüyü sonlandırarak çıktık. Başka bir örnek yapalım: 1 //JOptionPaneKullanimi7.java - 05.04.2014 2 3 import javax.swing.JOptionPane; 4 5 public class JOptionPaneKullanimi7 6 { 7 public static void main(String[] args) 8 { 9 String sayi1 = JOptionPane.showInputDialog("İlk sayıyı girin"); 10 int a = Integer.parseInt(sayi1); 11 String sayi2 = JOptionPane.showInputDialog("İkinci sayıyı girin"); 12 int b = Integer.parseInt(sayi2); 13 int sonuc = hesapla(a, b); 14 JOptionPane.showMessageDialog(null, sonuc, "Toplam", 15 JOptionPane.PLAIN_MESSAGE); 16 } 17 18 19 20 21 22 23 24 25 26 27 28 static int hesapla(int a, int b) { int toplam = 0; for(int i = a ; i <= b ; i++) { toplam += i; } return toplam; } } Ekran çıktısı: Bu örnekte kullanıcıdan aldığımız 2 sayı ile işlem yapılmaktadır. Alınan 2 sayı arasındaki değerleri toplar ve ekranda bilgi mesajı olarak verir. Alınan değerleri hesapla() adlı metoda gönderiyor ve sonucu, pencereye bir parametre olarak veriyor. Şimdi de son olarak klasik bir örnek olan vize ve final notu alıp ortalama bulan bir program yapalım ve sonuçlarına bakalım: 1 //JOptionPaneKullanimi8.java - 05.04.2014 2 3 import javax.swing.JOptionPane; 4 5 public class JOptionPaneKullanimi8 6 { 7 public static void main(String[] args) 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 { String vize = JOptionPane.showInputDialog("Vize notunu giriniz"); int v1 = Integer.parseInt(vize); while(v1 < 0 || v1 > 100) { vize = JOptionPane.showInputDialog("Vize notunu tekrar giriniz"); v1 = Integer.parseInt(vize); } String finalNotu = JOptionPane.showInputDialog("Final notunu giriniz"); int f1 = Integer.parseInt(finalNotu); while(f1 < 0 || f1 > 100) { finalNotu = JOptionPane.showInputDialog("Final notunu tekrar giriniz"); f1 = Integer.parseInt(finalNotu); } int not = (int)(v1 * 0.3 + f1 * 0.7); String sonuc = "Notunuz: " + not; JOptionPane.showMessageDialog(null, sonuc, "Not Açıklama", JOptionPane.INFORMATION_MESSAGE); } } Ekran çıktısı: Bu örnekte, girilen vize notu 0'dan küçük veya 100'den büyükse, tekrar vize notunu istiyor. Bu işlem, 0 - 100 arasında değer girilene kadar devam ediyor. Aynı şekilde final notu için de bu şekilde yapılıyor. Finalnotunu değişkene atarken final yazdığımızda hata verir çünkü bu Java'nın kendisine ait anahtar kelimelerinden birisidir. Biz de bunu finalNotu olarak değiştirdik. Bu tür anahtar kelimelerin değişken ismi olarak kullanılmadığını görmüştük diğer anahtar kelimelere [url=Ders 16 - Java'da Kullanılan Anahtar Kelimeler]http://www.elektroarge.com/java/ders-16-java-da-kullanilan-anahtarkelimeler-t704.html[/url] dersinden ulaşabilirsiniz. Biz de bunu finalNotu olarak değiştirdik. Bu tür anahtar kelimelerin değişken ismi olarak kullanılamadığını hatırlayalım. Daha sonra notların ortalamasını alıyor ve pencerede gösteriyor. Girilen notları, üzerinde işlem yapabilmek için int tipindeki değişkene cast ettik. Son olarak sonuc değişkenine, String ve int tipindeki değişkeni birleştirerek atama yapıyoruz. Bunu, pencere notumuzu gösterdiğimizde daha açıklayıcı olması için yaptık. Ders 47 - Nesneye Yönelik Programlamaya Giriş Nesneye yönelik programlama, yazılım karmaşıklığını ortadan kaldırmak amacıyla 1960'lı yılların sonunda ortaya çıkan bir yaklaşımdır. Yazılımdaki karmaşıklıktan kastımız şudur. Nesneye yönelik programlama sayesinde, yazdığımız programların daha rahat kontrol edilmesi sağlandı. Oluşan herhangi bir hata, program parçalara bölündüğü için daha rahat bulunur hale geldi. Bölünen bu parçaların organize bir şekilde çalışması sağlanarak, daha gelişmiş programlar yazılabilir hale geldi ve bunun yanında performans artışı sağlandı. Nesneye yönelik programlamanın sağladığı avantajlar, onu günümüzde geniş çaplı projeler için vazgeçilmez yapmıştır. Yazılımdaki karışıklığa çözüm için kullanılan prensipler vardır. Bunlar; kalıtım (inheritance), çok biçimlilik(polymorphism), soyutlama (abstraction), sarmalama (encapsulatio n) gibi kavramlardır. Bunları ileriki derslerimizde göreceğiz. Aslında nesneye yönelik programlamanın temelinde hiyerarşi yatar. Bu hiyerarşiyi de sınıflar venesneler oluşturur. Mesela; bir işyeri düşünelim. Bu nesneye yönelik programlama mantığında sınıfa karşılık gelir. Bu iş yerindeki her bir çalışan ise nesneye karşılık gelir. İşyerindeki her bir çalışanın, yani nesnenin diğer nesneler ile etkileşmesi ve organize çalışması sonucunda nesneye yönelik programlama kavramı ortaya çıkmıştır. Sınıf ve nesne kavramlarını daha yakından ve detaylı inceleyelim. Ders 48 - Sınıf ve Nesne Kavramları Nesne kavramının en kısa açıklaması şudur. Doğada herşey bir nesnedir. Uçan kuş, evimizdeki kapı, pencere, dışarıdaki arabalar vx. Bu nesnelerin iki özelliği vardır. Bu nesnelerin iki özelliği vardır. Durum vedavranış. Peki, bununla ne demek istiyoruz? Örnek olarak bir arabayı düşünelim. Bu arabanın rengi, fiyatı, markası, modeli gibi özellikleri onundurumunu belirtir. Buna attribute (özellik) de denir. Bu arabanın hızlanması, yavaşlaması, kaza yapması, vites değiştirmesi gibi özellikleri ise onun davranışını belirtir. Dolayısıyla durumu ve davranışı olan herşey birnesnedir. Doğadaki bu araba örneğinin bilgisayar yazılımlarındaki karşılığı nesnedir. Arabamızın durumundabelirtilen özellikler, nesneye yönelik programlamada değişkenler üzerinde saklanır. Davranışların nesneye yönelik programlama karşılığı ise metodlardır. Metodlar, bir çeşit nesne fonksiyonudur. Nesne kavramını artık biliyoruz. Şimdi ise sınıfların ne demek olduğunu anlatalım. Sınıflar, tahmin ettiğiniz üzere, nesnelerden oluşur. Nesnelerin durum ve davranışlarını tutar. Örnek olarak bir insan nesnesi düşünelim. İnsan nesnesinin durumu olan boy, kilo ve davranışı olan nefes alıp verme gibi özellikleri ile beraber tutulduğu yer sınıftır. Bu insan nesnesinin sınıfına canlı sınıfı diyebiliriz. Daha sonra bu canlı sınıfından istediğimiz kadar insan nesnesi oluşturabiliriz. Bu yeni oluşturulan nesnelere instance(örnek) denir. Bu oluşturduğumuz yeni insanın da nefes alma, cinsiyet, boy, kilo gibi özellikleri vardır. Bunu, savaş oyunlarındaki askerlere benzetebiliriz. Her asker bir instance'dir ve her askerin belirli özellikleri vardır. Dolayısıyla her nesnenin bir sınıfı vardır diyebiliriz. Bu anlattıklarımızdan yola çıkarak birer taslak, nesnelerin ise bu taslaktan üretilen birer varlık olduğunu düşünebiliriz. Bu taslakta, nesnelerde olması gereken özellikler bulundurulur. Bu özellikler hayata geçirilerek bir örnek oluşturulduğunda ise buna nesne denir. Dolayısıyla bu taslaktan istediğimiz kadar nesneoluşturabiliriz. Sadece aynı sınıftan türetilen nesnelerin tipi aynıdır. Yani bir araba sınıfıyla, insan sınıfından türetilen nesnelerin özellikleri farklıdır. Şimdi bir insan sınıfı düşünelim. Bu insan sınıfından türetilen nesnelerde boy, kilo, yaş gibi özellikler mutlaka olacaktır. Bu nesneye yönelik programlamanın kuralıdır. Fakat burada türetilen her nesnemizde ortak olarak bulunması gereken özelliklerin değeri farklıdır. Bazı insanlar zayıf, bazı insanlar şişman olabilir. Nesneye yönelik programlamanın temeli, işte buradan başlamaktadır. Buraya kadar anlattığımız durum ve davranışlara, nesneye yönelik programlamada field (alan) denilmektedir. SINIF OLUŞTURMA Nesne - sınıf ilişkisini ve bunlara bağlı olarak ortaya çıkan kavramları gördükten sonra sınıfların ve nesnelerin Java'da nasıl oluşturulduklarına bakalım. Java'da sınıf oluşturmak için kullanılan genel format şu şekildedir; erisim_belirleyici class 1 sinif_ismi 2 { 3 // özellikler 4 // metodlar 5 // yapıcılar 6 } Burada class sözcüğünün başına erişim belirleyicilerden birisi getirilir. Bu zorunlu değildir. Erişim belirleyicileri ileriki derslermizde detaylı olarak göreceğiz. Class sözcüğünden sonra da sınıfımızın ismi yazılır. Daha sonra açılan süslü parantezler içerisine de durum ve davranışları belirten alanlar yazılır. Yapıcılar konusunu da ilerleyen sayfalarda anlatacağız. Basit olarak bir sınıf oluşturma aşağıdaki gibi yapılır. //Insan.java - 05.04.2014 1 2 public class Insan // Insan adında sınıf 3 oluşturuldu 4 { 5 double boy; // Özellikler tanımlandı (3 6 Özellik) 7 String cinsiyet; 8 int yas; 9 } 10 Yukarıda Insan adında bir class (sınıf) oluşturduk. Sınıfımızın içerisine boy, yaş, cinsiyet gibi değişkenler koyduk. Görüldüğü gibi bu değişkenleri şimdilik durum (özellik) olarak belirledik. Bunlar sadece değişkengörevindedirler. Daha sonra bu sınıfımıza davranış belirten metodlar da ekleyeceğiz. Davranış derken meselanefesAl, yuru, kos gibi metodlardan bahsediyoruz. NEW ANAHTAR KELİMESİ İLE NESNE OLUŞTURMA Yukarıdaki sınıfımızdan oluşturduğumuz her örneğe nesne denir. Sınıfımızdaki tüm alanlara, nesnemiz de sahip olur. Diyelim ki bu sınıftan 10 adet insan oluşturduk. Oluşturduğumuz her insan nesnemizin de boyu, yaşı farklı olabilir. Java'da bir sınıftan nesne oluşturmak için new anahtar kelimesi kullanılır. 1 Insan okan = new Insan(); Burada insan sınıfından okan adında bir nesne türettik. Bunu new anahtar sözcüğü ile yapıyoruz. Oluşturduğumuz okan nesnesi, boy, cinsiyet, yas alanlarına sahip olacaktır. Bir de onur adında bir nesne oluştursaydık, bu nesnemiz de aynı alanlara sahip olacaktı. Şimdi ise bu sınıfımızdan bir nesne oluşturalım ve bu nesnelere değer atayalım. //Insan.java - 05.04.2014 1 2 public class Insan // Insan adında sınıf oluşturuldu 3 { 4 double boy; // Özellikler tanımlandı (3 Özellik) 5 String cinsiyet; 6 int yas; 7 8 public static void main(String[] args) 9 { 10 Insan kisi = new Insan(); // Insan sınıfından kisi adında bir nesne 11 oluşturuldu 12 kisi.boy = 1.78; // nesnenin boy değişkenine değer atandı 13 System.out.println(kisi.boy); // nesnemizin boy değeri ekrana yazdırıldı 14 } 15 } 16 17 Ekran çıktısı: 1 1.78 Burada ilk olarak Insan adında bir sınıf oluşturduk ve bu sınıfın alanlarını belirledik. Bunlar boy, cinsiyetve yas olsun. Daha sonra programımızın başladığı main metodunu yazdık. Bu metod içerisinde ilk olarak sınıfımızdan bir nesne oluşturduk. Bunu new anahtar sözcüğü ile yaptık. Oluşturduğumuz nesnenin adı kisiolsun. Bu nesne, oluşturulduğu sınıftaki tüm özelliklere sahip olur. Bu kisi nesnesinin boy özelliğine bir değer atadık ve ekrana yazdırdık. Insan sınıfımızdan oluşturduğumuz bir nesne, o sınıftaki alanlara sahiptir demiştik. Oluşturulan bu nesnenin özelliklerine nokta (.) ile erişiyoruz. Yani kisi.boy, kisi.yas diyerek, o kişinin özelliğine değer atayıp ekrana yazdırabiliriz. Nokta (.) operatöründen biraz bahsedelim. Bu operatör ile bir sınıfın altında bulunan metodlara ve değişkenlere erişebiliriz. Yalnızca sınıflarda değil, paket adlarında da kullanılır. Bu operatör, aslında bir nevihiyerarşi sağlar. Şimdi ise nesnenin durum özelliğinin yanında davranış özelliğine de bir örnek verelim. Davranıştan kastımız metodlardır. 1 //Araba.java - 05.04.2014 2 3 public class Araba 4 { 5 String marka, renk; // durum 6 7 void gaza_bas() // davranış 8 { 9 System.out.println("Araba hızlanıyor"); 10 } 11 12 void frene_bas() // davranış 13 { 14 System.out.println("Araba yavaşlıyor"); 15 } 16 17 public static void main(String[] args) 18 { 19 Araba a1 = new Araba(); // Araba sınıfından a1 adında nesne oluşturuldu a1.marka = "xxx"; // nesnenin markası belirlendi a1.renk = "siyah"; // nesnenin rengi belirlendi a1.gaza_bas(); // a1 nesnesinin gazaBas adlı metodu çalıştırıldı a1.frene_bas(); // a1 nesnesinin freneBas adlı metodu çalıştırıldı } } 20 21 22 23 24 25 26 27 Ekran çıktısı: 1 Araba hızlanıyor 2 Araba yavaşlıyor Bu örneğimizde, Araba sınıfından bir nesne oluşturduk ve bu nesne ile gazaBas ve freneBas metodlarını çağırdık. Bu metodlar, durum değil davranış özelliği gösterirler. Diğer, marka ve renk field'ları, durumniteliğindedirler. Türetilen bu nesneye önce mark ve renk değerleri atanıyor. Daha sonra gazaBas vefreneBas metodları çağırılıyor. Istisnalar: ! Oluşturulan her nesne, bellekte farklı bir alanda tutulur. Nesnelerin bellekte tutulduğu bölge heap alanıdır. Bu nesnelere, o nesnenin referansı ile erişebiliriz. Bir nesnenin birden fazla referansı olabilir. Bir sınıf içerisinde değişkenlerin, metodların, yapıcıların tanımlanabileceğini söylemiştik. Değişkenlerin tanımlamasını ve kullanılmasını önceki örneklerde anlattık. Şimdi daha detaylı bir örnek üzerinde inceleyelim. 1 //Metodlar.java - 05.04.2014 2 3 public class Metodlar // Insan adında sınıf oluşturuldu 4 { 5 int carp(int sayi1, int sayi2) 6 { 7 return sayi1 * sayi2; 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 } int topla(int sayi1, int sayi2) { return sayi1 + sayi2; } public static void main(String[] args) { Metodlar islem1 = new Metodlar(); // islem1 nesnesi Metodlar islem2 = new Metodlar(); // islem2 nesnesi int sonuc = islem1.carp(5,4); int sonuc2 = islem2.topla(7, 1); System.out.println("Çarpma sonucu: " + sonuc); System.out.println("Toplama sonucu: " + sonuc2); } } Ekran çıktısı: 1 Çarpma sonucu: 20 2 Toplama sonucu: 8 1. Bu örneğimizde iki tane metod oluşturduk. Birisi aldığı iki sayıyı çarpıyor, diğeri ise iki sayıyı topluyor. Metodlara nasıl parametre aktarıldığını Ders 31 - Parametreli Metodlar dersimizde anlatmıştık. 2. main metodunun içerisinde Metodlar sınıfından 2 adet nesne tanımlıyoruz. Dolayısıyla bu nesneler, sınıfın sahip olduğu metodlara sahip oluyor. 3. İlk oluşturduğumuz nesnenin carp metodunu çalıştırıyoruz ve değer olarak 5 ve 4 sayılarını gönderiyoruz. Buradan dönen değeri sonuc değişkenine atıyoruz. 4. Daha sonra ikinci nesnemiz üzerinden de topla metodunu çağırıyoruz ve parametre olarak 7 ve 1 sayılarını gönderiyoruz. Buradan dönen değeri de sonuc2 değişkenine atıyoruz ve sonuçları ekrana yazdırıyoruz. Istisnalar: ! Bir sınıf içerisinde istediğimiz kadar metod tanımlayabiliriz ve bunlara istediğimiz kadar parametre gönderebiliriz. Bu dersteki metodlar kavramında sıkıntı yaşıyorsanız, Metodlar konulu derslerimize tekrar göz atmanızı öneririz. Ders 49 - Sınıf ve Nesne Değişkenleri Java'da nesneye programlama kullandığımız için değişkenler, kullanıldığı yere göre farklı şekilde adlandırılırlar ve farklı şekilde adlandırılır ve farklı davranış sergilerler. Nesneye yönelik programlamada ihtiyaca göre nesne oluştururuz ve her nesnenin kendine has özellikleri olur. Bu şekilde her nesnenin kendine ait olan değişkenlerine nesne değişkenleri denir. Bir de her nesne için ortak olarak kullanılan değişkenler vardır. Bunlar nesneden nesneye farklılık göstermezler. Bunlara da sınıf değişkenleri denir. Şimdi örnek üzerinde sınıf değişkenlerini anlatalım. 1 //Degiskenler.java - 05.04.2014 2 3 public class Degiskenler 4 { 5 static int deger = 5; // sınıf 6 değişkeni 7 8 public static void main(String[] 9 args) 10 { 11 Degiskenler d1 = new 12 Degiskenler(); 13 14 15 16 Degiskenler d2 = new Degiskenler(); System.out.println(d1.deger); System.out.println(d2.deger); } } Ekran çıktısı: 1 5 2 5 Bu örnekte bir tane deger adında sınıf değişkeni tanımladık. Dediğimiz gibi sınıf değişkenleri, her nesne için ortak kullanılır ve her nesne için aynıdır. main metodu içerisinde iki tane nesne oluşturduk. Programımız ilk olarak main çalışmaya başladığı için buradaki nesnelerimizin işlemleri yapılacaktır. Daha sonra bu iki nesne için de deger değişkenin değeri yazdırıldı. Bu iki nesne için de bu değişkenin değerinin değerinin 5 olduğu görüldü. Örnekte de gördüğümüz üzere sınıf değişkenlerini static anahtar kelimesi ile tanımlıyoruz. static anahtar kelimesini önceki derslerimizde anlatmıştık. Ders 35 - Static Metodlar Ders 16 - Java'da Kullanılan Anahtar Kelimeler Şimdi ise nesne değişkenlerine örnek verelim ve farkı anlayalım. 1 //Degiskenler2.java - 05.04.2014 2 3 public class Degiskenler2 4 { 5 int deger; // nesne değişkeni 6 7 public static void main(String[] args) 8 { 9 Degiskenler2 d1 = new 10 Degiskenler2(); 11 Degiskenler2 d2 = new 12 Degiskenler2(); 13 d1.deger = 7; 14 d2.deger = 9; 15 16 17 18 System.out.println(d1.deger); System.out.println(d2.deger); } } Ekran çıktısı: 1 7 2 9 Bu örnekte de iki tane nesne oluşturduk. Bu nesneler Degiskenler2 sınıfına ait. Daha sonra nesnelerindeger adlı değişkenlerine ayrı ayrı 7 ve 9 değerlerini atadık. Son olarak da bunları ekrana yazdırdık ve gördük ki her nesne için bu değişken farklı değerler aldı. Nesne değişkenlerini normal olarak tanımlıyoruz. Başına erişim belirleyici getirmezsek, bu public olarak derleyici tarafından belirleniyor. Peki, bu nesne değişkenini static olarak tanımlasaydık, yani sınıf değişkeniyapsaydık ne olacaktı? Şimdi ise bunu gösterelim. //Degiskenler3.java - 05.04.2014 1 2 public class Degiskenler3 3 { 4 static int deger; // sınıf değişkeni 5 6 public static void main(String[] args) 7 { 8 Degiskenler3 d1 = new 9 Degiskenler3(); 10 Degiskenler3 d2 = new 11 Degiskenler3(); 12 d1.deger = 7; 13 d2.deger = 9; 14 System.out.println(d1.deger); 15 System.out.println(d2.deger); 16 } 17 } 18 Ekran çıktısı: 1 9 2 9 Burada main metodumuzda d1 nesnesi için deger değişkenine 7 değerini atadık. Değişkenimiz 7 oldu. Şimdi ise d2 nesnesi için de bir değer belirledik. Normalde her iki nesne için de bu değer farklı olmalı. Fakat değişkenimiz sınıf değişkeni olduğu için d2 nesnesi için de 9 atadıktan sonra, deger değişkenimiz artık 9 oldu. Yani bu her nesne için artık 9 değerini alacak. Dolayısıyla bu değişkenleri ekrana yazdırdığımızda, son atadığımız değer olan 9 değerini, her iki nesne için de aynı olarak yazdıracak. Istisnalar: ! Nesne değişkenleri dinamik değişkenler, yani instance variable olarak da adlandırılırlar. Sınıf değişkenleri ise static değişkenler olarak adlandırılırlar. Istisnalar: ! Eğer nesne değişkeni tanımladıysak oluşturulan her nesne için bellekte bir yer ayrılır. Bu nesne değişkenlerinin değeri, programın herhangi bir yerinde değiştirilebilir. Sınıf değişkenleri için bellekte sadece biryer ayrılır. Istisnalar: ! Sınıf değişkenleri static olarak tanımlandığı için bu değişkenlere nesne oluşturmadan da sadece sınıf adını kullanarak erişebiliriz. Yani bunlar nesneden bağımsızdırlar. Sınıf değişkenleri aynı zamanda static değişkenler olarak adlandırılırlar. Dediğimiz gibi bu değişkenleresınıf adı ile de erişebiliriz, çünkü nesneden bağımsızdırlar. Bunun sebebi ise; her nesne için aynı olmasıdır. Sınıf değişkenleri, diğer bazı dillerdeki global değişken kavramına benzer. Şimdi ise static, yani sınıf değişkenlerine, sınıf adı ile erişmeye bir örnek verelim. //Degiskenler4.java - 05.04.2014 1 2 public class Degiskenler4 3 { 4 static String yazi = "Okan Bilke"; 5 6 public static void main(String[] args) 7 { 8 System.out.println(Degiskenler4.yazi); // sınıf adı ile 9 erişildi 10 } 11 } 12 13 Ekran çıktısı: 1 Okan Bilke Gördüğümüz gibi static olan değişkenlere sadece sınıf adı ile erişebiliyoruz. Aynı şekilde sınıf adını kullanarak değer de atayabiliriz. Eğer değişkenimiz static olmasaydı, yani nesne değişkeni olsaydı bu şekilde erişemeyecektik. Erişmek için bir nesne oluşturmamız gerekecekti. Örneğimizde bir nesne oluşturmadık. Bu değişkenler için söyleceğimiz son özellik ise şudur: Sınıf değişkenleri program bittiğinde bellektensilinirler ve her program için yalnızca bir defa oluşturulurlar. Nesne değişkenleri ise, nesne yok olduğundabellekten silinirler. Ders 50 - Pass By Value - Pass By Reference PASS BY VALUE - PASS BY REFERENCE (DEĞER VE REFERANS TİPLER) Değişkenler konusunu anlatırken Primitive ve Referans tiplere değinmiştik. Ders 10 - Primitif Tipler Ders 11 - Referans Tipler Bu tiplerde bilmemiz gereken bir nokta var. Bir metoda parametre gönderdiğimizi varsayalım. Metod, bu parametreyi 10 ile çarpıyor ve ekrana bir şeyler yazıyor. Peki, metoddan çıktığımızda sizce asıl değişkenimizin değeri de değişiyor mu? Primitive ve Referans tipler için cevap farklıdır. Primitive (int, double, byte...) tiplerde, o değeri metoda parametre olarak gönderdiğimizde, değerin kopyası gönderilir ve orjinal değeri bozulmaz. Referans tiplerde ise metoda değerin kendisi gönderilir. Metodda olan değişiklikler, değişkenimize de yansır. Bu konu Değer veReferans tipler olarak bilinir. Referans tipler ile işlem yaparken nesne ve nesne değişkenlerini kullandığımız için, bu konuyu Metodlardersinde değil de burada incelemeyi uygun gördük. Fakat genel olarak bu konu, Metodlar konusunda geçer. Primitif tiplere bir örnek verelim ve değişkenin orjinal değerinin değişmediğini görelim. //Tipler.java - 05.04.2014 1 2 public class Tipler 3 { 4 public static void main(String[] args) 5 { 6 int a = 5; 7 System.out.println("Eski değer: " + 8 a); 9 degistir(a); 10 System.out.println("Yeni değer: " 11 + a); 12 } 13 static void degistir(int a) 14 { 15 a = a + 10; 16 } 17 } 18 Ekran çıktısı: 1 2 Eski değer: 5 Yeni değer: 5 Bu ilk örneğimizde a değişkenimizi ilk olarak ekrana yazdırdık. Daha sonra metoda parametre olarak gönderdik. Metodda bu değeri 10 ile topladık. Metoddan çıktığımızda yeni a değerini ekrana yazdırdık ve gördük ki asıl değerimizde bir değişiklik olmamış. Çünkü metoda parametre olarak gönderilen değer, değişkenimizin bir kopyasıdır. Primitive tiplerde nu böyledir. Bir metoda, değişkenin değerinin kopyaları gönderilir. Şimdi de referans tiplere örnek verelim. Referans tipler, new anahtar sözcüğü ile oluşturuluyorlardı. Metodlara, parametre olarak nesnenin adresi gönderilir. Bellekte aynı yeri işaret ettikleri için orjinal değeri değişir. Ayrıca istisna olarak diziler de referans tiplerden sayılırlar. //Tipler2.java - 05.04.2014 1 2 public class Tipler2 3 { 4 int x; 5 public static void main(String[] args) 6 { 7 Tipler2 t1 = new Tipler2(); 8 t1.x = 5; 9 System.out.println("Eski değer: " + 10 t1.x); 11 t1.degistir(t1); 12 System.out.println("Yeni değer: " + 13 t1.x); 14 } 15 void degistir(Tipler2 t1) 16 { 17 t1.x = t1.x + 10; 18 } 19 } 20 Ekran çıktısı: 1 Eski değer: 5 2 Yeni değer: 15 Burada da t1 nesnemizin x değişkenine 5 değerini atadık ve ekrana yazdırdık. Daha sonra t1 nesnesini,degistir() metoduna gönderdik. Bu metodda, t1 nesnesinin x değerini 10 artırdık. Metoddan çıkıp yeni değerimizi yazdırdığımızda ise 15 olduğunu gördük. Çünkü metoda gönderdiğimiz parametre, değişkenimizinorjinal değeri oluyor. Metoddaki değerin değiştirilmesi, orjinal değerin de değişmesi demek oluyor. Diziler de bir referans tiptir. Onu da örnek üzerinde gösterelim. //Tipler3.java - 05.04.2014 1 2 public class Tipler3 3 { 4 public static void main(String[] args) 5 { 6 int dizi[] = {1, 6, 9}; 7 System.out.println("Eski değer: " + 8 dizi[0]); 9 degistir(dizi); 10 System.out.println("Yeni değer: " + 11 dizi[0]); 12 } 13 14 static void degistir(int dizi[]) 15 { 16 dizi[0] = dizi[0] + 5; 17 } 18 } 19 Ekran çıktısı: 1 Eski değer: 1 2 Yeni değer: 6 Bu örnekte de 3 elemanlı dizi tanımladık ve ilk elemanını ekrana yazdırdık. Daha sonra bu ilk elemanı metoda gönderdik. Metod içerisinde bu dizi elemanının değerini 5 artırdık. Metoddan çıktığımızda yeni değeri ekrana yazdırdık ve orjinal değerin değiştiğini gördük. Çünkü diziler de bir referans tiptir. Şimdi de her iki yöntemi beraber kullanalım. //Tipler4.java - 05.04.2014 1 2 public class Tipler4 3 { 4 int b; 5 public static void main(String[] 6 args) 7 { 8 int a = 4; 9 degistir1(a); 10 System.out.println(a); 11 12 Tipler4 d1 = new Tipler4(); 13 d1.b = 10; 14 d1.degistir(d1); 15 System.out.println(d1.b); 16 } 17 18 void degistir(Tipler4 d1) 19 { 20 d1.b = d1.b + 25; 21 } 22 23 static void degistir1(int deger) 24 { 25 deger = deger + 5; 26 } 27 } 28 29 Ekran çıktısı: 1 4 2 35 Bu son örneğimizde, a değişkenimizin değerinin değişmediğini, b değişkeninin ise asıl değerinindeğiştiğini gözlemledik. Ders 51 - Yapıcılar (Constructor) Önceki derslerimizde nesneler oluşturmayı ve o nesneler üzerinden, bulunduğu sınıfın değişkenlerine veya metodlarına erişmeyi anlattık. Bir nesne üzerinden bir metod çağırdığımızda, metodun alacağı parametreleri gönderiyorduk. Sınıftan bir nesne oluşturulduğunda, derleyici otomatik olarak bir constructor (yapıcı) metod çağırır. Bu metod, oluşturulan her nesne için çağrılır. Yapıcılar, nesnenin ilk oluşturulduğunda alması gereken değerleri, kullanacağı metodları belirler. Yapıcıların adı, sınıf adı ile aynı olmak zorundadır. Yapıcı metodlar, geriye herhangi bir değer döndüremezler. Yapıcı metodlar, aşırı yükelenebilir. Aşırı yükleme (overloading) kavramını Metodlar derslerinde görmüştük. Her sınıf için bir default constuctor vardır. Bu default constructor'lar, herhangi bir parametre almazlar. Eğer biz bunu kullanmak istemiyorsak, parametre alan bir yapıcı kullanmak istiyorsak, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 kendimiz bir yapıcı metod yazmamız gerekir. Buna bir örnek verelim. //Yapicilar.java - 05.04.2014 public class Yapicilar { int deger1, deger2; // nesne değişkenleri public Yapicilar() // varsayılan yapıcı. Sınıf adı ile aynıdır. Parametre almaz. { deger1 = 5; } public Yapicilar(int sayi) // parametre alan yapıcı, sınıf adı ile aynıdır. { deger2 = sayi; } public static void main(String[] args) { Yapicilar nesne1 = new Yapicilar(); Yapicilar nesne2 = new Yapicilar(10); // yapıcıya parametre gönderildi System.out.println("İlk nesnenin değeri : " + nesne1.deger1); System.out.println("İkinci nesnenin değeri: " + nesne2.deger2); 24 25 26 27 28 } } Ekran çıktısı: 1 İlk nesnenin değeri : 5 2 İkinci nesnenin değeri: 10 Örneğimiz üzerinden yapıcıları inceleyelim. 1. Burada Yapicilar adında bir sınıfımız var. Bu sınıf içerisinde ise Yapicilar adında iki tane yapıcı metodumuz var. Yapıcı metodlar, sınıf adı ile aynı olmak zorundadır. 2. İlk metod parametre almıyor yani default constructordur. Bu metod deger1 adlı değişkene 5 değerini atıyor. 3. Diğer yapıcımız ise parametre alan bir yapıcıdır. Bu metod ise aldığı parametreyi deger2 adlı değişkene atar. 4. Daha sonra main metodumuz içerisinde iki adet nesne oluşturduk. İlk nesnemiz oluşturulduğundavarsayılan yapıcı çağrılacaktır. Eğer bir nesne oluşturursak, hemen bir varsayılan yapıcı çağırılır. Biz burada varsayılan yapıcımızı kendimiz yazdık. Yazmasaydık derleyici otomatik olarak oluşturacaktı. Varsayılan yapıcılar, nesne oluşturduğumuzda parametre göndermezsek çalışır. İlk nesnemiz için bir parametre göndermediğimizden dolayı varsayılan, yani parametre almayan yapıcı metod çağırıldı. 5. Diğer nesnemiz oluşturulduğunda ise 10 değerini gönderdik. Dolayısıyla, nesne oluşturuldu ilk andaparametre alan yapıcı metod çalıştırılır. Bu nesne için de gönderilen 10 değeri, deger2 değişkenine atandı. 6. Son satırlarda da bu nesneler için deger1 ve deger2 değişkenlerini ekrana yazdırdık. Yapıcı metodların overloading yapılabileceğini söylemiştik. Bu örnekte de görüldüğü gibi aynı isimli iki yapıcı metod yazdık ve bunlar mecburen farklı parametreli veya parametre sıraları farklı olan metodlar olmak zorundadır. Yapıcılar konusunda bir örnek daha verelim. //YapicilarOverloading.java - 05.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class YapicilarOverloading { void metod1() // ilk metod { System.out.println("Parametre almayan metod çağırıldı"); } void metod2(int sayi1) // ikinci metod { System.out.println("Parametre alan metod çağırıldı"); // alınan parametreyi kullanmadık } public YapicilarOverloading() // ilk yapıcı { metod1(); } public YapicilarOverloading(int sayi1) // ikinci yapici { metod2(sayi1); } public static void main(String[] args) { YapicilarOverloading nesne1 = new YapicilarOverloading(); YapicilarOverloading nesne2 = new YapicilarOverloading(10); } } Ekran çıktısı: 1 Parametre almayan metod çağırıldı 2 Parametre alan metod çağırıldı Şimdi örneğimizi açıklayalım. 1. Bu örnekte metod1 ve metod2 adında iki adet metod oluşturduk. Bu metodlar parametre alıp almadığına göre ekrana bilgilendirme mesajı yazıyor. 2. Daha sonra iki tane yapıcı metod yazdık. Bunlardan ilki default yapıcı, diğeri ise parametre alan yapıcımetoddur. 3. Parametre almayan yapıcı metod, metod1'i çağırıyor. Parametre alan metod ise metod2'yi çağırıyor. 4. Main metodumuzda ise nesne1 ve nesne2 adında nesneler oluşturduk. Bunlardan nesne1oluşturulduğunda, parametre almadığı için default constructor (varsayılan yapıcı metod) çağırılır. Bu constructor ise, metod1'i çağırıyor. 5. Daha sonra bu metod ekrana, "Parametre almayan metod çağırıldı" çıktısını yazıyor. 6. Main metodunda oluşturduğumuz ikinci nesne ise parametre alıyor. Dolayısıyla bu nesne oluşturulduğu anda onun yapıcısı çağırılıyor. Parametre alan yapıcı, yani ikinci yapıcı metod çağırılıyor. 7. Bu yapıcı da metod2'yi çağırıyor ve ekrana "Parametre alan metod çağırıldı" yazıyor. Yapıcılar konusunu daha iyi anlamak için son bir örnek verelim. Bu örneğimizde bir nesne dizisi oluşturalım. Örneğimizi verirken nesne dizileri nasıl oluşturulur onu da anlatmış olalım. 1 //Yapicilar2.java - 05.04.2014 2 3 public class Yapicilar2 4 { 5 static int sayi = 0; 6 public Yapicilar2() // varsayılan yapıcı. Sınıf adı ile aynıdır. Parametre 7 almaz. 8 { 9 sayi++; 10 } 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public static void dongu(Yapicilar2 nesne[]) { for(int a = 0 ; a < 4 ; a++) { nesne[a] = new Yapicilar2(); } } public static void main(String[] args) { Yapicilar2 nesne[] = new Yapicilar2[4]; // nesne dizisi oluşturuldu Yapicilar2.dongu(nesne); System.out.println(sayi + " adet nesne oluşturuldu"); } } Ekran çıktısı: 1 4 adet nesne oluşturuldu main metodumuz içerisinde 4 elemanlık bir nesne dizisi oluşturuldu. Daha sonra bu dizi dongu adındaki bir metoda parametre olarak gönderildi. Bu metodda da nesnemizin tüm elemanları oluşturuldu. Metodun içerisinde oluşan her bir nesne için yapıcımız çalıştı ve sayımızı 1 artırdı. Yani amacımız, kaç nesne oluşturulduğunu yapıcılar ile bulmak. Çünkü nesne oluşturulduğunda ilk olarak yapıcı çağırılır ve yapıcıiçerisinde ne varsa o işlenir. Bu dersten özet olarak çıkarmamız gereken düşünce şudur: Nesne oluşturulduğunda ilk olarak ona ait bir yapıcı çağırılır. Eğer parametre gönderilmemişse default constructor, gönderildiyse, ona ait olan parametreli constructor çağırılır. 2 parametre aldıysa, 2 parametreli yapıcı çağırılır. Tek parametre aldıysa, tek parametreli yapıcı çağırılır. Yani kendine özel hazırlanmış yapıcı. Bu yapıcılar içerisinde herhangi bir metod çağırılabilir veya bir değişkene atama yapılabilir veya ekrana bir şeyler yazılabilir. Bunun gibi birçok işlem yapılabilir. Örneğin; bir yapıcının içerisine "Şuan bir nesne oluşturuldu" gibi birçok işlem yapılabilir. Örneğin; bir yapıcının içerisine "Şuan bir nesne oluşturuldu" gibi bir çıktı da yazdırabilirdik. Çünkü yapıcılar, nesne oluşturulduğu ilk anda çalışır. Özet olarak yapıcılar, nesne oluşturulduğu ilk anda yapmamızı istediğimiz şeyleri yapan bir metoddur. Ders 52 - Kapsülleme (Encapsulation) Kapsülleme; kısaca bir sınıfın, içerisindeki metod ve değişkenleri korumasıdır. Bünyesindeki metod vedeğişkenlere dışarıdan erişmenin sakıncalı olduğu durumlarda kapsülleme mekanizması kullanılır. Kapsülleme sayesinde sınıf üyeleri, dış dünyadan gizlenir. Tabi bu gizliliğin dereceleri vardır. Bu dereceler, erişimbelirleyiciler sayesinde olur. Kapsülleme klasik verilen bir örnek vardır. Biz de ona benzer bir örnek verelim. Biz bilgisayarı açma tuşuna basarız ve bilgisayar açılır ya da şöför kontağı çevirir ve araba çalışır. Fakat kullanıcı arkaplanda ne olduğunu bilmez. Sadece o işin nasıl yapılacağını bilir. Kapsülleme bu işi yapar. Nesneye yönelik programlamanın temellerinden biri de kapsüllemedir. Çünkü sınıftaki bilgilerin dışarıya kapalı olması gerekir. Şimdi bunu sağlayan erişim belirleyicileri görelim. Bu erişim belirleyicileri, bütünlük olması açısından kapsülleme dersinde inceleyeceğiz. ERİŞİM BELİRLEYİCİLER (ACCESS MODIFIERS) Daha önceki konularda karşılaştığımız ve ileride anlatacağımızı söylediğimiz bu konu, nesneye yönelik programlamanın da bir parçasıdır. Erişim belirleyiciler, adından da anlaşıldığı üzere sınıf elemanına erişimi sınırlandıran anahtar kelimelerin genel adıdır. Bu anahtar kelimeler public, private, protected'dir. Bu anahtar kelimeleri kullanmazsak default anahtar kelimeyi kullanır. Kapsülleme'nin temelini bu erişim belirleyicileroluşturur. Erişim belirleyiciler konusuna somut bir örnek verelim. Ev adında bir sınıfımız olsun. Bu ev sınıfındaki kasaadlı metod gizli olarak tanımlanmalıdır. Yani bu kasa metoduna veya değişkenine sadece ev halkı erişebilsin. Evde önem arz etmeyen herhangi bir şeye ise akrabalar ve komşular erişebilsin. Evde önem arz etmeyen herhangi bir şeye ise akrabalar ve komşular erişebilsin. Yabancı kişiler ise evdeki hiçbir şeye erişemesin. Bu tip örnekleri çoğaltabiliriz. Bu eşyaları, önem derecesine göre başına erişim belirleyici anahtar kelimelerden birini getirerek bunları gizleyebiliriz. Şimdi bu anahtar kelimelerin ne anlama geldiğini söyleyelim. public: Bir elemanı public olarak tanımlarsak, bu elemana herkes ulaşabilir. protected: Bir sınıfın protected olarak tanımlanmış elemanına o sınıftan, o sınıftan türetilmiş sınıflardan ve o sınıf ile aynı pakette bulunan sınıflar erişebilir. private: private olarak tanımlanmış sınıf elemanlarına, yalnızca o sınıftan erişilebilir. O sınıftan türetilensınıflardan veya aynı pakette bulunan sınıflardan erişilemez. default: Herhangi bir erişim belirleyici tanımlanmamışsa, default olarak kabul edilir. Default tanımlanmış sınıf elemanlarına, o sınıftan ve aynı paketteki sınıftan erişilebilir. Bu anahtar kelimelerin kullanımına örnek verelim. PRIVATE ANAHTAR KELİMESİ İlk olarak private anahtar kelimesini gösterelim. Yukarıda tanımını yapmıştık. Örnek üzerinde de gösterelim. 1 //Ev.java - 05.04.2014 2 3 package Private_Aynı_Sınıf; 4 5 public class Ev 6 { 7 private void kasa() // private metod tanımlama 8 { 9 System.out.println("Gizli kasa"); 10 } 11 12 13 14 15 16 17 18 19 20 private String belge = "Gizli Belge"; // private değişken tanımlama public static void main(String[] args) { Ev anne = new Ev(); // Ev sınıfından nesne oluşturuldu anne.kasa(); // anne nesnesi, kasaya ulaşmaya çalışıyor System.out.println(anne.belge); } } Ekran çıktısı: 1 Gizli kasa 2 Gizli Belge Bu örnekte private konusuna bir örnek verdik. Burada sınıf tanımlamasının hemen altında bir metod vedeğişken tanımladık ve bunları private olarak belirledik. Daha sonra aynı sınıf içerisinde main metodunda birnesne oluşturarak bu elemanlara erişmeye çalıştık. Aynı sınıftan eriştiğimiz için hata vermedi ve privateelemanlara erişebildik. Programımızın başladığı main metodu, o sınıfın içindedir. Başka bir sınıfta main metodu tanımlayıp ve nesneyi orada türetip, oradan erişmeye çalışsaydık erişemeyecektik. Şimdi ise aynı sınıftan değil de başka bir sınıftan erişmeye çalışalım. Bunun için Kisiler adında bir sınıf daha oluşturuyoruz. (Aynı paket içerisinde) Ev Sınıfı: 1 //Ev.java - 05.04.2014 2 3 package Private_Farklı_Sınıf; // paketler aynı 4 5 public class Ev // ev sınıfı 6 { 7 private void kasa() // private metod 8 { 9 System.out.println("Gizli kasa"); 10 } 11 12 13 14 private String belge = "Gizli Belge"; // private değişken } Kisiler Sınıfı: //Kisiler.java - 06.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package Private_Farklı_Sınıf; aynı // paketler public class Kisiler // Kisiler sınıfı { public static void main(String[] args) { Ev anne = new Ev(); // nesne oluşturuldu anne.kasa(); // erişilemez System.out.println(anne.belge); // erişilemez } } Başka bir sınıf olan Kisiler adlı sınıftan nesne türetip Ev sınıfının private elemanlarına erişmeye çalıştığımızda, yukarıdaki gibi altını çiziyor ve erişemeyeceğimizi söylüyor. Görüldüğü gibi private elemanlara,sadece tanımlandığı sınıf içerisinden erişilebilir. Ne başka bir sınıftan türetilen nesne ile ne herhangi bir sınıftan ne de aynı pakette olan sınıf içerisinden erişilemez. PROTECTED ANAHTAR KELİMESİ Şimdi protected anahtar kelimesinin kullanımını görelim ve örnekler üzerinde anlatalım. Tanımını dersimizin başında yapmıştık. Yukarıda yaptığımız örneği bir de protected için yapalım. Ev Sınıfı: //Ev.java - 06.04.2014 1 2 package Protected_Farklı_Sınıf; 3 4 public class Ev 5 { 6 protected void bilgisayar() // protected metod tanımlandı 7 { 8 System.out.println("Bilgisayar metodu"); 9 } 10 protected String fatura = "Faturalar"; // protected değişken 11 tanımlandı 12 } 13 14 Kisiler Sınıfı: //Kisiler.java - 06.04.2014 1 2 package Protected_Farklı_Sınıf; // paketler aynı 3 4 public class Kisiler // Kisiler sınıfı 5 { 6 public static void main(String[] args) 7 { 8 Ev akraba = new Ev(); // akraba nesnesi 9 akraba.bilgisayar(); // akraba nesnesi, metoda erişmeye 10 çalışıyor 11 System.out.println(akraba.fatura); 12 } 13 } 14 15 Ekran çıktısı: 1 Bilgisayar metodu 2 Faturalar Bu örnekte Ev sınıfının elemanlarını protected olarak ayarladık. Yani dedik ki; bu elemanlara sadece evsınıfından olanlar, bu sınıftan türetilmiş sınıflar ve bu Ev sınıfı ile aynı paketten olan sınıflar erişebilsin. Biz de bu Ev sınıfı ile aynı paketten olan sınıflar erişebilsin. Biz de bu Ev sınıfı ile aynı paketten olan Kisiler adlı sınıfı oluşturduk. Bu sınıftan akraba adında bir nesne oluşturduk ve görüldüğü gibi bu nesne ile Ev sınıfınınprotected elemanlarına erişebildik. Sınıf Türetme (Kalıtım) konusunu anlatmadığımız için buna değinmeyeceğiz. Fakat protected elemanlara, türetilmiş sınıflardan da erişilebilir. Eğer Kisiler sınıfının en üstünde bulunan paket tanımlamasında package Protected_Farklı_Sınıf;tanımlamasını package Protected_Farklı_Sınıf2; yapsaydık, bu protected elemanlara erişemeyecektik. Çünkü aynı paketten olmayacaklardı. protected elemanlara aynı pakatten erişilebildiğini gördük. Aynı paketten erişilebiliyorsa aynı sınıftan da erişilebilir. Bunu da gösterelim. Sadece Ev sınıfı üzerinden anlatalım. Ev Sınıfı: 1 //Ev.java - 05.04.2014 2 3 package Protected_Aynı_Sınıf; 4 5 public class Ev 6 { 7 private void bilgisayar() // protected tanımlanmış metod 8 { 9 System.out.println("Bilgisayar metodu"); 10 } 11 protected String fatura = "Faturalar"; // protected tanımlanmış 12 değişken 13 public static void main(String[] args) 14 { 15 Ev akraba = new Ev(); 16 akraba.bilgisayar(); // aynı sınıftan protected elemanlara 17 erişilebilir 18 19 20 21 System.out.println(akraba.fatura); // aynı sınıftan her zaman erişilebilir. } } Bu örnekte de aynı sınıftan protected elemanlara erişmeyi gördük. Aynı sınıftan erişmek için anahtar kelimenin önemi yoktur. Kalıtım konusunda alt sınıf kavramını göreceğiz ve alt sınıflardan da üst sınıfın protected elemanlarına erişilebilir. Kısacası protected elemanlara o sınıftan, türetilen sınıftan, aynı pakette olan başka bir sınıftan erişilebilir. PUBLIC ANAHTAR KELİMESİ Şimdi de public anahtar kelimesine örnek verelim. İlk olarak bildiğimiz gibi aynı sınıftan erişmeyi görelim. Bunda herhangi bir sıkıntı yok. Çünkü bunu her şekilde yapabiliyoruz. //Ev.java - 06.04.2014 1 2 package public_aynı_sınıf; 3 4 public class Ev 5 { 6 private void adres() // public metod tanımlandı 7 { 8 System.out.println("Ev adresi"); 9 } 10 public int KatSayisi = 3; // public değişken 11 tanımlandı 12 13 public static void main(String[] args) 14 { 15 Ev halk = new Ev(); 16 halk.adres(); // herkes erişebilir 17 System.out.println(halk.KatSayisi); 18 } 19 } 20 21 Ekran çıktısı: 1 Ev adresi 2 3 Burada public olarak evin adresini ve kat sayısını verdik. Yani bu elemanlara herkes erişebilir. Bu örnekte aynı sınıftan public elemanlara erişmeyi gördük. Şimdi ise başka sınıftan ve başka pakettenerişmeyi görelim. Ev Sınıfı: //Ev.java - 06.04.2014 1 2 package Public_Farklı_Sınıf; 3 4 public class Ev 5 { 6 protected void adres() 7 { 8 System.out.println("Ev 9 adresi"); 10 } 11 public int katSayisi = 3; 12 } 13 14 Kisiler Sınıfı: 1 //Kisiler.java - 06.04.2014 2 3 package Public_Farklı_Sınıf; 4 5 public class Kisiler 6 { 7 public static void main(String[] args) 8 { 9 Ev halk = new Ev(); 10 halk.adres(); 11 System.out.println(halk.katSayisi); 12 } 13 } 14 15 Bu örnekte ekran çıktımız yine aynı olacaktır. Yani halk nesnesi,Ev sınıfındaki public elemanlara erişebilecektir ve ekrana değerlerini yazacaktır. Eğer Kisiler sınıfındaki paket tanımlamasında paket1 adlı paketi paket2 yaparsak, farklı paketlerde olduğu için Ev sınıfının elemanlarına erişebilecek miyiz, onu görelim. Ev sınıfımız aynı kalsın ve biz Kisiler sınıfının yeni halini şu şekilde yapalım. Kisiler Sınıfı: 1 //Kisiler.java - 06.04.2014 2 3 package Public_Farklı_Sınıf2; 4 import Public_Farklı_Sınıf.Ev; 5 6 public class Kisiler 7 { 8 public static void main(String[] args) 9 { 10 Ev halk = new Ev(); 11 halk.adres(); 12 System.out.println(halk.katSayisi); 13 } 14 } 15 16 Ekran çıktısı: 1 Ev adresi 2 3 Örneğimizde görüldüğü gibi farklı paketlerde olsak bile, public elemanlara erişebiliriz. Biz burada halkadında bir nesne oluşturduk yani bir ev ile ilgili public bilgilere, tüm halkın ulaşabildiğini göstermek için bu şekilde adlandırdık. Ayrıca Ev sınıfı kullanabilmek için import ettik. Farklı paketler de olsa, o paketi sınıfa dahil ederek public elemanlara erişebiliriz. Yine aynı şekilde türetilmiş sınıflardan da erişilebilir. ! Istisnalar: Eğer alanımızın başına bir erişim belirleyici yazmazsak default olarak algılanır. default olan alanlara da yalnızca o sınıftan ve aynı paketten erişilebilir. Istisnalar: ! Java'da .java uzantılı dosya içerisinde birden fazla sınıf kullanacaksak, yalnızca bir tanesi public olarak tanımlanabilir. Aynı yerde iki veya ikiden fazla sınıf public olamaz. Nottaki özelliğe bir örnek verelim: //Ev.java - 06.04.2014 1 2 public class Ev 3 { 4 public static void main(String[] 5 args) 6 { 7 } 8 class Kisiler // bu sınıf public 9 olamaz 10 { 11 } 12 } 13 Burada Ev sınıfını public olarak tanımladığımız için aynı yerde, public olan başka bir sınıf tanımlayamadık. Dolayısıyla Kisiler sınıfını default olarak tanımlamak zorunda kaldık. Istisnalar: ! Erişim belirleyicileri doğru kullanmak, proje açısından önemlidir. Eğer yanlış bir kullanımında bulunursak izin verilmeyen kişiler, bazı erişilmemesi istenen bilgileri okuyabilir. Şimdi de kapsüllemede önemli bir yeri olan Getter ve Setter metodları görelim. Ön bilgi verecek olursak bu metodlar, private elemanlara, başka sınıflardan kontrollü bir şekilde erişmeyi sağlar. GETTER VE SETTER METODLARI Kapsülleme ile iç içe olan bir konuda getter ve setter metodları konusudur. Kapsülleme'de bu metodların da görevi vardır. Erişim belirleyicileri anlattığımızda private elemanlara, başka bir sınıftan erişemeyeceğimizi söylemiştik. Java'da ve diğer dillerde, bu private elemanlara erişmenin bir yolu vardır. C# dilinde bunlara get - setmetodları denir. Java'da ise bunlar getter - setter metodlar olarak adlandırılır. Bu metodlar sayesinde private olan üyeler okunabilir veya değerleri değiştirilebilir. Okuyabilmek içingetter, yazabilmek içinse setter metodlar kullanılır. Getter metodlar, okuma yaptığı için parametre almazlar. Setter metodlar ise private üyelere değer atadığı için parametre alırlar. GETTER VE SETTER METODLARINI TANIMLAMA Ön bilgi verdikten sonra şimdi bir örnek getter ve setter metodları oluşturalım ve örnek üzerinde inceleyelim. 1 //GetterSetter.java - 05.04.2014 2 3 package Getter_ve_Setter_Metodları; 4 5 public class GetterSetter 6 { 7 private int deger; // private değişkenler 8 tanımlandı 9 private String ad; 10 public int getDeger() // getter metod 11 { 12 return deger; 13 } 14 public void setDeger(int deger) // setter 15 metod 16 { 17 this.deger = deger; 18 } 19 public String getAd() // getter metod 20 { 21 return ad; 22 } 23 public void setAd(String ad) // setter metod 24 25 26 27 28 29 30 31 32 33 34 35 { this.ad = ad; } public static void main(String[] args) { GetterSetter n1 = new GetterSetter(); n1.setAd("Okan"); System.out.println(n1.getAd()); n1.setDeger(5); System.out.println(n1.getDeger()); } } Ekran çıktısı: 1 Okan 2 5 Örneğimizi açıklayalım: 1. main metodunda bir nesne oluşturuyoruz. 2. Bu nesne üzerinden setAd() metodunu çağırıyoruz ve parametre olarak Okan veriyoruz. Bunun ileprivate değişken olan ad değişkenine, Okan parametresini atıyoruz. 3. n1.getAd() ile atadığımız bu değişkeni ekrana yazdırıyoruz. Bu metod return ad; satırına sahip olduğu için bize ad değişkenini döndürüyor. 4. Daha sonra bu nesne üzerinden setDeger() metodunu çağırıyoruz ve parametre olarak 5 değerini gönderiyoruz. Bunun ile private değişken olan deger değişkenine, 5 parametresini atıyoruz. 5. Son olarak n1.getDeger() metodunu çağırıyoruz. Bu metod, return deger; satırına sahip olduğu için bize deger değişkenini döndürüyor. Istisnalar: ! Getter metodlara istediğimiz adı verebiliriz. Fakat get kelimesi ile başlatmak, kodun okunabilirliğini artıracaktır. Bu şekilde görüldüğü gibi private elemanların değerlerini okuyabildik ve üzerinde değer yazabildik. private elemanlara erişmeyi yalnızca getter ve setter metodlar ile yapmayız. Bir sınıfın yapıcısında daprivate elemanlara değer atayabiliriz. Fakat değer okuyamayız. Çünkü yapıcılar geriye değer döndürmezler. Ayrıca yapıcılar içerisinde başka bir metod da çağırılabilir. Şimdi aynı örneği bir de yapıcılar ile yapalım. 1 //GetterSetter2.java - 05.04.2014 2 3 package Getter_ve_Setter_Metodları; 4 5 public class GetterSetter2 6 { 7 private int deger; // private alanlar 8 private String ad; 9 10 public int getDeger() 11 { 12 return deger; 13 } 14 15 public void setDeger(int deger) 16 { 17 this.deger = deger; 18 } 19 20 public String getAd() 21 { 22 return ad; 23 } 24 public void setAd(String adi) 25 { 26 this.ad = adi; 27 } 28 public GetterSetter2(String adi, int sayi) // 29 yapıcı 30 { 31 setAd(adi); // setter metod çağırıldı 32 setDeger(sayi); // setter metod çağırıldı 33 } 34 public static void main(String[] args) 35 { 36 37 38 39 40 41 GetterSetter2 n1 = new GetterSetter2("Sezer", 10); System.out.println(n1.getAd()); System.out.println(n1.getDeger()); } } main metodundaki ilk satırda nesne oluştururken, yapıcımıza Sezer ve 10 değerlerini gönderdik. Yapıca ise, bu alınan değerler, setter metodlara gönderiliyor. O yüzden artık main içerisinde setter metodları kullanarak değer atamaya gerek kalmadı. Ayrıca yapıcımız içinde setter metodlarını çağırmak yerine alınan değerleri doğrudan private değişkenlere atayabilirdik. Bunun için yapıcımızda kullanacağımız satır aşağıdadır. 1 ad = adi; 2 deger = sayi; ... şeklinde olurdu. ECLIPSE ÜZERİNDE KISAYOLDAN GETTER VE SETTER OLUŞTURMA Derslerimizde Eclipse IDE üzerinde anlattığımız için Eclipse üzerinde kısayoldan getter ve settermetodları nasıl ekleyebileceğimizi görelim. 1. Sol taraftaki Project Explorer üzerinde, çalıştığımız projenin src klasörünü açalım. 2. src klasörünün altında eğer paketimiz varsa paketimizi seçelim. 3. Daha sonra hangi sınıf içerisinde getter ve setter metodlarını oluşturmak istiyorsak, o sınıf üzerine sağ tıklayalım ve aşağıda bulunan şekildeki adımları takip edelim. Source kısmında istediğimiz metodları ekleyebiliriz. Ders 53 - This Anahtar Kelimesi Java'da this anahtar kelimesinin kullanılma amacını şöyle açıklayabiliriz. Önceki derslerimizdeki örneklerde bir metoda parametre gönderiyorduk ve bazı metodlarda bu alınan parametreyi bir nesne değişkenine atıyorduk. Bir örnek üzerinde gösterelim: //ThisAnahtarKelimesi.java - 05.04.2014 1 2 public class ThisAnahtarKelimesi 3 { 4 String ad; 5 6 public void degistir(String ad) 7 { 8 this.ad = ad; 9 } 10 11 public static void main(String[] args) 12 { 13 ThisAnahtarKelimesi t = new 14 ThisAnahtarKelimesi(); 15 t.degistir("Okan"); 16 System.out.println(t.ad); 17 } 18 } 19 20 Ekran çıktısı: 1 Okan Böyle bir sınıfımız olduğunu düşünelim. String tipinde bir ad değişkeni tanımladık. Bu bir nesne değişkenidir. Daha sonra degistir adında bir metod oluşturduk. Bu metod, aldığı String tipindeki adparametresini, nesne değişkeni olan ad değişkenine atıyor. Burada alınan parametre değişkeninin adı ile atadığımız nesne değişkeninin adı aynı olduğu için this anahtar kelimesini kullanmamız gerekiyor. Eğer bunlar farklı olsaydı, this anahtar kelimesini kullanmamız gerekmeyecekti. Eğer bu örnekte this anahtar kelimesini yazmasaydık, null çıktısı verecektir. Eğer gönderdiğimiz parametrenin adı, atadığımız değişkenin adı ile aynı olmasaydı, this anahtar kelimesini yazmaya gerek kalmayacaktı. Yukarıdaki örneği bir de farklı parametre adı ile yapalım. //ThisAnahtarKelimesi2.java - 05.04.2014 1 2 public class ThisAnahtarKelimesi2 3 { 4 String ad; 5 6 public void degistir(String adi) 7 { 8 ad = adi; // this kullanılmadı çünkü isimler farklı 9 } 10 11 public static void main(String[] args) 12 { 13 ThisAnahtarKelimesi2 t = new 14 ThisAnahtarKelimesi2(); 15 t.degistir("Okan"); 16 System.out.println(t.ad); 17 } 18 } 19 20 Bu kod da "Okan" çıktısı verecektir. Gönderdiğimiz parametre adı ile nesne değişkenimizin adı farklı olduğu için this anahtar kelimesini kullanmaya gerek kalmadı. Başka bir tanımla anlatmak gerekirse, this anahtar kelimesi o anda işlem yapan nesnenin referansınıdöndürür. Bu referans ile biz nesne değişkenlerine erişiriz. Bir metod çağırıldığında, o metodun hangi nesne tarafından çağırıldığı bilinebilir. Sonuç olarak, this anahtar kelimesi, bu gibi isim çakışmalarında karışıklığı önlemek amacıyla kullanılır. this anahtar kelimesi kullanılarak, nesne değişkeninin kullanılacağı belirtilir. Istisnalar: ! this anahtar kelimesi, yalnızca yapıcı metodlarda değil tüm metodlarda kullanılabilir. this anahtar kelimesinin bir başka kullanım amacı da, aynı sınıf içerisindeki başka bir yapıcıyı çağırmaktır. Diyelim ki biri 1 parametre, diğeri de 2 parametre alan 2 yapıcımız olsun. 1 parametre alan yapıcıdaki parametreye 1 parametre daha ekleyerek 2 parametre alan yapıcı metodu çağırabiliriz. Bunu bir örnek üzerinde inceleyelim ve konuyu daha iyi anlayalım. //ThisAnahtarKelimesi3.java - 05.04.2014 1 2 public class ThisAnahtarKelimesi3 3 { 4 String ad; 5 String soyad; 6 7 public ThisAnahtarKelimesi3(String ad) // tek parametre alan yapıcı 8 { 9 this(ad, "Bilke"); // this ile 2 parametreli yapıcı çağrıldı 10 } 11 12 public ThisAnahtarKelimesi3(String ad, String soyad) // iki 13 parametreli yapıcı 14 { 15 System.out.println(ad + " " + soyad); 16 } 17 18 public static void main(String[] args) 19 { 20 ThisAnahtarKelimesi3 nesne = new 21 ThisAnahtarKelimesi3("Okan"); 22 } 23 } 24 Ekran çıktısı: 1 Okan Bilke Bu örnekte ad ve soyad olarak iki nesne değişkeni tanımladık. Bunun yanında 1 ve 2 parametre alan iki yapıcı tanımladık. main metodu içerisinde nesne oluşturduğumuzda tek bir String parametresi gönderdik ve dolayısıyla tek parametre alan yapıcı çalıştı. Bu yapıcıda ise this ile diğer yapıcıyı çağırdık. Çağırırken de yanına 2 parametreli olması için bir String parametresi daha ekledik. Böylece 2 parametremiz oldu ve iki parametre alan yapıcıyı çağırarak çalıştırdık. this anahtar kelimesinde bahsedeceğimiz son nokta ise, this anahtar kelimesinin bir metoddan geriye değer olarak döndürebilmesidir. Herhangi bir metod içerisinde return this; dediğimizde o metoddan geriye, o an çalışan nesnenin referansı döner. Bunu, o anki çalışan metodun hangi nesne üzerinden çağırıldığını öğrenmek için kullanabiliriz. Ders 54 - Static Anahtar Kelimesi static anahtar kelimesi, kısaca sınıftaki alanlara nesne oluşturmadan erişmeyi sağlar. Şimdi bunu daha ayrıntılı bir şekilde anlatalım. Bir sınıf düşünelim. İçerisinde kişi bilgilerinin tutulduğu ad, soyad, cinsiyet gibi alanlar olsun. Daha sonra bu sınıftan nesneler oluşturduğumuzda her kişi için ad, soyad, cinsiyet gibi bilgiler tutulacaktır. Görüldüğü gibi her kişi için bu alanlar vardır ve farklıdır. Bunlara nesne değişkenleri denir. Her oluşturulan kişi nesnesi için bellekte ad, soyad, cinsiyet alanları tutulur. Buradaki her ad, soyad ve cinsiyet değişkeninin ait olduğu birnesne vardır. Java'da her nesne için ayrı tutulan alanlar değil de bir sınıf için ortak tutulan alanlar oluşturmak istersek, bunun için yapmamız gereken static anahtar kelimesi kullanmaktır. Oluşturacağımız alanların başına staticanahtar kelimesi getirerek oluşturacağımız değişkenler, sınıf değişkenleri olarak adlandırılır. Bu alanlara, sınıftan bir nesne oluşturmadan doğrudan sınıf adı ile erişim yapılabilir. static olarak tanımlanmış değişkenler, yani sınıf değişkenleri, o sınıftan oluşturulan her nesne için ayrı ayrı oluşturulmaz. Dolayısıyla sınıf değişkenleri, bellekte tek bir yerde tutulurlar. Ayrıca sınıf değişkenleri, o sınıftan nesne oluşturulmasa bile bellekte bunun için yer ayrılır. Fakat nesne değişkenlerinde, nesne oluşturulduğunda o değişken bellekte yer kaplamaya başlar. Static anahtar kelimesine, sınıf ve nesne değişkenleri konusunda değinmiş ve giriş yapmıştık. Şimdi bunu bir örnekle pekiştirelim. //Kisiler.java - 06.04.2014 1 2 package staticanahtar; 3 4 public class Kisiler 5 { 6 private String ad; // nesne değişkeni 7 private String soyad; // nesne değişkeni 8 private String cinsiyet; // nesne değişkeni 9 public static int sayi = 0; // sınıf değişkeni 10 11 public Kisiler(String ad, String soyad, String 12 cinsiyet) 13 { 14 this.ad = ad; 15 this.soyad = soyad; 16 this.cinsiyet = cinsiyet; 17 sayi++; // static değişkenin değeri artırıldı. 18 } 19 } 20 21 Programımızın bir de main metodunu yazalım ve inceleyelim. 1 //MainMetodu.java - 06.04.2014 2 3 package staticanahtar; 4 5 public class MainMetodu 6 { 7 public static void main(String[] args) 8 { 9 System.out.println("Başlangıçta kişi sayısı: " + Kisiler.sayi); 10 // sayı değişkenine sınıf adı ile eriştik 11 Kisiler kisi1 = new Kisiler("Okan", "Bilke", "Erkek"); 12 Kisiler kisi2 = new Kisiler("Onur", "Bilke", "Erkek"); 13 Kisiler kisi3 = new Kisiler("Mustafa", "Bilke", "Erkek"); 14 System.out.println("Nesneler oluşturulduktan sonraki kişi sayısı: " + kisi1.sayi); } } 15 16 17 18 19 Ekran çıktısı: 1 Başlangıçta kişi sayısı: 0 2 Nesneler oluşturulduktan sonraki kişi sayısı: 3 Örneğimizi açıklayalım. 1. main metodumuz içerisinde ilk olarak kişi sayımızı yazdırdık. Buradaki sayi değişkenine, görüldüğü gibi doğrudan sınıf adı ile eriştik, herhangi bir nesne oluşturmadık. 2. Daha sonra 3 tane nesne oluşturduk ve ilk değerlerini verdik. Kisiler sınıfının yapıcısı ile bu değerler ad,soyad ve cinsiyet değerlerine atandı. Kisiler sınıfımızın yapıcısında, sayi değişkenimizin değerini, her nesne oluşturmada 1 artırdık. Çünkü bir sınıftan nesne oluşturulduğunda ilk olarak oluşturulan sınıfın yapıcısı çağırılır. 3. Son olarak da nesneler oluşturulduktan sonraki sayi değişkenimizin değerini ekrana yazdırdık. 3 adetkisi nesnesi oluşturduğumuz için ve bunlar oluşturulurken, çağırılan her yapıcıda sayi değeri arttığı için ekrana 3 yazdı. Bu değişkene ise sınıf adı ile değil nesne ile eriştik. Yani burada sınıf değişkenlerini, oluşturulan tüm nesneler etkiler. Bu yüzden sınıf değişkenleri staticolarak tanımlanır ve bu değişkenlere erişmek için nesne oluşturmak gerekmez. STATIC METODLAR Değişkenleri static olarak tanımladığımız gibi metodları da static olarak tanımlayabiliriz. Bu şekilde tanımlanmış metodlara en iyi örnek Math sınıfının metodlarıdır. Örneğin; Math sınıfının sqrt() fonksiyonunu kullanabilmek için bu sınıftan bir nesne oluşturmak gerekmez. Doğrudan Math.sqrt(); fonksiyonunu kullanarak karekök aldırabiliriz. Bunun sebebi; Math sınıfındaki tüm metodların static olarak tanımlanmasıdır. Static metodların kullanımına bir örnek verelim. //Kisiler.java - 06.04.2014 1 2 public class Kisiler 3 { 4 public static String ad = 5 "Okan"; 6 7 public static int isimGetir() 8 { 9 return ad; 10 } 11 } 12 13 Metodumuzun başına da static anahtar kelimesini getirdik. Bunu, sınıf adı ile erişmek için yaptık. staticmetodlara nesne oluşturmadan da erişebiliriz. Bu static metodlar içerisinden bir değişkene veya başka bir metoda ulaşmak istersek, doğrudan çağırmak mı gerekir? Burada bir not düşmemiz gerekiyor. Istisnalar: Static metodlar içerisinden, static olmayan bir değişkene ! erişilemez ve static olmayan bir metod çağırılamaz. Fakat bunun tam tersi olabilir. Yani static olmayan bir metod içerisinden, static olan bir değişkene erişilebilir ve static olan bir metod çağırılabilir. static bir metod içerisinden, static olmayan bir değer döndürmeye çalışırsak veya bir static olmayanmetod çağırırsak, aşağıdaki hatayı alırız. 1 Cannot make a static reference to the non-static field ad Neden böyle bir hata alırız? Bir nesne olmadığında static metodlara erişebiliriz. Fakat nesnesiz olarak eriştiğimiz bu metoddan, staticolmayan bir metoda veya değişkene ulaşamayız. Çünkü bunlara ulaşmak için nesne gerekir. Bu konuyu Ders 35 - Static Metodlar dersinde daha detaylı incelemiştik. Static olan metodlara, sınıf adı.metodadı(); şeklinde erişebiliyoruz. Eğer sınıf adını da yazmadan doğrudan metod adı ile erişmek istersek, ne yapmamız gerekir? Bunun için ise Static Import yöntemini kullanacağız. STATIC IMPORT Bunu math.sqrt() metodu üzerinden anlatalım. Biz doğrudan sqrt() fonksiyonunu çağırarak işlem yaptırmak istiyorsak, yapmamız gereken yukarıda import ettiğimiz java.lang.Math.* sınıfının başına staticanahtar sözcüğünü getirmektir. Bunu bir örnekle açıklayalım. 1 //MainMetodu.java - 06.04.2014 2 3 import static java.lang.Math.*; 4 5 public class MainMetodu 6 { 7 public static void main(String[] args) 8 { 9 System.out.println("5 üzeri 2: " + pow(5, 2)); 10 } 11 } 12 13 Ekran çıktısı: 1 5 üzeri 2: 25.0 Görüldüğü gibi import kelimesinden sonra static getirerek Math sınıfının bütün metodlarını ekledik. ArtıkMath sınıfının bütün metodlarını doğrudan kullanabiliriz. Ders 55 - Enum Kavramı Enum'lar sınıflara benzer. Kendilerine ait yapıcıları vardır. Bünyesinde üyeler barındırır. Enum tanımlamak için enum anahtar kelimesi kullanılır. Konuyu anlattıktan sonra Enum kavramının ne olduğunu, ne işe yaradığını daha iyi anlayacaksınız. ENUM TANIMLAMA Basit bir enum tanımlaması yapalım. enum Hayvanlar {KEDI, KOPEK, YILAN, 1 TAVSAN} 2 // enum elemanlarının arasına virgül koyulur Şimdi buradaki elemanları çağıran bir sınıf yapalım. 1 //Enum.java - 06.04.2014 2 3 enum Hayvanlar 4 { 5 KEDI, KOPEK, YILAN, TAVSAN 6 } 7 public class Enum 8 { 9 public static void main(String[] args) 10 { 11 System.out.println(Hayvanlar.KEDI); 12 System.out.println(Hayvanlar.KOPEK); 13 System.out.println(Hayvanlar.YILAN); 14 System.out.println(Hayvanlar.TAVSAN); 15 } 16 } 17 18 Ekran çıktısı: 1 KEDI 2 KOPEK 3 YILAN 4 TAVSAN Enum içerisindeki elemanlara, enum adı ile erişebiliyoruz. Bu enum içerisindeki elemanlara değerler de verebiliriz. İçerisinde yapıcı olan ve enum elemanlarına değer verdiğimiz bir enum tanımlarsak: //Arabalar.java - 06.04.2014 1 2 enum Arabalar 3 { 4 AUDI(200), BMW(190), OPEL(180), FIAT(160); // enum elemanlarına 5 değer verdik 6 public int hiz; 7 Arabalar(int hiz) // enum yapıcısı. Public olamaz. 8 { 9 this.hiz = hiz; 10 } 11 } 12 13 Burada enum yapımızın adı Arabalar'dır. İçerisinde 4 eleman var ve bunların değerlerini parantez içerisinde verdik. Yapıcımız da enum ile aynı isimdedir. Aldığı int değerini enum içerisindeki elemanların hizdeğerine atar (parantez içerisindeki değere). Tabi bunun için de int tipinde bir hiz değişkeni tanımladık. Hemen ilk notumuzu da düşelim. Istisnalar: ! Enum içerisindeki yapıcılar public olamaz ve enum'lar, bir sınıftan türetilemezler (miras alamazlar). Yukarıdaki yapı için de bir örnek verelim. 1 //Enum2.java - 06.04.2014 2 3 enum Arabalar 4 { 5 AUDI(200), BMW(190), OPEL(180), FIAT(160); // enum elemanlarına 6 değer verdik 7 public int hiz; 8 Arabalar(int hiz) // enum yapıcısı. Public olamaz. 9 { 10 this.hiz = hiz; 11 } 12 } 13 14 public class Enum2 15 { 16 public static void main(String[] args) 17 { 18 System.out.println(Arabalar.AUDI.hiz); 19 System.out.println(Arabalar.BMW.hiz); 20 System.out.println(Arabalar.OPEL.hiz); 21 System.out.println(Arabalar.FIAT.hiz); 22 } 23 } 24 Ekran çıktısı: 1 200 2 190 3 180 4 160 Bu örnekte, enum içerisindeki değerleri ekrana yazdırdık. Burada değişken olarak belirlediğimiz hiz değişkeni, parantez içerisindeki değerler oluyor. enum içerisindeki her elemanın bir hız değişkeni olmuş oldu. Örneğimizde de bunu yazdırdık. enum içerisindeki elemanların değerlerini kendimiz de verebilirdik. Bunu da gösterelim. 1 //Enum3.java - 06.04.2014 2 3 enum Arabalar2 4 { 5 AUDI, BMW, OPEL, FIAT; 6 public int hiz; 7 } 8 9 public class Enum3 10 { 11 public static void main(String[] args) 12 { 13 Arabalar2.AUDI.hiz = 230; 14 Arabalar2.BMW.hiz = 210; 15 System.out.println(Arabalar2.AUDI.hiz); 16 System.out.println(Arabalar2.BMW.hiz); 17 } 18 } 19 20 Ekran çıktısı: 1 230 2 210 enum içerisindeki elemanlar yalnızca int tipinde değerleri almazlar. Bir de String tipinde veri aldığı duruma örnek verelim. //Enum4.java - 06.04.2014 1 2 enum Arabalar3 3 { 4 AUDI("Siyah"), MERCEDES("Beyaz"); 5 public String renk; 6 7 Arabalar3(String renk) // yapıcımız String tipinde 8 parametre aldı 9 { 10 this.renk = renk; 11 } 12 } 13 14 public class Enum4 15 { 16 public static void main(String[] args) 17 { 18 System.out.println(Arabalar3.AUDI.renk); 19 System.out.println(Arabalar3.MERCEDES.renk); 20 } 21 } 22 23 Ekran çıktısı: 1 Siyah 2 Beyaz Örnekte de yaptığımız üzere enum elemanları String tipte değerleri almıştır. ENUM İÇERİSİNDEKİ ELEMANLARI YAZDIRMAK Enum içerisindeki elemanları tek tek yazdırmak yerine bilindiği gibi for döngüsü ile yapabiliriz. Fakat foryerine foreach (gelişmiş for döngüsü) yapısını kullanacağız. foreach ile enum elemanlarını yazdırma ile ilgili bir örnek verip bu özelliği geçelim. //Enum5.java - 07.04.2014 1 2 enum Arabalar4 3 { 4 AUDI("Siyah"), MERCEDES("Beyaz"); 5 public String renk; 6 7 Arabalar4(String renk) // yapıcımız String tipinde 8 parametre aldı 9 { 10 this.renk = renk; 11 } 12 } 13 14 public class Enum5 15 { 16 public static void main(String[] args) 17 { 18 for(Arabalar4 a: Arabalar4.values()) 19 { 20 System.out.print(a.name() + " - "); 21 System.out.println(a.renk); 22 } 23 } 24 } 25 26 Ekran çıktısı: AUDI - Siyah 1 MERCEDES 2 Beyaz foreach dediğimiz döngü tipinde önce değişkenin tipi yazılıyordu, fakat burada değişkenimizin tipiArabalar4'dır. Çünkü o tipteki bir elemandır. Dizilerdeki gibi düşünürsek Arabalar4.values() dediğimizde de o enumdaki elemanları kastediyoruz. Daha sonra a.name ile bu enum verilerini yazdırıyoruz ve a.renk diyerek de parantez içerisindeki değerleri yazdırıyoruz. a.name değil de sadece a yazsaydık, yine aynı sonucu elde ederdik. Çünkü buradaki a, enum içerisindeki bir elemana karşılık geliyor. ORDİNAL METODU İLE ENUM ELEMANLARININ İNDİSİNİ ÖĞRENME Enumlar yapı olarak hem dizilere hem de sınıflara benzerler. Diziye benzeyen kısmına bakarsak, enum elemanlarının bir indisinin olduğunu söyleyebiliriz. Her elemanın bir indisi vardır ve ilk indis dizilerdeki gibi sıfır (0)'dan başlar. Buna bir örnek verelim. 1 //Enum6.java - 07.04.2014 2 3 enum Arabalar5 4 { 5 AUDI, MERCEDES; 6 } 7 8 public class Enum6 9 { 10 public static void main(String[] args) 11 { 12 System.out.println(Arabalar5.AUDI.ordinal()); 13 System.out.println(Arabalar5.MERCEDES.ordinal()); 14 } 15} 16 17 Ekran çıktısı: 1 0 2 1 Ordinal() metodu ile enum elemanlarının indisini öğrenebiliriz. Enum elemanlarının bir indisi olduğunu söylemiştik. Bu indisi bulmayı öğrendik. Şimdi bu indisi kullanarak da bir örnek yapalım. Bu örneği yaparken switch yapılarını da kullanacağız. Bu da demek oluyor ki enum elemanları switch içerisinde bulunabilir. //Enum7.java - 07.04.2014 1 2 enum aylar 3 { 4 ocak, subat, mart // sona noktalı virgül 5 gelmeyebilir 6 } 7 8 public class Enum7 9 { 10 public static void main(String[] args) 11 { 12 int x = aylar.mart.ordinal(); // mart ayının indisi 13 alındı 14 switch(x) 15 { 16 case 0: System.out.println("Ocak ayındayız"); 17 break; 18 case 1: System.out.println("Şubat ayındayız"); 19 break; 20 case 2: System.out.println("Mart ayındayız"); 21 break; 22 default: System.out.println("Bu aylarda değiliz"); 23 break; 24 } 25 } 26 } 27 Ekran çıktısı: 1 Mart ayındayız Aylar adında bir enum tanımladık ve elemanlarını belirledik. Ordinal metodu ile Mart ayının indisini bir xdeğişkenine attık. Daha sonra bildiğiniz switch yapısı ile bunu karşılaştırdık. ENUM İÇERİSİNDE METOD TANIMLAMA Enum içerisinde değişken ve yapıcı tanımlamayı gördük. Şimdi de enum içerisinde metod tanımlamayı görelim. Enum içerisinde metodlar da tanımlanabilir. 1 //Enum8.java - 07.04.2014 2 3 enum Maaslar 4 { 5 Okan(1000), Onur(1200), Göksu(2000); 6 private int maas; 7 Maaslar(int m) 8 { 9 maas = m; 10 } 11 int maasGoster() 12 { 13 return maas; 14 } 15 static void metod2() 16 { 17 System.out.println("Burası metod2'dir"); 18 } 19} 20 21public class Enum8 22{ 23 public static void main(String[] args) 24 { 25 System.out.println(Maaslar.Okan.maasGoster()); 26 System.out.println(Maaslar.Onur.maasGoster()); 27 System.out.println(Maaslar.Göksu.maasGoster()); 28 Maaslar.metod2(); 29 } 30} 31 32 Ekran çıktısı: 1 1000 2 1200 3 2000 4 Burası metod2'dir Enum içerisinde 2 farklı metod tanımladık. Birisi maaşları döndürüyor diğeri ise ekrana bir String yazıyor.main metodunda ise, bu metodları çağırdık. Metod2'ye main içerisinden erişebilmek için static olarak tanımladık. Ders 56 - Annotation Kavramı Annotation kavramı ilk olarak Java 5 ile karşımıza çıkmıştır. Annotation, Java koduna eklenebilen sınıf, metod, değişken, parametre ve paketlere ön bilgi ve metadata eklemek için kullanılan yapılardır. Annotation'lar üç şekilde kullanılabilir. Bunlar: Derleyici bilgilendirme için kullanılabilir. Bu tip kullanılan annotation'lar sayesinde derleyici hataları ve uyarıları görmezden gelir. Derlenme ve yüklenme anında kullanılarak otomatik kod ve XML dosyası oluşturma gibi işlemlerde kullanılabilirler. Çalışma anında işletilerek kodun annotation'a göre çalışması sağlanır. Annotation'lar başına @ işareti yazılarak kullanırlar. Her durumda annotation'lar bilgilendirilmek istenilen nesneden önce gelmelidir. Bazı annotation'lar derleyici ön tanımlı durumdadır. Bazı metodları kullandığımızda derleyicinin annotation ile sağladığı uyarıyla karşılaşabiliriz. Örneğin; @Override: Miras alınan sınıf içerisindeki bir metodu, alt sınıfta yeniden tanımlamak istediğimizde, derleyici bize bunu annotation ile bildirir. @Override 1 void metod() 2 { 3 // metod 4 gövdesi 5 } @Deprecated: Sürümü eski olan metodlar kullanıldığında, derleyici bizi bu annotation ile uyarır. 1 @Deprecated 2 static void main() 3 { 4 5 // metod gövdesi } @SuppressWarnings: Bu annotation tipi, parametre olarak vereceğimiz uyarı tipini derleyicinin göz ardı etmesini sağlar. 1 @SuppressWarnings("karşı koyma") 2 void metod() 3 { 4 // metod gövdesi 5 } ANNOTATION OLUŞTURMA Java'daki annotation'lar, sadece derleyicinin bize sunduğu annotation'larla sınırlı değildir. Kendimiz özel durumlar için annotation yazabiliriz. Annotation yazmak, interface yazmaya benzer. Annotation'umuzu yazarken @interface anahtar kelimesi ile işaretlemeliyiz. Örnek bir annotation tanımı aşağıdaki gibi olacaktır. public @interface 1 annotationOrnegi 2 { 3 // metod gövdesi 4 } Bu, tüm birimler için annotation tanımına örnektir. Eğer annotion'u bir birim ile sınıflandırmak istiyorsak, annotation'dan önce @Target anahtar kelimesini ve bunun tipini yazmalıyız. Aşağıda @Target anahtar kelimesinin tipleri verilmiştir. @Target(ElementType.TYPE): Sadece sınıf, enum ve interface için sınırlanır. @Target(ElementType.PACKAGE): Sadece paketler için sınırlandırılır. @Target(ElementType.METHOD): Sadece metodlar için sınırlandırılır. @Target(ElementType.LOCAL_VARIABLE): Sadece yerel değişkenler için sınırlandırılır. @Target(ElementType.CONSTRUCTOR): Sadece yapıcı metod için sınırlandırılır. @Target(ElementType.FIELD): Sadece sınıf üyeleri için sınırlandırılır. @Target(ElementType.ANNOTATION_TYPE): Sadece annotation birimleri için tanımlanan annotation sınırlandırılır. Annotation yazarken bir diğer belirteceğimiz unsur ise, derleyicinin derleme ve çalışma anında annotation'a erişip erişemeyeceği unsurdur. Bunu belirtirken; aynen @Target anahtar kelimesi olduğu gibi annotation'dan önce @Retentation anahtar kelimesi ve tipini yazmamız gerekir. Derleyicinin derleme anında annotation'a erişmesini istiyorsak, aşağıdaki anahtar kelimeyi annotation'dan önce yazmalıyız. 1 @Retention(RetentionPolicy.RUNTIME) Tüm bu gördüklerimizi bir örnek üzerinden kısaca anlatmaya çalışalım. 1 //annotationOrnegi.java - 07.04.2014 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Target(ElementType.TYPE) 9 @Retention(RetentionPolicy.RUNTIME) 10 @interface geoBilgi 11 { 12 public String sekilIsmi(); 13 public int kenarSayisi(); 14 } 15 @geoBilgi (sekilIsmi = "Düzgün Sekizgen", kenarSayisi = 8) 16 class geometrikSekil 17 { 18 public int icAci(int kenar) 19 { 20 return (180*(kenar - 2)) / kenar; 21 } 22 public int kosegenSayi(int kenar) 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 { return (kenar*(kenar - 3)) /2; } } public class annotationOrnegi { public static void main(String args[]) { geometrikSekil g = new geometrikSekil(); geoBilgi annotation = g.getClass().getAnnotation(geoBilgi.class); // annotation bilgilerimizi oluşturduğumuz nesne içerisine aldık. int aci = g.icAci(annotation.kenarSayisi()); // kenar sayısını annotation içerisinden aldırarak geometrik şeklimizin iç açısını bulduk. int kosegen = g.kosegenSayi(annotation.kenarSayisi()); // yine kenar sayısını annotationdan alarak köşegen sayısını bulduk. System.out.println(annotation.sekilIsmi() + " : "); System.out.println("Bir iç açısı = " + aci); System.out.println("İçerisinden geçen toplam köşegen sayısı = " + kosegen); } } Ekran çıktısı: Düzgün Sekizgen : 1 Bir iç açısı = 135 2 İçerisinden geçen toplam köşegen sayısı 3 = 20 Örneğimizde ilk aşamada bir annotation tanımladık. Bu annotation, geometrik şeklimizin ismini ve kenar sayısını tutuyor. Derleyicinin derleme anında ulaşabilmesi için @Retention ve annotation'un sadece sınıflar ile sınırlandırmak için @Target anahtar kelimesini kullandık. Daha sonrasında geometrikSekil sınıfımızı tanımlamadan önce sınıfımıza oluşturduğumuz annotation'u ekledik. Bütün annotation'ları elde etmek içingetAnnotation() metodunu kullandık. Böylelikle aynı türden birden fazla annotation olması durumunda annotation'ları bir arada toplayabiliriz. Köşegenimizin bir iç açısını hesap edebilmek için nesnemizin metoduna parametre olarak annotation'dan aldığımız bilgiyi gönderdik ve geometrik şeklimizin bir açısını elde ettik. Bu işlemlerin aynısını köşegen sayısını bulmak için bir daha tekrar ettik ve köşegen sayısını elde ettik. Daha sonra bu bilgileri ekrana yazdırdık. Ders 57 - Garbage Collector (Çöp Toplayıcı) Java dilinin üstünlüklerinden biri de Garbage Collection yapıcısının bulunmasıdır. Programlarda bazı nesnelerin kullanımı bittiğinde bellekten silinmeleri gerekir. C++ dilinde bu işi kendimiz yapıyorduk, fakat Java'da otomatik olarak yapılıyor. Bir nesneye programda bir referans verildiğini düşünelim. Mesela; 1 Hayvan h; Burada new anahtar kelimesini kullanmadığımız için hnesnesi bellekte bir yer kaplamaz. Ona sadecereferans verilmiştir. Bu şekilde programda olan nesnelerin silinmeleri gerekir. Java, dediğimiz gibi bu işi otomatik olarak yapar. Belirli aralıklarla programı kontrol edip, işi bitmiş ve işaret edilmemiş nesneleri siler. Kullanılmayan bu nesneler uygulamanın performansını da etkiler. Bu şekilde biriken nesneler, programda OutOfMemoryException hatası verir. Eğer bir nesne new operatörü ile oluşturulup belleğe yerleşmek ister ve bellekte de yer kalmamış olursa, Garbage Collector hemen bellekteki gereksiz nesneleri silerek yer ayırır. Nesneler, belleğin heap alanında toplandığı için Garbage Collector bu alanda işlem yapar. Çöp toplama isteğini JVM'e gönderir. Mükemmel bir algoritmaya sahip olan Garbage Collector, Java dilinin önemli artılarındandır. Kullanmayan nesneleri temizleyerek o alanı belleğe tekrar iade eden bu Garbage Collector, otomatikolarak çalışır. Fakat bunu manuel, yani kendimiz çalıştırmak istiyorsak; şu kod satırını kullanmamız gerekir. 1 Runtime. getRuntime.gc(); Veya 1 System.gc(); Eğer uygulamamızda gereksiz nesneler bulunmuyorsa, Garbage Collector devreye girmez. Yukarıdaki kodlardan birini yazarak Çöp Toplayı'yı etkin hale getirebiliriz. FINALIZE METODUNUN KULLANIMI Java'da bir nesneyi silmek istediğimizde ek olarak çalışan bir metod daha vardır. Bu metod finalize()metodudur. Garbage Collector, nesneleri silmeden önce bu metodu çağırır ve kullanır. Dolayısıyla nesneyi silerken yapmak istediğimiz şeyler bu metod ile yapılır. //GarbageCollector.java - 07.04.2014 1 2 public class GarbageCollector 3 { 4 GarbageCollector() 5 { 6 System.out.println("Nesne oluşturuldu"); 7 } 8 protected void finalize() 9 { 10 System.out.println("Nesne silindi. Silinirken bu metod 11 çalıştı"); 12 } 13 public static void main(String args[]) 14 { 15 for(int i = 0 ; i < 3 ; i++) 16 { 17 GarbageCollector n1 = new GarbageCollector(); 18 } 19 Runtime.getRuntime().gc(); // JM, Garbage Collector'u 20 çağırdı 21 } 22 } 23 Ekran çıktısı: Nesne oluşturuldu Nesne oluşturuldu 1 Nesne oluşturuldu 2 Nesne silindi. Silinirken bu metod 3 çalıştı 4 Nesne silindi. Silinirken bu metod 5 çalıştı 6 Nesne silindi. Silinirken bu metod çalıştı Garbage Collector, JVM tarafından çağırılır ve kontrol edilir. Bu örnekte 3 nesne oluşturduk ve Garbage Collector'u çağırdık. Bu da finalize() metodunu işlenmek üzere çağırdı ve bu metod içerisindeki işlendi. Bu metodun Protected olmasının sebebi; bu sınıfın dışından bu metoda erişilememesi ve nesnelerin dışarıdan yok edilememesi gerekliliğidir. Istisnalar: ! Nesnelerin silinme sırası, oluşturulma sıralarının tam tersidir. İlk oluşturulan nesne en son silinir. Istisnalar: Dosya okuma yazma işlemlerinde de Stream kullanarak bir işlem yaptığımızda o Stream'ı kapatmak için definalize() metodu ! kullanılır. Okuma yazma işlemi için oluşturulan nesneler, finalize() metodu ile bellekten silinirler. Diyelim ki işlemleri o1 nesnesi ile yaptık. o1.finalize(); diyerek nesneyi silebiliriz. super.finalize() ile üst sınıfın finalize() metodu çağırılabilir. 1 //Calistir.java - 07.04.2014 2 3 class A 4 { 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 A() { System.out.println("A sınıfından nesne oluştu"); } protected void finalize() { System.out.println("Burası A'nın finalize metodu"); } } class B extends A { protected void finalize() { System.out.println("Burası B'nin finalize metodu"); } B() { super.finalize(); System.out.println("B sınıfından nesne oluştu"); } } public class Calistir { public static void main(String args[]) { B nesne1 = new B(); Runtime.getRuntime().gc(); } } Ekran çıktısı: 1 A sınıfından nesne oluştu 2 Burası A'nın finalize metodu 3 B sınıfından nesne oluştu nesne1 adında bir nesne oluşturduk ve B sınıfının yapıcısı çalıştı. Üst sınıftan türetildiği için doğrudan ilk olarak A sınıfının yapıcısı çalışmış oldu. Daha sonra üst sınıfın finalize() metodunun çalışmasını istedik ve Asınıfının finalize() metodu çalıştı. Bundan sonra ise B'nin yapıcısındaki metin ekrana yazıldı. Bu işlemlerden sonra da Garbage Collector'u çağırdık ve gereksiz nesneler varsa temizlenmesini istedik. Garbage Collector yapısı ve finalize() metodu genel olarak bu şekildedir. Istisnalar: Bu bölümden sonra Kalıtım, Soyut Sınıflar, ! Arayüzler, Çok Biçimlilik gibi Nesneye Yönelik Programlamanın temek kavramlarını inceleyeceğiz. Ders 58 - Kalıtım Kavramına Giriş Nesneye yönelik programlamanın temel taşlarından biri olan Kalıtım, sınıflardan yeni sınıflar türetmeyi sağlar. Türetilen bu yeni sınıflar, türetildiği sınıfların özelliklerine sahip olur. Örneğin; Araç adında bir sınıfımız olsun. Otomobil sınıfını bu Araç sınıfından türettiğimiz zaman Otomobil sınıfı, Araç sınıfının özelliklerini taşır. Aynı şekilde Hayvan adında bir sınıfımız olsun. Sürüngenler adında bir sınıfı bu Hayvan sınıfından türetirsek,Hayvan sınıfını genişletmiş oluruz ve Sürüngenler sınıfı, Hayvan sınıfının özelliklerini taşımış olur. Fakat bunun tersi doğru değildir. Hayvan sınıfı, Sürüngenler sınıfının her özelliğini taşımayabilir. Kalıtım yapmak için kullanacağımız kelime extends'dir. Şimdi Hayvan sınıfından Surungenler sınıfını türetelim. public class Hayvan 1 { 2 } 3 public class Surungenler extends 4 Hayvan 5 { 6 } Bu şekilde tanımlama yaptığımızda Surungenler sınıfındaki elemanlar, Hayvan sınıfının elemanlarını miras almış oluyor. Hayvan sınıfından extends ile bir sınıf daha oluşturabiliriz, fakat bir sınıfı hem Hayvan hem deMemeliler sınıfından türetemeyiz. Yani bir sınıf, birden fazla sınıftan türetilemez. Surungenler sınıfı, Hayvan sınıfının elemanlarını miras aldığı zaman, Hayvan sınıfındaki aynı olan özellikleri tekrar tanımlamasına gerek kalmaz. Kalıtımın amacı da budur zaten. Bunun yanında Hayvansınıfından aldığı metod ve değişkenlere başka metod ve değişkenler de ekleyebilir. Eğer biz Surungenler adlı bir sınıf oluşturacaksak, aynı metodları tekrar yazmak yerine Hayvan sınıfını miras alırız. Eğer ekleyeceğimiz farklı metodlar varsa da bunları Surungen sınıfına dahil ederiz. Şimdi kalıtım konusunda ilk örneğimizi verelim. Hayvan Sınıfı: //Hayvan.java - 07.04.2014 1 2 public class Hayvan 3 { 4 public void nefesAl() 5 { 6 System.out.println("Nefes alma 7 metodu"); 8 } 9 } 10 11 Surungen Sınıfı: //Surungen.java - 07.04.2014 1 2 public class Surungen extends Hayvan // Surungen sınıfını Hayvan sınıfından 3 türettik 4 { 5 public static void main(String[] args) 6 { 7 Surungen s = new Surungen(); 8 s.nefesAl(); // artık bu sınıfımız da nefesAl metoduna sahip oldu 9 } 10 } 11 12 Ekran çıktısı: 1 Nefes alma metodu Burada Surungen sınıfını Hayvan sınıfından türettik ve Surungen sınıfı içerisinde, nefesAl() metodunu tanımlamadan bu metoda erişebildik. Istisnalar: ! Kalıtımın en büyük avantajı bizi, üst sınıflarda tanımlanmış olan metod ve değişkenleri tekrar tekrar yazmaktan kurtarmasıdır. Ders 59 - Super Class ve Sub Class Kavramları SUPER CLASS (ÜST SINIF) VE SUB CLASS (ALT SINIF) KAVRAMLARI Kalıtım konusuna bir başka somut örnek verelim ve bununla birlikte bir kavramı daha açıklayalım.Otomobil adında bir sınıfımız olsun. Yarış otomobili ve aile otomobili sınıfları, Otomobil sınıfının alt sınıflarıdır (Sub class). Otomobil sınıfı da diğer bu sınıfların üst sınıfıdır (Super - class). Otomobil örneğinde alt sınıflar, üst sınıfının tüm özelliklerine sahiptir. Bir yarış otomobili, otomobilsınıfındaki vites ve hız gibi değişkenlere ve bunun gibi metodlara sahip olur. Bunların yanında kendine ait metod ve değişkenleri de olabilir. Bir yarış otomobilinde normal otomobilden farklı olarak ek özellikler de bulunabilir. Bu ek özellikleri kendi sınıfına dahil edebilir. Bunun dışında yarış otomobili sınıfı, Otomobilsınıfındaki freneBas adlı bir metodu değiştirebilir. Buna metod overriding denir. Bunu ileriki konularda göreceğiz. Istisnalar: ! 1 2 3 4 Kalıtım ve üst sınıf - alt sınıf konusuna bir örnek daha verelim. //Calistirma.java - 06.04.2014 class Telefon { 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public Telefon() { System.out.println("Telefon sınıfının yapıcısı"); } } class AkilliTelefon extends Telefon { public AkilliTelefon() { System.out.println("AkilliTelefon sınıfının yapıcısı"); } } class CepTelefonu extends Telefon { public CepTelefonu() { System.out.println("CepTelefonu sınıfının yapıcısı"); } } class Nokia extends CepTelefonu { public Nokia() { System.out.println("Nokia sınıfının yapıcısı"); } } public class Calistirma { public static void main(String[] args) { Nokia n1 = new Nokia(); } } Ekran çıktısı: 1 Telefon sınıfının yapıcısı 2 CepTelefonu sınıfının yapıcısı 3 Nokia sınıfının yapıcısı Bu örneğimizde Calistirma sınıfındaki main metodunda, Nokia sınıfından bir nesne ürettik. Nokia sınıfı,CepTelefonu sınıfından türetilmiştir. CepTelefonu sınıfı ise Telefon sınıfından türetilmiştir. En yukarıdan başlayarak yapıcılar çağırılır ve en sonda ise ilk oluşturulan nesnenin olduğu sınıfın yapıcısı çağırılır. Bir sınıftan nesne oluşturulduğunda, o sınıfın yapıcısından önce, türetildiği sınıfın yapıcısı çağırılır. Bu şekilde en üst seviyedeki SuperClass'ın yapıcı metodu çağırılır. Bir örnek daha verelim. 1 //Kalitim.java - 06.04.2014 2 3 class Sinif1 4 { 5 int x; 6 void metod1() 7 { 8 System.out.println("Burası metod1"); 9 } 10 } 11 12 class Sinif2 extends Sinif1 // kalıtım yapıldı 13 { 14 int y; 15 void metod2() 16 { 17 System.out.println("Burası metod2"); 18 } 19 } 20 public class Kalitim 21 { 22 public static void main(String[] args) 23 { 24 Sinif2 s2 = new Sinif2(); // Sinif2'den türetildi 25 s2.x = 7; 26 System.out.println(s2.x); 27 s2.metod1(); 28 Sinif1 s1 = new Sinif1(); // s1.metod2(); bu metoda 29 erişilemezdi 30 } 31 } 32 Ekran çıktısı: 1 7 2 Burası metod1 Bu örnekte de Sinif2'den türetilen nesne ile Sinif1'in elemanlarına erişebiliyoruz. Eğer Sinif1'den bir nesne oluştursaydık, bu nesne ile Sinif2'nin elemanlarına erişemezdik. Bir de metodlara parametre geçirelim ve türetilmiş sınıf üzerinden bu metodlara erişelim. 1 //Kalitim2.java - 06.04.2014 2 3 class Sinif1_2 4 { 5 int x, y; 6 void degerAta (int a, int b) 7 { 8 x = a; 9 y = b; 10 } 11 } 12 13 class Sinif2_2 extends Sinif1_2 // kalıtım 14 yapıldı 15 { 16 int carp() 17 { 18 return x * y; 19 } 20 } 21 public class Kalitim2 22 { 23 public static void main(String[] args) 24 { 25 Sinif2_2 s2 = new Sinif2_2(); 26 s2.degerAta(5, 9); 27 System.out.println(s2.carp()); 28 } 29 } 30 Ekran çıktısı: 1 45 Sinif2_2'yi Sinif1_2'den türettik ve main metodunda Sinif2_2'den oluşturduğumuz nesne ile Super Class olan Sinif1_2'nin degerAta metodunu çağırdık. Bu metoda 5 ve 9 değerlerini gönderdik. Bu parametreler, x ve t değişkenlerine atandı. Daha sonra s2 nesnesi üzerinden carp metodunu çağırdık. Bu metod da, değerlerini atadığımız x ve y değişkenlerini çarparak geriye sonucu döndürdü. Peki, bu şekilde türetilen bir sınıf, türediği sınıfın her elemanına erişebilecek mi? Eğer Super Class'daprivate elemanlar varsa sub class'lardan erişilemez. Buna bir örnek verelim. //Kalitim3.java - 06.04.2014 1 2 class Sinif1_3 3 { 4 private int x = 6; // private eleman 5 } 6 7 class Sinif2_3 extends Sinif1_3 // kalıtım 8 yapıldı 9 { 10 public String ad = "Okan"; 11 } 12 public class Kalitim3 13 { 14 public static void main(String[] args) 15 { 16 Sinif2_3 s2 = new Sinif2_3(); 17 System.out.println(s2.x); // hata verir 18 } 19 } 20 21 Ekran çıktısı: 1 Exception in thread "main" java.lang.Error: Unresolved compilation 2 problem: 3 4 The field Sinif1_3.x is not visible at Kalitim3.main(Kalitim3.java:17) Görüldüğü gibi Sinif1_3'in private elemanlarına erişemeyiz. Ders 60 - Super Metodu ile Üst Sınıfın Yapıcısını Çağırmak Kalıtım ile bir sınıftan başka bir sınıf türetmeyi ve bunları kullanmayı önceki derslerimizde gördük. Bu dersimizde de farklı bir kavramdan bahsedeceğiz. Türetilen sınıf, türeyen sınıfın yapıcısına ulaşmak isterse ne yapmak gerekir? Bunun için super anahtar kelimesini kullanmalıyız. Bu anahtar kelimeyi kullanarak üst sınıfın yapıcısını çağırmak için super() metodunu çağırabiliriz. A sınıfından B sınıfını türettik diyelim. Bu B sınıfının yapıcısının içerisinde super() metodunu çağırırsak, Asınıfının yapıcısı çağırılmış olur. Istisnalar: ! Alt sınıftaki yapıcının içerisinde ilk olarak super() metodu yazılmalıdır. Bu alt sınıftaki yapıcıda ekrana yazdırma, başka bir metod çağırma gibi işlemler de olabilir. super() metodu, bunlardan önce ilk sırada yazılır. super() ile üst sınıfın yapıcısı çağırılacaksa ve bu üst sınıftaki yapıcılar da birden fazla ise hangisinin çağırılacağına şöyle karar verilir. super() metodunun parametrelerine, çağırılacak yapıcının parametreleri yazılır. Parametreleri eşleşen yapıcı çağırılır. Buna bir örnek verelim. 1 //B.java - 07.04.2014 2 3 class A 4 { 5 public A() // A'nın yapıcısı 6 { 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 System.out.println("A'nın yapıcısı"); } } class B extends A { public B() // B'nin yapıcısı { super(); // A'nın yapıcısı çağırıldı System.out.println("B'nin yapıcısı"); } public static void main(String[] args) { B nesne = new B(); } } Ekran çıktısı: 1 A'nın yapıcısı 2 B'nin yapıcısı Bu örnekte B'nin yapıcısında ilk olarak super() metodu ile üst sınıfın yapıcısını çağırdık. Yapıcılarda ilk olarak bunu çağırmamız zorunludur. super() ile çağırdığımız zaman A'nın yapıcısı çağrıldı. main metodumuzda da B sınıfından bir nesne oluşturduk. Bu ilk olarak B'nin yapıcısını çağırdı ve program anlattığımız şekilde çalıştı. Şimdi de A sınıfında birden fazla yapıcımız olsun. Yani yapıcılar aşırı yüklenmiş olsun (overloading). Buna bir örnek verelim. 1 //B2.java - 07.04.2014 2 3 class A2 4 { 5 public A2(int a) 6 { 7 System.out.println("Tek parametreli yapıcı: " + a); 8 } 9 public A2(int a, int b) 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 { System.out.println("İki parametreli yapıcı: " + a + " ve " + b); } } class B2 extends A2 { public B2() { super(4, 7); // ikinci parametreli yapıcı çağırıldı System.out.println("B'nin yapıcısı"); } public static void main(String[] args) { B2 nesne = new B2(); } } Ekran çıktısı: 1 İki parametreli yapıcı: 4 ve 7 2 B'nin yapıcısı A sınıfımızda 2 adet constructor (yapıcı) var. Birisi 1, diğeri 2 parametre alıyor. B sınıfını da A'dan türettik. Daha sonra B sınıfının yapıcısında 2 parametreli yapıcıyı çağırdık ve 2 adet int değerini gönderdik(super(4, 7). Eğer tek parametreli yapıcıyı çağırmak isteseydik super metodu içerisine sadece bir int değeri verirdik. Derleyici bunu otomatik olarak algılıyor ve super() metodu içerisinde kaç parametre varsa, o parametrelere sahip yapıcı çağırılıyor. Aşağıdaki örnekte ise yapıcılar içerisinde farklı işlemler yaparak, super() metodu ile bu yapıcıyı çağıralım. 1 //B3.java - 07.04.2014 2 3 class A3 4 { 5 int x; 6 String ad; 7 public A3(int a, String b) 8 { 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 x = a; ad = b; } public A3(String b, int a) // Çağırılan yapıcı budur { ad = b; x = a; } void yazdir() { System.out.println("Değerler : " + ad + " ve " + x); } } class B3 extends A3 { public B3() { super("Okan", 7); // 1. parametresi String, 2. parametresi int olan yapıcı çağırıldı } public static void main(String[] args) { B3 nesne = new B3(); nesne.yazdir(); } } Ekran çıktısı: Değerler : Okan ve 1 7 Bu örnekte super("Okan", 7) ile ilk parametresi String ikinci parametresi int olan yapıcıyı çağırdı ve gönderilen değerleri ad ve x değişkenlerine yazdı. main metodunda oluşturduğumuz nesne ile program çalışmaya başlayacaktır. B3 sınıfından bir nesne oluşturduğumuz için B3 sınıfının yapıcısı çağırıldı. Daha sonramain metodunda nesne.yazdir() diyerek A3 sınıfındaki yazdir metodunu çalıştırdık ve atanmış olan değerleri yazdırdık. super anahtar kelimesi ile ilgili söyleyeceğimiz son özellik de, bu kelimenin aynı zamanda sınıftaki değişkenlere erişmeyi sağlamasıdır. Bu özelliği örnek üzerinde anlatalım. //AltSinif.java - 07.04.2014 1 2 class UstSinif 3 { 4 int x; 5 } 6 class AltSinif extends UstSinif 7 { 8 int x; 9 public AltSinif(int i, int j) 10 { 11 super.x = i; // UstSinif'in x değişkenine 12 atar 13 x = j; // AltSinif'in x değişkenine 14 atar 15 } 16 public static void main(String[] args) 17 { 18 AltSinif nesne = new AltSinif(3, 6); 19 } 20 } 21 main metodunda nesneyi oluşturduk ve yapıcısına 3 ve 6 değerlerini gönderdik. AltSinif'in yapıcısında alınan i değeri super.x değişkenine atanır. Hem üst sınıfta hem de alt sınıfta bu değişken var. Peki, hangisine atama yapılıyor? Eğer super.x dersek üst sınıfın x değişkenine atama yapılır. Alınan j değeri de normal xdeğişkenine atandı. Bu x değişkeni de AltSinif sınıfındaki x değişkenidir. Bu örnekte, super anahtar kelimesi ile üst sınıftaki değişkenlere erişebileceğimizi gördük. Hatırlarsanızthis anahtar kelimesi de buna benzer bir iş yapıyordu. Fakat super anahtar kelimesi, üst sınıfın elemanlarına erişmeyi sağlarken, this ise bulunduğu sınıfın elemanlarına erişmeyi sağlıyordu. super metodunun kullanım şekli böyledir. Bunun ile ilgili bilmemiz gereken en önemli nokta, yapıcıların her zaman en üstünde tanımlanırlar. Ders 61 - Metod Overriding Kalıtım konusunda anlattığımız gibi, türetilen sınıf türediği sınıfın tüm özelliklerini taşıyor ve kullanabiliyordu. Fakat miras aldığı bu metodları aynen kullanmak istemezse, ne yapmamız gerekir? Buradaoverriding kavramı karşımıza çıkıyor. Bir sınıf, türetildiği sınıftaki bir metodu değiştirmek istediği zaman bunuoverriding ile gerçekleştiriyoruz. Bu şekilde metodları override ettiğimiz zaman alt sınıf, üst sınıfın metodunu doğrudan kullanmak yerine kendine ait bir metoda sahip oluyor. Şimdi bir örnek verelim. 1 //SinifA.java - 07.04.2014 2 3 public class SinifA 4 { 5 protected int sayi = 6; 6 public String ad = "Okan"; 7 public String metod() 8 { 9 return ad + sayi; 10 } 11 } 12 13 class SinifB extends SinifA 14 { 15 public String metod() // metod override edildi 16 { 17 return ad + sayi + ad; 18 } 19 } 20 21 class calistir 22 { 23 public static void main(String[] args) 24 { 25 SinifB n = new SinifB(); 26 System.out.println(n.metod()); 27 } 28 29 30 } Ekran çıktısı: 1 Okan6Okan Bu örnekte SinifB, SinifA'nın metodunu override ediyor. Artık kendine ait bir metodu oldu. mainmetodunda bu SinifB içerisindeki metodu çağırdığımızda, SinifA'nın değil SinifB'nin metodu çağırılıyor. EğerSinifB içerisinde bir metod tanımlasaydık, doğrudan SinifA içerisindeki metodu çalıştıracaktı. Onu da gösterelim. //SinifA.java - 07.04.2014 1 2 public class SinifA 3 { 4 protected int sayi = 6; 5 public String ad = "Okan"; 6 public String metod() 7 { 8 return ad + sayi; 9 } 10 } 11 12 class SinifB extends SinifA 13 { 14 // override edilen bir metod yok 15 } 16 17 class calistir 18 { 19 public static void main(String[] 20 args) 21 { 22 SinifB n = new SinifB(); 23 System.out.println(n.metod()); 24 } 25 } 26 27 Ekran çıktısı: 1 Okan6 Burada SinifB içerisinde bir metod yok. Daha doğrusu override edilen bir metod yok. O yüzdenSinifB'den bir nesne oluşturduğumuzda ve bu nesne üzerinden bir metod çalıştırdığımızda doğrudanSinifA'nın metodu çalışacaktır. Kalıtım konusunda, alt sınıf üst sınıfın elemanlarını tekrar tanımlamak zorunda kalmıyordu ve doğrudan kullanıyordu. Override ile istenilen metodlar tekrar tanımlanabilir ve aynı kendine göre düzenleyebilir. Istisnalar: ! Bir metodun override edilebilmesi için belli başlı kurallar vadır. Her metod override edilemez. Notumuzda söylediğimiz gibi bu belli başlı kurallara bir değinelim. Nasıl ki metodlar konusunda anlattığımız overload özelliği gibi override konusunda da genel olarak aynı şeyler geçelidir. 1. Override edilecek metodların dönüş tipi, metod adı, parametre listeleri aynı olmak zorundadır. 2. Alt sınıftaki override edilecek metodun erişim belirleyicisi, üst sınıftaki override edilen metodun erişim belirleyicisinden daha yüksek derecede olmalı. İlk maddeyi Ders 33 - Metodları Aşırı Yükleme (Overloading) konusundan biliyorum. Bunlardan bir tanesi farklı olduğu zaman override işlemi yapılamıyor. İkinci maddeyi ise örneğimiz üzerinden anlatalım. Alt sınıftaki metodumuzun erişim belirleyicisi public olarak tanımlanmıştır. Bu yüzden üst sınıftaki aynı metodun erişim belirleyicisi, public'ten daha kısıtlı olmalıdır. Eğer alt sınıftaki private olarak tanımlamış olsaydık üst sınıftaki metod private ve private'den daha kısıtlı olmalıdır. private'den daha kısıtlı olan yoktur. Mecburen üst sınıftakini de private tanımlamak zorunda kalırdık. Override konusuna bir örnek daha verelim. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 //A.java - 08.04.2014 class A { int x, y; A(int i, int j) // A sınıfının yapıcısı { x = i; y = j; } void yazdir() { System.out.println("x ve y değerleri: " + x + " " + y); } } class B extends A { int z; B(int i, int j, int k) // B sınıfının yapıcısı { super(i, j); // i ve j üst sınıfının yapıcısına gönderildi z = k; // alınan k değeri z'ye atandı } void yazdir(String yazi) // metod overriding { System.out.println(yazi + z); } } class calistir { public static void main(String[] args) { B nesne = new B(6, 1, 8); // B'den nesne oluşturulup ilk değer ataması yapıldı nesne.yazdir("Z'nin değeri: "); // B sınıfının yazdir() metodu çağırılır nesne.yazdir(); // A sınıfının yazdir() metodu çağırılır } } Ekran çıktısı: 1 Z'nin değeri: 8 2 x ve y değerleri: 6 1 Yazdığımız kodu açıklayalım. 1. İlk olarak main metodundan başlayalım. B sınıfından nesne oluşturduk ve parantezler içerisinde B'nin yapıcısına 3 değer gönderdik. Bu değerlerden ilk ikisi, super() ile üst sınıfın yapıcısına gönderildi. Gönderilen son değer ise z değişkenine atandı. 2. Daha sonra nesne.yazdir() diyerek parametre olarak bir String değeri gönderdik. Dolayısıyla Bsınıfındaki yazdir() metodu çalıştı. Normalde böyle bir metod olmasaydı doğrudan A sınıfındaki metod çalıştırılırdı. Fakat B sınıfı diyor ki, ben A'nın metodunu kullanmak istemiyorum kendi metodumu oluşturdum. 3. Son olarak nesne.yazdir() metodunu parametre göndermeden çalıştırdık. B sınıfında böyle bir metod olmadığı için default olarak A sınıfındaki yazdir() metodu çalıştırıldı. Üst sınıfa override ettiğimiz metodu doğrudan çağırmak için super() metodunu kullanabiliriz. Bir önceki örnekte bu metodu, üst sınıfın yapıcısına parametre göndermek için kullanmıştık. 1 //A.java - 08.04.2014 2 3 class A 4 { 5 void yazdir() 6 { 7 System.out.println("Burası A sınıfı"); 8 } 9 } 10 11 class B extends A 12 { 13 void yazdir() 14 { 15 super.yazdir(); // üst sınıftaki yazdir() metodu 16 çağırılır 17 System.out.println("Burası B Sınıfı"); 18 } 19 20 21 22 23 24 25 26 27 28 29 } class calistir { public static void main(String[] args) { B nesne = new B(); nesne.yazdir(); } } Ekran çıktısı: Burası A 1 sınıfı 2 Burası B Sınıfı yazdir() metodunu override ettik ve B sınıfındaki yazdir() metodunun içerisinde de üst sınıftaki yazdir() metodunu çağırdık. Bu dersimizden sonra overloading ve overriding kavramlarını karıştırmış olabilirsiniz. Bunu şöyle açıklayalım. Overriding'de metod adı, parametreler, tipler aynı olmak zorundadır. Overloading'de iseparametre sırası,tipleri veya sayısından en az biri farklı olmalıdır. Metod overriding konusunun temel mantığı bu şekildedir. Bu konuyu anlatırken super anahtar kelimesini de tekrar etmiş olduk. TOSTRING METODUNUN OVERRIDE EDİLMESİ toString() metodu, nesnelerin metin karşılıklarının ekrana yazılması için kullanılır. toString metoduObject sınıfı altında tanımlanmıştır yani her sınıf, toString() metoduna erişip bu metodu kullanabilir. AncaktoString metodu her zaman yeterli değildir. Nesnenin metin karşılığı yoksa toString() metodu, nesnenin sınıf ismini ve hafızadaki referansını geriye döndürür. Aşağıdaki örnek üzerinden bu durumu açıklayalım. 1 //toStringOrnegi.java - 08.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package toString; class sekil { int kose; int kosegen; int icAci; sekil(int kose) { this.kose = kose; kosegen = (kose * (kose - 3)) / 2; icAci = (180 * (kose - 2)) / kose; } } public class toStringOrnegi { public static void main(String[] args) { sekil geometrik = new sekil(5); System.out.println(geometrik); // System.out.println(geometrik.toString()); } } Ekran çıktısı: 1 toString.sekil@4f0e284f Yukarıdaki örnekte geometrik şekil tanımlayabildiğimiz bir sınıf oluşturduk. Daha sonrasında bu sınıftan bir nesne oluşturduk ve bu nesnenin metin karşılığını almak için nesneyi println() metoduyla ekrana yazdırdık. Böyle bir durumda Java sınıf içerisinde toString() metodunun override edilip edilmediğini kontrol eder. Sınıf içerisinde toString() metodu yoksa ya da eğer sınıf başka bir sınıfın alt sınıfıysa ve üst sınıfta toString()metodununun kullanılıp kullanılmadığını kontrol edilir. En son durumda Java, hiçbir yerde bu metodu bulamadığında Object sınıfında tanımlı olan genel toString() metodunu kullanır. Bu durumda Java, nesneninsınıf ismini ve hafızadaki referansını ekrana yazar. Örneğimizde tanımladığımız sınıf içerisinde toString metodunu override etmediğimiz için üst sınıfın yaniObject sınıfının toString() metodu çağrıldı ve metodumuzun bilgileri ekrana yazıldı. Burada toString.sekil()metodumuzun bulunduğu paket adı ve sınıfımızın ismini gösterir. Daha sonrasındaki @ işaretinden sonraki sayı ise metodumuzun bellekteki referansını gösterir. Dediğimiz gibi bir sınıfta toString() metodu yoksa nesneyi yazdırmak istediğimizde dönen değerler bu şekilde olur. Istisnalar: ! Eğer bir nesneyi ekrana yazdırdığımızda Object sınıfındaki toString() metodunun çalıştırılmasını ve yukarıdaki değerlerin döndürülmemesini istemiyorsak, bu metodu override edip kendimize göre düzenlemeliyiz. toString() metodunu override ederek nesnelerimizin daha anlaşılır olmasını sağlayabiliriz. Yukarıdaki örneği sınıf içerisinde toString() metodunu override edecek şekilde yeniden düzenleyerek bu konuyu açıklamaya çalışalım. 1 //toStringOrnegi.java - 08.04.2014 2 3 package toString; 4 5 class sekil 6 { 7 int kose; 8 int kosegen; 9 int icAci; 10 11 sekil(int kose) 12 { 13 this.kose = kose; 14 kosegen = (kose * (kose - 3)) / 2; 15 icAci = (180 * (kose - 2)) / kose; 16 } 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @Override public String toString() // toString metodu override edildi { return kose + " koşeli düzgün geometrik şeklin " + kosegen + " adet köşegeni vardır. Bir iç açısı ise " + icAci + " derecedir."; } } public class toStringOrnegi { public static void main(String[] args) { sekil geometrik = new sekil(8); System.out.println(geometrik); // nesne yazdırılıyor String s = "Sekizgen: " + geometrik; System.out.println(s); } } Ekran çıktısı: 8 koşeli düzgün geometrik şeklin 20 adet köşegeni vardır. Bir iç açısı ise 1 135 derecedir. 2 Sekizgen: 8 koşeli düzgün geometrik şeklin 20 adet köşegeni vardır. Bir iç açısı ise 135 derecedir. Örneğimizde bir önceki örnekten farklı olarak toString() metodunu override ettik. Bu sayede nesnemize ait metin bilgilerini metod üzerinden ekrana yazdırabildik. Örnekte görüldüğü gibi toString() metodu, sadece nesne println() metodu ile yazdırılmak istendiğinde çağrılmaz. toString() metodu nesne ile ilgili metin işlemleri gerektiren yerlerde çağrılır. Yukarıdaki örnekte kendi metinimizle nesnemizin döndüreceği metini birleştirdik ve bu anda toString() metodu çağrılmış oldu. Şimdi başka bir örnek verelim. Bu örnekte önce toString() metodunu override etmeden bir nesneyi yazdırmaya çalışalım. 1 //toStringOrnegi.java - 08.04.2014 2 3 package toString2; 4 5 class Calisan 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 { public String ad = "Okan"; public String soyad = "Bilke"; public int yas = 23; } public class toStringOrnegi { public static void main(String[] args) { Calisan kisi = new Calisan(); System.out.println(kisi); } } Ekran çıktısı: 1 toString2.Calisan@324a4e31 Biz burada kisi nesnemizi yazdırmak istediğimizde, aslında tüm bilgilerinin yazılmasını istedik. Fakat biz nesneyi yazdırmak istediğimizde biliyoruz ki; Object sınıfının toString() metodu çalıştırılır ve bu metod dapaketadı sınıfadı şeklinde değer döndürür. Nesnemize ait olan değerleri yazdırmak için kendimiz biz toString() metodu yazarak, Object sınıfındakitoString() metodunu override edelim. 1 2 3 4 5 6 7 8 9 10 11 //toStringOrnegi.java - 08.04.2014 package toString2; class Calisan { public String ad = "Okan"; public String soyad = "Bilke"; public int yas = 23; public String toString() // override işlemi 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 { return "Ad: " + ad + " Soyad: " + soyad + " Yas: " + yas; } } public class toStringOrnegi { public static void main(String[] args) { Calisan kisi = new Calisan(); System.out.println(kisi); } } Ekran çıktısı: 1 Ad: Okan Soyad: Bilke Yas: 23 Sınıfımız içerisinde toString() metodunu override ederek, nesnemizi yazdırmak istediğimizde nelerin yazılmasını istiyorsak, onu return ile ekleriz. Ders 62 - Final Anahtar Kelimesi Bu konuyu Değişkenler dersimizde kısaca anlatmıştık. Fakat Nesneye Yönelik Programlama ve Kalıtımdahilinde detaylı olarak incelemeyi daha uygun gördüm. Çünkü nesneye yönelik programlamada ve kalıtımda kullanılan bir çok özelliği bulunuyor. final anahtar kelimesi, Java'da temelde sabitler tanımlamaya yarar. Sabitler, değeri sabit olan değişkenlerdir. Örneğin; Pi sayısının değeri bir sabittir. Bunun dışında biz de istediğimiz bir değişkeni sabit olarak belirleyebiliriz. Final anahtar kelimesini yalnızca değişkenlere değil sınıflara, metodlara, parametre uygulayabiliriz. Dolayısıyla yalnızca sabit tanımlama görevi yoktur. Bunları ayrı ayrı inceleyeceğiz. Eğer bir sınıfı final olarak tanımlarsak bu sınıftan türetme yapamayız. Bir metodu final olarak tanımlarsak bu metodlar override edilemezler. Bir parametreyi final olarak tanımlarsak bu parametrenin değerini değiştiremeyiz. Bir değişkeni final olarak tanımlarsak da değerini değiştiremeyiz. FINAL İLE SABİT TANIMLAMA final anahtar kelimesi ile tanımlanmış değişkenlerin değeri değiştirilemez. Bunlara sabit değişkenler denir.(Sabitler) final değişkenlerde söyleyeceğimiz ilk şey, final değişkenler ilk değeri atanmadan kullanılamazlar. Normalde bir değişken tanımlanıp değeri verilmediğinde default değere sahip olurdu. Fakat finaldeğişkenlerde bu şekilde yaparsak hata ile karşılaşırız. Buna bir örnek verirsek: public final int x; 1 System.out.println(x); // hatalı kullanım. İlk değer atanmadan 2 kullanılamaz. Şu şekilde tanımlama doğru olacaktır: public class Insan 1 { 2 public final int x = 5; // final değişken tanımlandı ve ilk değeri 3 verildi. 4 } final ile değişken tanımlamasında yanlış olan bir şey de değişkeni ilk değeri olmadan tanımlıyoruz ve başka bir yerde ona değer veriyoruz. Bu kullanım hatalıdır. Bu şekilde tanımlanmış değişkenlerin ilk değerleri, tanımlandığı ilk anda ya da yapıcılar içerisinde verilmelidir. Fakat metodlar içerisinde final tanımlarsak, başka satırda da ilk değeri verilebilir. Tanımlandığı ilk anda değer vermeye örnek göstermiştir. Şimdi ise yapıcılar içerisinde ilk değer almasına örnek verelim. 1 //FinalDegiskenler.java - 08.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class FinalDegiskenler { private final int x; public final FinalDegiskenler (int deger) // yapıcı metod tanımlandı { x = deger; // alınan parametre, final değişkenine atandı } public void yaz() { System.out.println(x); // final değişken ekrana yazdırıldı } } Yapıcımız içerisinde, x adlı final değişkene ilk değerini atama işlemini yaptık. Daha sonra main metodu içerisinde bir nesne oluşturup yaz() metodunu çağırmamız gerekiyor. final anahtar kelimesi ile tanımlanmış değişkenlerin değeri, programın herhangi bir yerinde değiştirilemez. Buna da bir hatalı kullanım örneği verelim. //Degiskenler.java - 08.04.2014 1 2 public class Degiskenler 3 { 4 private final int sayi; 5 public Degiskenler(int deger) 6 { 7 sayi = deger; 8 } 9 public static void main(String[] 10 args) 11 { 12 Degiskenler d = new 13 Degiskenler(5); 14 sayi = 10; // hatalı 15 } 16 } 17 Bu metoda bir nesne oluşturduk ve 5 değerini, yapıcı ile atadık. sayi değişkenimiz 5 oldu. Daha sonra değişkenimizi 10 yapmaya çalışıyoruz. Bu hatalı bir kullanımdır. Çünkü yapıcı ile sabit değişkenimize bir değer verildi. Onu artık değiştirmeye çalışmak hata verecektir. Final değişkenler, sınıf içerisinde tanımlandığı gibi metod içerisinde de tanımlanabilir ve kullanılabilir. Eğer metod içerisinde tanımlarsak; ilk değer atamasını, metod içerisinde başka satırlarda da yapabiliriz. //Degiskenler2.java - 08.04.2014 1 2 public class Degiskenler2 3 { 4 public void al() 5 { 6 final int x; // metod içerisinde final 7 tanımlama 8 x = 5; 9 } 10 } 11 12 Eğer final değişkenleri, metod içerisinde tanımlarsak, diğerlerinden farklı olarak ilk değer atamasını başka satırda da yapabiliriz, fakat bunu metod içerisinde yapmak zorundayız. Son olarak final değişkenler ile ilgili şundan bahsedelim. final değişkenler aynı zamanda static olabilir. Yani sınıfa ait bir değişken olabilir. Tüm sınıf öğeleri bu değişkeni ortam olarak kullanırlar ve değiştiremezler. Eğer böyle bir değişken istiyorsak, yapmamız gereken tanımlama şu şekilde olacaktır: 1 public static final int x = 6; Istisnalar: ! final anahtar kelimesi ile yapacağımız tanımlamalarda değişken isimlerini büyük yapmak, bu değişkeni diğerlerinden ayırdığı için kodu okumada yarar sağlar. FINAL İLE METODLARIN OVERRIDE EDİLMELERİNİ ENGELLEME Metodlar, final olarak tanımlanabilir. Değişkenlerdeki gibi sabit tanımlama amacıyla kullanılmazlar. Yukarıda da bahsettiğimiz gibi metodları final olarak tanımlarsak, bu metodlar override edilemezler. Buna örnek vererek açıklayalım. //FinalMetod.java - 08.04.2014 1 2 public class FinalMetod 3 { 4 public final void deneme() // final metod 5 { 6 System.out.println("Bu metod override edilemez"); 7 } 8 } 9 10 public class FinalMetod2 extends FinalMetod 11 { 12 public final void deneme() // override edilemez 13 { 14 System.out.println("Bu metod override edilmeye 15 çalışıldı."); 16 } 17 } 18 19 Burada değiştirilmek istenen metod deneme() metodudur. Fakat bu metod final olarak tanımlandığı için değiştirilemez. final metodları, anlaşıldığı üzere alt sınıflardan değiştirilmesini istemediğimiz metodlar için kullanılır. Yani override yapmamızı engeller. FINAL İLE PARAMETRELERİN DEĞERİNİN DEĞİŞMESİNİ ENGELLEME final parametreleri, bir metoda gönderdiğimiz parametrelerin değişmesini istemediğimiz durumlarda kullanırız. Diyelim ki bir metoda parametre gönderiyoruz ve bu parametreyi kendi içinde tekrar eşliyoruz. 1 public void gonder() 2 { 3 int x = 5; 4 5 6 7 8 9 al(x); } public void al (final int y) { y = y + y; } Bu örnekte The final local variable y cannot be assigned. It must be blank and not using x compound assignment hatası ile karşılaşacağız. Çünkü parametre olarak aldığımız y değeri final olarak tanımlanmış yani sabit. Daha sonra al() metodu içerisinde ise bu değerin 2 katını tekrar aynı değere atıyoruz. Bu metod içerisindeki fonksiyon eğer int z = y + y; olsaydı, hata almayacaktık. Çünkü alınan değer başka bir değişkene atandı, yani y'nin değeri değişmedi. FINAL İLE SINIFLARIN KALITIMINI ENGELLEME final anahtar kelimesi sınıflarda kullanılırsa, bir sınıf tanımlaması şu şekilde yapılır. public final class 1 Canli 2 { 3 } Bu şekilde bir sınıf tanımlayabiliriz, fakat dediğimiz gibi bu sınıftan başka bir sınıf türetemeyiz. Bu şekilde bir yanlış kullanıma örnek verelim. 1 public final class Canli 2 { 3 } 4 class Hayvan extends Canli // turetilemez 5 { 6 } Burada Canli sınıfından Hayvan adlı bir sınıf türettik. Fakat Canli sınıfımızı final ile tanımladığımız için bu kullanım şekli yanlıştır. Başka bir örnek verelim. 1 //Sinif.java - 08.04.2014 2 3 final class Sinif 4 { 5 6 7 8 9 10 11 12 13 14 15 16 } class SinifB extends Sinif // final class'tan kalıtım yapılamaz { public static void main(String[] args) { SinifB s = new SinifB(); } } Ekran çıktısı: Exception in thread "main" java.lang.Error: Unresolved compilation 1 problem: 2 3 at SinifB.main(Sinif.java:9) Gördüğümüz gibi final olarak tanımlanmış sınıftan, başka bir sınıf türetemeyiz. Bu kelime kalıtımı önler. Ders 63 - Upcasting ve Downcasting Kavramları Bu konuyu şu şekilde anlatalım. İlk olarak bir kalıtım ilişkisinin diyagramını çizelim. Burada bir kalıtım ilişkisi var. Yani her hayvan bir canlıdır. Aynı zamanda her omurgalı da bir hayvandır. Aynı zamanda da tüm sınıflar Object sınıfından türetilmişlerdir. Biz yukarda kalıtım ilişkimizi modelledik. Tüm sınıflar bir üst sınıfını miras alıyor. Şimdi aşağıda bu hiyerarşimizi kodlayalım. 1 //Canlı.java - 08.04.2014 2 3 class Canlı 4 { 5 public void adSoyle() 6 { 7 System.out.println("Burası Canlı sınıfı"); 8 } 9 } 10 11 class Hayvan extends Canlı 12 { 13 public void adSoyle() 14 { 15 System.out.println("Burası Hayvan 16 sınıfı"); 17 } 18 } 19 20 class Omurgalı extends Hayvan 21 { 22 public void adSoyle() 23 { 24 System.out.println("Burası Omurgalı 25 sınıfı"); 26 } 27 } 28 29 class Omurgasız extends Hayvan 30 { 31 public void adSoyle() 32 { 33 System.out.println("Burası Omurgasız 34 sınıfı"); 35 } 36 } 37 38 class Calistir 39 { 40 public static void main(String[] args) 41 42 43 44 45 46 47 48 49 50 { Canlı c = new Canlı(); c.adSoyle(); Hayvan h = new Hayvan(); h.adSoyle(); Omurgalı o1 = new Omurgalı(); o1.adSoyle(); Omurgasız o2 = new Omurgasız(); o2.adSoyle(); } } Ekran çıktısı: 1 Burası Canlı sınıfı 2 Burası Hayvan sınıfı 3 Burası Omurgalı sınıfı 4 Burası Omurgasız sınıfı Bu örnekte kalıtım ilişkimizin kodunu yazdık ve çıktısını inceledik. Her sınıfa ait bir nesne oluşturduk ve ana sınıftaki adSoyle() metodunu override ettik. Oluşturulan nesnelerin olduğu sınıftaki adSoyle() metodu çalıştı. Biz sınıfımızda her hayvanın bir canlı olduğunu söyledik. Madem her hayvan bir canlıdır, o zaman bizHayvan sınıfından bir nesne oluşturup bu nesneyi Canlı sınıfının referansına bağlayabiliriz. Buna upcasting denir. Bunu aynı örnek üzerinde gösterelim ve sadece Çalıştır sınıfımızı değiştirelim. 1 //Canlı.java - 08.04.2014 2 3 class Canlı 4 { 5 public void adSoyle() 6 { 7 System.out.println("Burası Canlı sınıfı"); 8 } 9 } 10 11 class Hayvan extends Canlı 12 { 13 public void adSoyle() 14 { 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 System.out.println("Burası Hayvan sınıfı"); } } class Omurgalı extends Hayvan { public void adSoyle() { System.out.println("Burası Omurgalı sınıfı"); } } class Omurgasız extends Hayvan { public void adSoyle() { System.out.println("Burası Omurgasız sınıfı"); } } class Calistir { public static void main(String[] args) { Canlı c = new Canlı(); // upcasting(1) c.adSoyle(); Canlı h = new Hayvan(); // upcasting(2) h.adSoyle(); Hayvan o1 = new Omurgalı(); // upcasting(3) o1.adSoyle(); Hayvan o2 = new Omurgasız(); // upcasting(4) o2.adSoyle(); } } Ekran çıktısı: 1 Burası Canlı sınıfı 2 Burası Hayvan sınıfı 3 4 Burası Omurgalı sınıfı Burası Omurgasız sınıfı Çıktımız yine aynı olacaktır. Çünkü biz kalıtıma aksi bir şey yapmadık. Zaten her hayvan bir canlıdır. Her omurgalı da bir hayvandır. 2. upcasting yapmamızda Hayvan sınıfından bir nesne oluşturduk ve bu nesneyi, üst sınıfı olan Canlı sınıfının referansına bağladık. Diğer upcasting satırları da bu şekildedir. Aynı satırları şu şekilde de yazabilirdik: 1 //Canlı.java - 08.04.2014 2 3 class Canlı 4 { 5 public void adSoyle() 6 { 7 System.out.println("Burası Canlı sınıfı"); 8 } 9 } 10 11 class Hayvan extends Canlı 12 { 13 public void adSoyle() 14 { 15 System.out.println("Burası Hayvan 16 sınıfı"); 17 } 18 } 19 20 class Omurgalı extends Hayvan 21 { 22 public void adSoyle() 23 { 24 System.out.println("Burası Omurgalı 25 sınıfı"); 26 } 27 } 28 29 class Omurgasız extends Hayvan 30 { 31 public void adSoyle() 32 { 33 System.out.println("Burası Omurgasız 34 sınıfı"); 35 36 37 38 39 40 41 42 43 44 45 46 47 48 } } class Calistir { public static void main(String[] args) { Canlı c = new Canlı(); c.adSoyle(); Canlı h = (Canlı)new Hayvan(); h.adSoyle(); Hayvan o1 = (Hayvan)new Omurgalı(); o1.adSoyle(); Hayvan o2 = (Hayvan)new Omurgasız(); o2.adSoyle(); } } Yukarıda aslında aynı şeyi yaptık. Sadece referans olarak belirlediğimiz sınıfa doğru cast işlemi yaptık.Upcasting yaparken bunu yapmak zorunlu değildir. Fakat birazdan göreceğimiz Downcasting işleminde buzorunludur. Peki, Downcasting işlemini nasıl yapıyoruz. Tahmin ettiğiniz gibi üst sınıfı, alt sınıfın referansınabağlıyoruz. Bunu yaparken cast işlemi zorunludur. Yani hangi sınıfın referansına bağladığımızı parantez içerisinde göstermemiz gerekir. Aynı örneği bir de Downcasting için yapalım. 1 //Canlı.java - 08.04.2014 2 3 class Canlı 4 { 5 public void adSoyle() 6 { 7 System.out.println("Burası Canlı sınıfı"); 8 } 9 } 10 11 class Hayvan extends Canlı 12 { 13 public void adSoyle() 14 { 15 System.out.println("Burası Hayvan sınıfı"); 16 } 17 } 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 class Omurgalı extends Hayvan { public void adSoyle() { System.out.println("Burası Omurgalı sınıfı"); } } class Omurgasız extends Hayvan { public void adSoyle() { System.out.println("Burası Omurgasız sınıfı"); } } class Calistir { public static void main(String[] args) { Hayvan h1 = new Hayvan(); Canlı c = h1; // upcasting Hayvan h2 = (Hayvan)c; //downcasting (1) h2.adSoyle(); Omurgalı o1 = new Omurgalı(); Hayvan h3 = o1; // upcasting Omurgalı o2 = (Omurgalı)h3; // downcasting(2) o2.adSoyle(); } } Ekran çıktısı: Burası Hayvan sınıfı 1 Burası Omurgalı 2 sınıfı Burada da downcasting örneği verdik. Yani üst sınıf, alt sınıfın tipinde referans alması için zorlanıyor.Downcasting 1 işleminde Hayvan sınıfımızdan türetilmiş olan nesne, bir alt sınıfı olan Omurgalı sınıfının referansına bağlanıyor. Dolayısıyla oluşturulan o2 nesnesinin adSoyle() metodu çalıştırılınca Hayvan sınıfının değil, Omurgalı sınıfının adSoyle() metodu çalıştırılıyor. Dediğimiz gibi downcasting yaparken parantez içerisinde hangi referansa işaret edileceği yazılmak zorundadır. Kalıtımda alt sınıf, üst sınıfın üyelerine erişebiliyorken; üst sınıf, alt sınıfın üyelerine erişemiyordu. Fakatdowncasting ile üst sınıfa ait bir referans ile alt sınıftaki üyelere erişilebilir. Ders 64 - Soyut Sınıflar ve Metodlara Giriş Nesneye yönelik programlamada, sınıfları miras bırakırken bazı metodların içeriğinin farklı olmasını isteyebiliriz veya bir üst sınıfa tanımladığımız ortak metot, sınıfı miras bırakacağımız alt sınıfların bazılarının ihtiyacını karşılamıyor olabilir. Bu gibi durumlarda soyut sınıfları kullanmak bizim için avantaj sağlayacaktır. Soyut sınıflarda amaç, nesne türetirken şablon oluşturmaktır. Soyut sınıfta tanımlanan şablon, bu sınıfı miras alan alt sınıflarda override edilerek yeniden tanımlanır. Örnek olarak üçgen, yamuk ve daire düşünelim. Örnek olarak verdiğimiz nesnelerin ortak özellikleri ve birbirinden farklı oldukları bir takım özellikler vardır. Hepsinin ortak özelliği bir geometrik şekil olmasıdır. Farklarına ise basit olarak alan hesaplarını verebiliriz. Yani şekil isminde bir sınıf tanımlasaydık bu sınıfı miras alacak üçgen, yamuk ve daire sınıfları için alanı hesaplayabilecek ortak bir metod tanımlayamayacaktık. Bu tip örneklerde üst sınıfı ve alt sınıflar için farklı olacak metodu, soyut tanımlarız. Alt sınıflarda ise soyut tanımladığımız bu metodu override ederek yeniden tanımlarız. Soyut sınıf tanımladığımızda içerisinde mutlaka bir soyut metod bulundurması gerekmektedir. Tersini düşündüğümüzde, yani sınıfın içerisinde bir soyut metod tanımladığımızda ise, sınıfı soyut işaretçisiyleişaretlemeliyiz(Sınıfı soyuta çevirmeliyiz). Bir sınıfı veya metodu soyut olarak tanımlamak için erişim belirtecinden sonra abstract anahtar sözcüğünü kullanmalıyız. Soyut metodlar, kendi başına bir anlam ifade etmezler. Istisnalar: ! Bir metod soyut olarak tanımlandıysa, o metodun olduğu sınıf da mutlaka soyut (abstract) olarak tanımlanmalıdır. Istisnalar: ! Soyut sınıftaki soyut metot, alt sınıflarda override edilmezse, derleme anında hata ile karşılaşırız. Ders 65 - Soyut Sınıf ve Kalıtm Arasındaki İlişki Soyut sınıflar anlaşıldığı üzere Kalıtım konusuyla yakından ilişkilidir. Kalıtımda olduğu gibi soyut sınıflarda da bu sınıftan bir sınıf türetiliyor ve bazı gerekli metodlar override ediliyor. Fakat bir fark var. Kalıtım konusunda alt sınıftayken, üst sınıfta bulunan istediğimiz metodu overrideedebiliyorduk. Üst sınıftaki metodumuzun başına override anahtar kelimesini getirerek, istediğimiz bir alt sınıftan bu metotları override edebiliyorduk. Soyut sınıflarda, soyut olarak tanımladığımız metot, alt sınıflardamutlaka override edilmelidir. Kalıtımdaki gibi isteğe bağlı bir durum yoktur. Soyut sınıflardan, soyut alt sınıflar türetilebilir. Bu şekilde türetirsek bu alt soyut sınıf, üst soyut sınıfın soyut metodunu override etmek zorunda kalmaz. Bir başka fark da şudur: Kalıtım yaparken üst sınıfta tanımladığımız metot, o üst sınıf için bir şeyler ifade ediyordu. Yani bu sınıfa ait bir metod oluyordu ve bu üst sınıf bu metodu istediği gibi doldurarak kendisi için kullanabiliyordu. Bir sınıfı soyut olarak tanımlayıp, içerisinde de soyut bir metod oluşturursak; bu metodun o üst sınıf için bir anlamı olmaz. Sadece bu soyut sınıftan türeyen sınıflar, bu metodu kullanarak kendileri için şekillendirirler. Yani bu soyut metot, alt sınıfların işine yarar. Soyut sınıfları kullanabilmek için kalıtım yapmamız gerektiği için kalıtım ve soyut sınıflar konusu iç içedir. Ders 66 - Soyut Sınıf Örneği Bu dersimizi örnek üzerinden anlatalım. //geometrikSekil.java - 08.04.2014 1 2 public abstract class geometrikSekil 3 { 4 private String isim; 5 6 public void isimBelirle(String isim) 7 { 8 this.isim = isim; 9 // geometrik şeklimizin ismini 10 belirledik 11 } 12 13 public String isimGetir() 14 { 15 return this.isim; 16 // şeklimizin ismini döndürecek 17 metod 18 } 19 20 // soyut metodumuzu tanımladık 21 public abstract double alanHesap(); 22 } 23 Yukarıda görüldüğü gibi soyut sınıfımızı, abstract anahtar kelimesiyle işaretleyerek tanımladık. Bu sınıfı miras alacak bütün sınıflar, tanımladığımız soyut metodu override etmek zorundadırlar. Metodumuzunoverride edilmemesi durumunda, aşağıdaki gibi hatayla karşılaşacağız. Şimdi bu sınıfı miras alacak diğer sınıfların tanımına geçelim. ucgen.java //ucgen.java - 08.04.2014 1 2 public class ucgen extends geometrikSekil 3 { 4 private double yukseklik; 5 private double taban; 6 7 public void bilgi(double yukseklik, double taban) 8 { 9 isimBelirle("Üçgen Nesnesi"); 10 this.yukseklik = yukseklik; 11 this.taban = taban; 12 // üçgen nesnemizin bilgilerini belirledik 13 } 14 15 @Override 16 public double alanHesap() 17 { 18 return (taban*yukseklik) / 2; 19 // üçgenimizin alanını hesapladık ve bunu geriye 20 döndürdük 21 } 22 } 23 24 dikdortgen.java 1 //dikdortgen.java - 08.04.2014 2 3 public class dikdortgen extends geometrikSekil 4 { 5 private double uzunKenar; 6 private double kisaKenar; 7 8 public void bilgi(double uzunKenar, double kisaKenar) 9 { 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 isimBelirle("Dikdörtgen Nesnesi"); this.uzunKenar = uzunKenar; this.kisaKenar = kisaKenar; // dikdörtgen nesnemizin bilgilerini belirledik } @Override public double alanHesap() { return uzunKenar * kisaKenar; // dikdörtgenimizin alanını hesapladık ve bunu geriye döndürdük } } daire.java //daire.java - 08.04.2014 1 2 public class daire extends geometrikSekil 3 { 4 private double yaricap; 5 private double pi = Math.PI; 6 7 public void bilgi(double yaricap) 8 { 9 isimBelirle("Daire Nesnesi"); 10 this.yaricap = yaricap; 11 // daire nesnemizin bilgilerini belirledik 12 } 13 14 @Override 15 public double alanHesap() 16 { 17 return pi * Math.sqrt(yaricap); 18 // dairemizin alanını hesapladık ve bunu geriye 19 döndürdük 20 } 21 } 22 23 Yukarıdaki sınıflarda görüldüğü üzere soyut sınıfımızı miras aldık ve soyut sınıfımızda tanımladığımız soyut metodumuzu, bu sınıfların herbirinde override ettik. Daha önce soyut sınıfın tek başına kullanılamayacağınıve soyut sınıfın kendini miras alan diğer sınıflar için şablon olarak kullanılabileceğini söylemiştik. Peki, ana sınıfımızda soyut sınıfımızdan bir nesne oluşturmak istersek ne olur? Cevabını aşağıdaki resim üzerinden anlatalım. Yukarıdaki şekilde de görüldüğü gibi soyut bir sınıfın nesnesini oluşturmak istediğimizde hataylakarşılaşacağız. Derleyici bize "geometrikSekil'in bir örneğini oluşturamazsınız" şeklinde bir uyarı veriyor. Istisnalar: ! Soyut sınıflardan nesne üretilemez, fakat alt sınıflardan bu soyut sınıfa referans verilebilir. Ayrıca soyut sınıflar içerisinde yapıcılar tanımlanabilir. Örneğimizin son kısmıyla devam edelim. 1 //soyutSinifOrnegi.java - 08.04.2014 2 3 public class soyutSinifOrnegi 4 { 5 public static void main(String[] args) 6 { 7 daire daireNesnesi = new daire(); 8 dikdortgen dikdortgenNesnesi = new dikdortgen(); 9 ucgen ucgenNesnesi = new ucgen(); 10 // nesnelerimizi oluşturduk 11 12 daireNesnesi.bilgi(5.0); 13 System.out.print(daireNesnesi.isimGetir() + ": "); 14 System.out.println(daireNesnesi.alanHesap()); 15 // daire için alanı hesapladık 16 17 dikdortgenNesnesi.bilgi(5.0, 3.0); 18 System.out.print(dikdortgenNesnesi.isimGetir() + ": 19 "); 20 System.out.println(dikdortgenNesnesi.alanHesap()); 21 // diktörtgen için alanı hesapladık 22 23 ucgenNesnesi.bilgi(4.0, 3.0); 24 System.out.print(ucgenNesnesi.isimGetir() + ": "); 25 System.out.println(ucgenNesnesi.alanHesap()); 26 // üçgen için alan hesapladık 27 } 28 } 29 Ekran çıktısı: Daire Nesnesi: 1 7.024814731040727 2 Dikdörtgen Nesnesi: 15.0 3 Üçgen Nesnesi: 6.0 Yukarıdaki örneğimizde görüldüğü gibi geometrik şekil nesnelerimizi tanımladık ve alan hesaplarını yaptık.alanHesap() metotlarını sınıflar içerisinde override ettiğimiz için sonuç bütün sınıflar için özel hale geldi. Şimdi soyut sınıflara bir örnek daha verelim. Bu örnekte de soyut sınıflarda normal bir metot olabileceğini, soyut sınıftan nesne türetmeden doğrudan soyut sınıf elemanlarına erişmeyi, static bir metot tanımlayarak, soyut sınıftaki metoda erişmeyi anlatalım. 1 //soyutSinif.java - 09.04.2014 2 3 abstract class SoyutSinif 4 { 5 abstract public void goster(); // soyut metod 6 public SoyutSinif() // soyut sınıf yapıcısı 7 { 8 System.out.println("Burası Soyut Sınıf Yapıcısı"); 9 } 10 public void metod() // normal metod 11 { 12 System.out.println("Soyut sınıfa ait normal metod"); 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 } public static void metod2() // static void { System.out.println("Soyut sınıfa ait static normal metod"); } } class AltSinif1 extends SoyutSinif { public void goster() // soyut metod override edildi { System.out.println("Burası Alt Sınıf 1"); } } class AltSinif2 extends SoyutSinif { public void goster() // soyut metod override edildi { System.out.println("Burası Alt Sınıf 2"); } } public class Baslat { public static void main(String[] args) { AltSinif1 a1 = new AltSinif1(); AltSinif2 a2 = new AltSinif2(); a1.goster(); a2.goster(); SoyutSinif s1[] = new SoyutSinif[1]; s1[0] = a1; s1[0].metod(); SoyutSinif.metod2(); } } Ekran çıktısı: 1 Burası Soyut Sınıf yapıcısı 2 Burası Soyut Sınıf yapıcısı 3 Burası Alt Sınıf 1 4 Burası Alt Sınıf 2 5 Soyut sınıfa ait normal metod 6 Soyut sınıfa ait static normal metod Bu örnekte yaptıklarımızı anlatalım. 1. Soyut sınıfımızda bir normal metod, bir static metot ve yapıcı tanımladık. Static olan metodu, sınıf adı ile doğrudan erişebilmek amacıyla yaptık. 2. Baslat adlı sınıfın main metodunda a1 ve a2 nesneleri oluşturduk. Bu nesneler üzerinden goster()metotlarını çalıştırdık. Bu metotlar, soyut olan metodu override etmektedirler. 3. Bu nesneleri oluşturduğumuz anda otomatik olarak üst sınıfın da yapıcısı çalıştığı için iki kere soyut sınıfımızın yapıcısı çalıştı. 4. Soyut sınıftan nesne oluşturmayı dizi şeklinde yaptık ve a1 nesnesini referans olarak verdik. Bu şekilde soyut sınıfımızın normal metoduna ulaşabildik. 5. Son olarak sadece sınıf adını kullanarak static olan metoda eriştik. Istisnalar: ! Farklı veriler alıp aynı işlemi yapacaksak, bunları soyut sınıflar içerisinde yapmamız gerekir. Soyut sınıfların da kullanılma amacı budur. İlk baştaki örneğimizde farklı parametreler aldık, fakat aynı işi yaptık. Hepsinde alan bulma işlemi yaptık. Ders 67 - Arayüz Kavramına Giriş Arayüzler yapı olarak daha önceki dersimizde gördüğümüz soyut sınıflara benzerler. Soyut sınıflara benzemelerine rağmen yapı olarak bazı yönleriyle bu soyut sınıflardan ayrılır. Soyut sınıflarda, gövdesiz soyut metodları ve tanımlayabileceğimiz diğer metodları kullanabiliyorduk. Arayüzlerde ise bütün metodlar gövdesizolarak tanımlanır. Arayüzler, sınıfların bir işi nasıl yapacağını değil, işi yaparken hangi adımları veya ne yapması gerektiğini tanımlar. Arayüzler, temelde çoklu kalıtım olayını basite indirgemek için oluşturulmuştur. Arayüzler, temelde çoklu kalıtım olayını basite indirgemek için oluşturulmuştur. Arayüzlerin kod yapısı sınıf tanımlamaya benzer. Sınıfları aşağıdaki gibi tanımlıyorduk. erisimBelirteci class 1 sinifAdi 2 { 3 // metodlar ve 4 değişkenler } Bir arayüzü ise aşağıdaki gibi tanımlayabiliriz. erisimBelirteci interface 1 arayuzAdi 2 { 3 // değişkenler ve metod 4 görevleri } Arayüzlerin çoklu kalıtım olayını basite indirgemek için oluşturulduklarını söylemiştik. Arayüzlerin, sınıfları birleştirici özelliği vardır. Sınıflar, kullanmak istediği arayüzü tanımından sonra impelements anahtar sözcüğü ile kendi bünyelerine dahil edebilirler. Arayüzlerde değişken erişim belirteçleri de sınıflardakinden farklıdır. Arayüz içerisinde anlık değişkenler bulunmazlar. Arayüz içerisinde tanımladığımız değişkenlerin erişim belirteçleri public static ve final tipindedir ve ilk değer ataması zorunludur. Yani arayüzü kullanacak diğer sınıflar, değişkenleri değiştiremezler. Arayüzler içerisinde tanımladığımız değişkenler, daha çok diğer sınıflarda sabit olarak kullanacağımız değişkenlerdir. Arayüzlerin yapı olarak soyut sınıflara benzediğini söylemiştik. Sınıflar sadece bir adet soyut sınıfı miras alarak kullanabiliyorlardı. Arayüzlerde ise durum bu açıdan farklıdır. Sınıflar, birden fazla arayüzü bünyesine katabilir. Bu da çoklu kalıtımda bizim işimizi kolaylaştırır. Istisnalar: ! Arayüzler, soyut sınıflarda olduğu gibi hem gövdeli hem gövdesiz metodlara sahip değildir. Tamamengövdesiz metodlar bulunur. Yani bu metodlar başlı başına bir iş yapmazlar. Bu metodların, implementedilen sınıflarda override edilmeleri gerekir. Ders 68 - Arayüz Örneği Şimdi bir örnek yaparak arayüzleri anlamaya çalışalım. //calisan.java - 09.04.2014 1 2 public interface calisan // arayüz tanımlandı 3 { 4 double oran = 0.7; 5 double ucret(); 6 void calisanBolumu(); 7 void ucretBelirle(double ucretSabiti); 8 // bu arayüzü kullanacak olan sınıflarda tanımlayacağımız metodları 9 yazdık. 10 } 11 12 Yukarıda, diğer sınıflarımızda kullanacağımız arayüzümüzü tanımladık. Bu arayüzün metodlarını, arayüzü kullanacağımız sınıflarda override ederek yeniden tanımlamak zorundayız. Şimdi sınıfımızı yazalım ve calisan arayüzlerden implement edelim. isci.java 1 //isci.java - 09.04.2014 2 3 public class isci implements calisan 4 { 5 double ucretSabiti; 6 7 // çalışan ücretini döndüren metod 8 @Override 9 public double ucret() 10 { 11 return ucretSabiti * oran; 12 } 13 14 // çalışan bölümünü ekrana yazdıralım metod 15 @Override 16 public void calisanBolumu() 17 { 18 System.out.println("Ucretli Çalışan"); 19 } 20 21 22 23 24 25 26 27 28 29 // çalışan ücretini belirtmek için kullanılacak metod @Override public void ucretBelirle(double ucretSabiti) { this.ucretSabiti = ucretSabiti; } } mudur.java //mudur.java - 09.04.2014 1 2 public class mudur implements calisan 3 { 4 double ucretSabiti; 5 6 @Override 7 public double ucret() 8 { 9 return ucretSabiti; 10 } 11 12 @Override 13 public void calisanBolumu() 14 { 15 System.out.println("Yönetici"); 16 } 17 18 @Override 19 public void ucretBelirle(double 20 ucretSabiti) 21 { 22 this.ucretSabiti = ucretSabiti; 23 } 24 } 25 26 satisElemani.java 1 //satisElemani.java - 09.04.2014 2 3 public class satisElemani implements calisan 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 { double ucretSabiti; double komisyon; final double komisyonOran = 0.3; @Override public double ucret() { return ((ucretSabiti * oran) + komisyon); } @Override public void calisanBolumu() { System.out.println("Satış Elemanı"); } @Override public void ucretBelirle(double ucretSabiti) { this.ucretSabiti = ucretSabiti; } // satış elemanının komisyonunu belirleyen metod public void satisKomisyonuBelirle(int adet) { komisyon = adet * komisyonOran; } } Arayüzlerimizi kullanan sınıflarımızı yukarıda tanımladık. Görüldüğü gibi arayüz içerisinde tanımladığımız metodlar, sınıflar içerisinde farklı şekillerde kullanılmışlardır. Şimdi ana sınıfımızı da yazarak örneğimizi tamamlayalım. 1 //arayuzOrnegi.java - 09.04.2014 2 3 public class arayuzOrnegi 4 { 5 public static void main(String[] args) 6 { 7 // işçi ile ilgili bilgiler yazdırılıyor. 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 isci ucretliCalisan = new isci(); ucretliCalisan.calisanBolumu(); ucretliCalisan.ucretBelirle(865.70); System.out.println("Maaşı: " + ucretliCalisan.ucret()); // müdür ile ilgili bilgiler yazdırılıyor mudur yonetici = new mudur(); yonetici.calisanBolumu(); yonetici.ucretBelirle(5519.71); System.out.println("Maaşı: " + yonetici.ucret()); // satış elemanı ile ilgili bilgiler yazdırılıyor satisElemani pazarlama = new satisElemani(); pazarlama.calisanBolumu(); pazarlama.ucretBelirle(978.75); pazarlama.satisKomisyonuBelirle(250); System.out.println("Komisyon: " + pazarlama.komisyon); System.out.println("Maaşı: " + pazarlama.ucret()); } } Ekran çıktısı: Ucretli Çalışan Maaşı: 605.99 1 Yönetici 2 Maaşı: 3 5519.71 4 Satış Elemanı 5 Komisyon: 6 75.0 7 Maaşı: 760.125 Örneğimizde tüm çalışanlar için kullanabileceğimiz metodların olduğu bir arayüz oluşturduk. Daha sonrasında ise bu arayüzü kullanacağımız sınıflar oluşturduk. Arayüzümüzde oluşturduğumuz metodları, bu sınıflarda override ederek tekrar tanımladık. Ana sınıfımızda ise bu metodlara değerlerimizi göndererekçalışan maaşlarını ve diğer bilgilerini ekrana yazdırdık. Istisnalar: ! Arayüzler, soyut sınıflara benzese de aralarında önemli farklar vardır. Eğer her metodun override (iptal) edilmesini istiyorsak, bu metodları bir arayüz içerisinde tanımlarız. Ayrıca arayüzlerde, soyut sınıflarda olduğu gibi bir ilişki kavramı yoktur. Yani arayüz ve bunu kullanan sınıflar arasında kalıtım açısından bir bağlantı olmayabilir. Ders 69 - Arayüzlerde Genişletilme Özelliği Daha önceden tanımladığımız bir arayüzü genişletmemiz mümkündür. Bu bir arayüzün başka bir arayüzü kalıtım yoluyla devralmasıyla mümkün olur. Bir arayüzün diğer bir arayüzü miras alması, sınıftaki gibidir. Yani bir arayüz diğer bir arayüzü extends anahtar sözcüğü ile miras alabilir. Örnek olarak daha önceki konuda işlediğimiz satış elemanı sınıfını düşünelim. Ücretli çalışanlarımız, komisyon yöntemiyle çalışmadığı için arayüzümüzde komisyon ile ilgili herhangi bir metod tanımlamamıştık. Bu durumda eğer bu arayüzümüze komisyon ile ilgili bir metot tanımlamak istersek, başka bir arayüz tanımlayarak, bu işlemi gerçekleştirebiliriz. Şimdi aşağıdaki örneği inceleyelim: 1 //calisan.java - 09.04.2014 2 3 public interface calisan // arayüz tanımlandı 4 { 5 double oran = 0.7; 6 double ucret(); 7 void calisanBolumu(); 8 void ucretBelirle(double ucretSabiti); 9 // bu arayüzü kullanacak olan sınıflarda tanımlayacağımız metodları 10 yazdık. 11 } 12 13 public interface calisanKomisyon extends calisan 14 { 15 // bu arayüzü, calışan arayüzünden miras aldık 16 double komisyonOran = 0.3; 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public void satisKomisyonuBelirle(int adet); // komisyon belirleyecek metodumuz } public class satisElemani implements calisanKomisyon { // bu sınıfı, calisanKomisyon arayüzünden implement ettik double ucretSabiti; double komisyon; @Override public double ucret() { return ((ucretSabiti * oran) + komisyon); } @Override public void calisanBolumu() { System.out.println("Satış Elemanı"); } @Override public void ucretBelirle(double ucretSabiti) { this.ucretSabiti = ucretSabiti; } // satış elemanının komisyonunu belirleyen metod @Override public void satisKomisyonuBelirle(int adet) { komisyon = adet * komisyonOran; } } Örnekte de görüldüğü gibi komisyonumuzu belirlemek için kullanacağımız metodun gövdesini ve komisyonumuzu belirlemek için kullandığımız oranımızı, ilk arayüzümüzü kalıtım yoluyla miras alan ikinci arayüzümüzde yazdık. satisElemani sınıfımız da bu kez yeni oluşturduğumuz arayüzü kullandı. Sınıfımız içerisinde ilk arayüzümüzün de metodlarının override edilerek kullanıldığında dikkat edelim. Arayüzü kullandığımız sınıfta, arayüzün kalıtım zincirindeki tüm metodları override ederek kullanmak zorundayız. Yani bir sınıf, bir arayüzden implement ediliyorsa ve bu arayüz de başka bir arayüzden miras alınmışsa, sınıfımız bu iki arayüzdeki metodları da override etmelidir. Son bir örnek vererek konumuzu kapatalım. 1 //Canli.java - 09.04.2014 2 3 interface Canli 4 { 5 public void nefesAl(); 6 } 7 8 interface Hayvan extends Canli 9 { 10 public void avlan(); 11 } 12 13 interface Surungen extends Hayvan 14 { 15 public void surun(); 16 } 17 // yukarıda 3 adet arayüz tanımlandı 18 19 // tavşan sınıfı 20 class Tavsan implements Hayvan 21 { 22 public void nefesAl() 23 { 24 System.out.println("Nefes 25 alıyor"); 26 } 27 public void avlan() 28 { 29 System.out.println("Avlanıyor"); 30 } 31 } 32 33 // timsah sınıfı 34 class Timsah implements Surungen 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 { public void avlan() { System.out.println("Avlanıyor"); } public void surun() { System.out.println("Sürünüyor"); } public void nefesAl() { System.out.println("Nefes Alıyor"); } } Bu örneğimizde 3 adet arayüz tanımladık. Bu arayüzlerden Hayvan arayüzünden Tavsan sınıfınıimplement ettik. Surungen arayüzünden de Timsah sınıfını implement ettik. Tavsan sınıfımız, Hayvan veCanli arayüz lerindeki metodları override etmek zorunda kaldı. Çünkü Hayvan arayüzü de Canli arayüzünden türetilmiştir(miras). Timsah sınıfımız ise, hem Hayvan hem Canli hem de Surungen arayüzlerindeki metodları override etmek zorunda kaldı. Bunun sebebi de Surungen arayüzünün Hayvan arayüzünden, Hayvan arayüzünün ise Canliarayüzünden miras alınmasıdır. Istisnalar: ! Bir arayüz içerisinde aynı isimde 2 metod varsa, bu metodların aldığı parametrelerin farklı olması gerekir.Dönüş tiplerinin farklı olması bir anlam ifade etmez, hata oluşur. Bu, metodlardaki overload işlemine benzer. Ders 70 - Arayüz İçerisinde Başka Bir Arayüz Kulanma Bir arayüz, başka bir arayüz içerisinde bulunabilir. Yukarıda anlattığımız gibi bu dahili arayüzler de publicolarak tanımlanmalıdır. Örnek vererek açıklayalım ve kullanımını görelim. 1 //Calistir.java - 09.04.2014 2 3 interface Arayuz1 4 { 5 interface Arayuz2 // arayüz içinde arayüz 6 { 7 public void metod2(); 8 } 9 public void metod1(); 10 } 11 12 interface Arayuz3 13 { 14 public void metod3(); 15 } 16 17 class Sinif1 implements Arayuz1 18 { 19 public void metod1() // Arayuz1'deki metod1 override 20 edildi 21 { 22 System.out.println("Arayüz1'deki metod1 override 23 edildi"); 24 } 25 } 26 27 class Sinif2 implements Arayuz1.Arayuz2 28 { 29 public void metod2() // Arayuz2'deki metod2 override 30 edildi 31 { 32 System.out.println("Arayüz2'deki metod2 override 33 edildi"); 34 } 35 } 36 37 class Sinif3 implements Arayuz3 38 { 39 public void metod3() // Arayuz3'deki metod3 override 40 edildi 41 { 42 43 44 45 46 47 48 49 50 51 52 53 54 System.out.println("Arayüz3'deki metod3 override edildi"); } } public class Calistir { public static void main(String[] args) { Sinif1 s1 = new Sinif1(); s1.metod1(); Sinif2 s2 = new Sinif2(); s2.metod2(); Sinif3 s3 = new Sinif3(); s3.metod3(); } } Ekran çıktısı: Arayüz1'deki metod1 override edildi 1 Arayüz2'deki metod2 override 2 edildi 3 Arayüz3'deki metod3 override edildi Örneğimizde Arayuz1 içerisinde Arayuz2 adında başka bir arayüz tanımladık. Bu Arayuz2 içerisine demetod2 adında bir metot tanımladık. Arayuz1 içerisinde de metod1 adında bir metod bulunmaktadır. Bu arayüzlere erişim belirleyici tanımlamadık, çünkü varsayılan olarak public tanımlanmıştır. Arayuz3 içerisine de metod3 adında bir metot tanımladık. Daha sonra main metodunda bu arayüzleri kullanan sınıfları çağırdık. Bu 3 sınıfta da (Sinif1, Sinif2, Sinif3) implement edildikleri arayüzlerde bulunan metodları override ettik. Ders 71 - Dahili Sınıflara Giriş Java dilinde diğer dillerdeki çoklu kalıtım yoktur. Java çoklu kalıtımı arayüz (interface) ve dahili sınıflar(inner classes) ile sağlar. Dahili sınıfları, sınıf içerisinde tanımlanmış sınıflar olarak belirtebiliriz. Dahili sınıflar bir bütünü oluşturan parçaları bütün olarak tanımlamamıza imkan sunar. Dahili sınıflar, Java'ya 1.1 sürümüyle beraber dahil olmuştur. Dahili sınıfları 3 ana grupta inceleyebiliriz. Bunlar: Dahili Üye Sınıflar (static üye sınıflar, static olmayan üye sınıflar) Yerel Sınıflar İsimsiz Sınıflar Ders 72 - Dahili Üye Sınıflar Dahili üye sınıflar, sınıf içerisinde tanımlanmış sınıflardır. Dahili üye sınıflar sayesinde parçalar bir araya gelerek bütünü oluşturabilirler. Örnek olarak bir bilgisayarı ele alalım. Bilgisayar parçalardan oluşmaktadır. Her parçanın bir sınıf olarak tanımlandığı bir sınıf oluşturalım. 1 //bilgisayar.java - 09.04.2014 2 3 public class bilgisayar 4 { 5 public class anakart 6 { 7 // 1. dahili üye sınıf 8 // kodlar 9 } 10 11 public class islemci 12 { 13 // 2. dahili üye sınıf 14 // kodlar 15 } 16 17 public class RAM_Bellek 18 { 19 // 3. dahili üye sınıf 20 // kodlar 21 } 22 } 23 24 25 26 27 28 29 public static void main(String args[]) { bilgisayar.RAM_Bellek = new bilgisayar().new RAM_Bellek(); } Örnekte görüldüğü gibi bilgisayar parçaları, bilgisayar sınıfı altında tanımlanarak bilgisayar sınıfını oluşturdu. Burada bilgisayar parçaları, dahili üye sınıfları oluşturmaktadır. Örnekte dikkat etmemiz gereken bir diğer nokta ise, RAM_Bellek sınıfının nesnesidir. Bu sınıfın direk olarak nesnesini oluşturamayız. Dahili sınıfın nesnesini oluşturabilmek için örnekte de olduğu gibi üst sınıf üzerinden nesnemizi oluşturabiliriz. Basit bir başka örnek verelim. //islemYap.java - 09.04.2014 1 2 public class islemYap 3 { 4 public class DahiliUyeSinif 5 { 6 public void metod1() 7 { 8 System.out.println("Dahili üye sınıfın metodu"); 9 } 10 public void metod2(int a, int b) 11 { 12 System.out.println(a * b); 13 } 14 } 15 public static void main(String args[]) 16 { 17 islemYap.DahiliUyeSinif n1 = new islemYap().new 18 DahiliUyeSinif(); 19 n1.metod1(); 20 n1.metod2(4, 8); 21 } 22 } 23 24 Ekran çıktısı: Dahili üye sınıfın 1 metodu 2 32 Örneğimizde dahili üye sınıf oluşturduk ve içerisinde iki metot tanımladık. Daha sonra main metodu içerisinde de bu dahili sınıftan bir nesne oluşturarak, bu nesne üzerinden metotları çağırdık. Ders 73 - Dahili Üye Sınıflar ve Erişim Belirteçleri Dahili üye sınıfları normal sınıflar gibi erişim belirteçleriyle nitelendirebiliriz. Böylece dahili sınıfımızı diğer dahili sınıflarımıza karşı kısıtlamış oluruz. Fakat dikkat edilmesi gereken bir diğer önemli nokta ise; üst sınıf ve dahili sınıf ilişkisidir. Erişim belirteci ne olursa olsun üst sınıf metotları, dahili sınıfın elemanlarına ve metotlarınaerişebilirler. Daha önceki dersimizdeki örneği ele alırsak, örneğimizde bilgisayar sınıfı oluşturmuştuk ve içerisinde birimleri dahili sınıf şeklinde oluşturmuştuk. Örneğimizde erişim belirteçlerimiz public'ti. Herhangi bir sınıf private tanımlansaydı, bu sınıfa erişim sadece üst sınıfın metotları sayesinde olur. Diğer dahili sınıfların metotları için dahili sınıfın içeriği kısıtlanmış olur. 1 //dahiliSinifOrnegi.java - 09.04.2014 2 3 import java.util.ArrayList; 4 5 public class dahiliSinifOrnegi 6 { 7 //1. dahili sınıf asal sayı hesaplama için kullanılır 8 public class asalSayi 9 { 10 public boolean asalSayi(int asalSayi) 11 { 12 int bolen = 0; 13 boolean kontrol; 14 15 for(int i = 2 ; i < asalSayi ; i++) 16 { 17 if(asalSayi % i == 0) 18 bolen++; 19 } 20 21 if(bolen == 0) 22 kontrol = true; 23 else 24 kontrol = false; 25 26 return kontrol; 27 } 28 } 29 30 //2. dahili sınıf mükemmel sayı hesaplama için kullanılır. 31 protected class mukemmelSayi 32 { 33 // kendisi hariç bölenleri toplamı kendisine eşit olan sayı mükemmel 34 sayıdır 35 protected boolean mukemmelSayi(int mukemmelSayi) 36 { 37 int bolenToplam = 0; 38 boolean kontrol; 39 40 for(int i = 1 ; i < mukemmelSayi ; i++) 41 { 42 if(mukemmelSayi % i == 0) 43 bolenToplam += i; 44 } 45 46 if(bolenToplam == mukemmelSayi) 47 kontrol = true; 48 else 49 kontrol = false; 50 51 return kontrol; 52 } 53 } 54 55 //3. dahili sınıf fibonacci elemanlarını bulmak için kullanılır 56 private class fibonacciSerisi 57 { 58 // fibonacci dizisi, her sayının kendinden öncekiyle toplanması 59 // sonucu oluşan sayı dizisidir. ilk 2 elemanı 1'dir. 60 private ArrayList fibonacciSerisi(int elemanSayisi) 61 { 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 ArrayList<Integer> fibonacci = new ArrayList<Integer>(); fibonacci.add(0, 1); fibonacci.add(1, 1); // ilk iki indise 1'i ekledik for(int i = 0 ; i < elemanSayisi-2 ; i++) { fibonacci.add(i+2, fibonacci.get(i) + fibonacci.get(i+1)); // bir sonraki indise ardışık indise sahip dizilerin elemanları toplanarak ekleniyor } return fibonacci; } } public static void main(String[] args) { // dahili sınıflarımız için birer nesne oluşturduk dahiliSinifOrnegi.asalSayi asal = new dahiliSinifOrnegi().new asalSayi(); dahiliSinifOrnegi.mukemmelSayi mukemmel = new dahiliSinifOrnegi().new mukemmelSayi(); dahiliSinifOrnegi.fibonacciSerisi fibonacci = new dahiliSinifOrnegi().new fibonacciSerisi(); System.out.println(asal.asalSayi(5)); System.out.println(asal.asalSayi(413)); System.out.println(mukemmel.mukemmelSayi(6)); System.out.println(mukemmel.mukemmelSayi(12)); System.out.println(fibonacci.fibonacciSerisi(7)); System.out.println(fibonacci.fibonacciSerisi(11)); } } Ekran çıktısı: true 1 false 2 true 3 false 4 [1, 1, 2, 3, 5, 8, 13] 5 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 6 89] Yukarıdaki örneğimizde üç adet dahili sınıf bulunmaktadır. Bunlardan ilkinin erişim belirteci public, ikincisinin protected ve üçüncüsünün ise private'dir. main metodu ise ana sınıfımızın bir üyesidir. Örneğimizde ilk olarak verilen sayının asal sayı olup olmadığını kontrol eden asalSayi sınıfını ve bu sınıfın yapılandırıcısını yazdık. İkinci olarak yine verilen sayının, bu sefer mükemmel sayı olup olmadığını kontrol eden sınıfı ve yapılandırıcısını yazdık. Üçüncü olarak ise; istenilen sayıda elemanı olan fibonacci serisiniüretecek sınıfı ve bu sınıfın yapılandırıcısını yazdık. Bundan sonraki kısımda ana sınıfımızın bir üyesi olanmain() metodu içerisinde bu dahili sınıfların nesnelerini oluşturduk. Burada private erişim belirteçlifibonacciSerisi sınıfını tanımlarken, hata almadığımıza dikkat edelim. main metodumuz başka bir sınıfın üyesi olsaydı bu tanımlamayı yaparken hata alacaktık. Daha sonrasında ise metotlarımıza değer vererek, dönen sonuçları ekrana yazdırdık. Ana sınıfın, dahili üye sınıfın tüm alanlarına erişebileceğinden bahsettik. Aynı şekilde dahili üye sınıf,kendisini çevreleyen sınıfın tüm alanlarına erişebilir. Istisnalar: ! Eğer dahili üye sınıfımızı static olarak tanımlarsak, bu dahili sınıfın elemanlarına erişmek içinanasınıf.dahilisınıf ile değil de doğrudan o sınıfın adı ile nesne oluştururuz. Yukarıda anlattığımız nota bir örnek verelim. 1 //islemYap.java - 09.04.2014 2 3 public class islemYap 4 { 5 // normal dahili üye sınıf ve normal sınıf üyeleri 6 public class DahiliUyeSinif 7 { 8 private int x; 9 private int y; 10 public DahiliUyeSinif(int sayi1, int sayi2) 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 { x = sayi1; y = sayi2; } public void carp() { System.out.println("Çarpma sonucu: " + (x * y)); } } // static dahili üye sınıf ve static üyeler public static class DahiliUyeSinif2 { public static void topla(int sayi1, int sayi2) { System.out.println("Toplama sonucu: " + (sayi1 + sayi2)); } } // islemYap sınıfına ait main metodu public static void main(String[] args) { islemYap.DahiliUyeSinif a = new islemYap().new DahiliUyeSinif(5, 8); a.carp(); DahiliUyeSinif2.topla(5, 2); // nesnesiz erişme } } Ekran çıktısı: Çarpma sonucu: 1 40 2 Toplama sonucu: 7 1. Örneğimizde 2 dahili sınıf oluşturduk. İlk dahili sınıfımızda bir yapıcı bulunuyor ve aldığı parametreleri x ve y değişkenlerine atıyor. Buradan anlıyoruz ki dahili sınıflarda yapıcı olabilir. Fakat bu dahili sınıflardan bir nesne oluşturulduğu zaman, yapıcısı otomatik olarak çağırılmaz. 2. main metodunda bu sınıfın carp() metodunu çağırmak için anasınıf.dahilisınıf yapısı ile nesne oluşturarak eriştik. 3. Diğer dahili sınıfımızı ise static tanımladık ve içerisindeki topla() metodunu da static tanımladık. Bu metot ise, aldığı değerleri topluyor ve ekrana gösteriyor. Bu metoda main içerisinden erişmek için ise herhangi bir nesne oluşturmamıza gerek kalmadı. Çünkü hem sınıfımızın static hem de içerisindeki metodumuz static'tir. Şimdi de static olan ve olmayan dahili sınıflar tanımlayalım ve bu sınıfların içerisinde hangi tipte elemanlar olabilir, ona bakalım. 1 //islemYap2.java - 09.04.2014 2 3 public class islemYap2 4 { 5 class DahiliUyeSinif 6 { 7 public int x = 5; 8 public static final int y = 5; 9 public static String ad = "Okan"; // 10 tanımlanamaz 11 public static void metod1() // 12 tanımlanamaz 13 { 14 // metod gövdesi 15 } 16 } 17 static class DahiliUyeSinif2 18 { 19 public int a = 11; 20 public static final int b = 23; 21 public static String ad = "Onur"; 22 public static void metod2() 23 { 24 // metod gövdesi 25 } 26 public void metod3() 27 { 28 // metod gövdesi 29 } 30 31 } } Örneğimizde static olan ve olmayan 2 dahili sınıf tanımladık. Static olmayan sınıfımızın içerisinde static bir değişken ve metot tanımlayamadık. Fakat hem static hem de final olan değişkenleri kullanabildik. Bunlar da bildiğiniz üzere sabitler'dir. Istisnalar: ! Static dahili sınıflar içerisinde ise static olan ve olmayan her türlü metot ve değişkenler tanımlanabilir. Ayrıca static olan sınıflar, static metotlar gibi içinde bulunduğu sınıfın static olmayan elemanlarınaerişemez. Fakat static olan alanlara erişebilir. Istisnalar: ! Static olmayan üye sınıflar ise, içinde bulunduğu sınıfın static olan ve olmayan alanlarına erişebilir. Bunlarıstatic metodlar gibi düşünebiliriz. Bu başlık altında anlatacağımız son özellik şudur: Bir sınıf içerisinde dahili sınıf tanımlayabiliyorduk. Bu dahili sınıf içerisinde de yine bir dahili sınıf tanımlayabiliriz. Örnek vererek açıklayalım. 1 //AnaSinif.java - 09.04.2014 2 3 import AnaSinif.DahiliUyeSinif1.DahiliUyeSinif2; 4 5 public class AnaSinif 6 { 7 static class DahiliUyeSinif1 8 { 9 static class DahiliUyeSinif2 10 { 11 static void yazdir() 12 { 13 System.out.println("En içteki dahili sınıfın 14 metodu"); 15 } 16 } 17 18 19 20 21 22 23 } public static void main(String[] args) { DahiliUyeSinif2.yazdir(); } } Ekran çıktısı: En içteki dahili sınıfın 1 metodu Yukarıdaki örnekte iç içe dahili sınıflar tanımladık. main metodumuzun içerisinde de doğrudan sınıf adınıkullanarak metodumuzu çağırdık. Çünkü örneğimizde dahili sınıfları static olarak tanımladık. Ders 74 - Yerel Sınıflar Yerel sınıflar, metot içerisinde tanımlanan sınıflardır. Dahili üye sınıfların, kendilerini çevreleyen sınıfları olduğunu anlatmıştık. Yerel sınıfların ise kendilerini çevreleyen metotlar vardır. Yerel sınıfların en önemli özelliği, sadece bu metot içerisinden erişilebilir olmasıdır. Yani metot dışarısından yerel sınıflara erişip bu sınıfları kullanamayız. Yerel sınıflar metot dışarısında tanımlanan arayüzlere erişebilirler. Yerel sınıflar, içeirisinde bulundukları metotların sadece final olarak işaretlenmiş değişkenlerine ulaşabilirler. Yerel sınıfların bir diğer özelliği de erişim belirtecine sahip olamazlar. Yani bir yerel sınıfı public, protected veya privatetanımlayamayız. Yerel sınıfları sadece friendly erişim belirteciyle işaretleyebiliriz. Yerel sınıfları daha iyi anlayabilmek için bir örnek yapalım. 1 //yerelSinifOrnegi.java - 09.04.2014 2 3 interface fonksiyonlar // interface tanımlandı 4 { 5 public double faktoriyelAl(double sayi); 6 } 7 public class yerelSinifOrnegi 8 { 9 public double faktoriyel(double sayi) 10 { 11 // yerel sınıfı çevreleyen metod 12 double sonuc; 13 class faktoriyelAlma implements fonksiyonlar 14 { 15 // yerel sınıf 16 private double sonuc2 = 1; 17 @Override 18 public double faktoriyelAl(double sayi2) 19 { 20 for(int i = 1 ; i <= sayi2 ; i++) 21 { 22 sonuc2 *= i; 23 } 24 return sonuc2; 25 } 26 } // yerel sınıfın bir nesnesini oluşturduk faktoriyelAlma f = new faktoriyelAlma(); sonuc = f.faktoriyelAl(sayi); return sonuc; 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 } public void hesaplama() { // faktoriyelAlma f = new faktoriyelAlma(); yaparsak // metodumuz, sınıfı tanımadığından hata ile karşılacaksınız } public static void main(String args[]) { yerelSinifOrnegi y = new yerelSinifOrnegi(); System.out.println("9'un faktoriyeli: " + y.faktoriyel(9)); } } Ekran çıktısı: 9'un faktoriyeli: 1 362880.0 Örneğimizde sınıfımız içerisinde bir metod oluşturduk ve bu metodumuzun içerisinde bir yerel sınıfoluşturduk. İşlemlerimizi yerel sınıf içerisinde yaptık. Dönen sonuca dikkat ettiğimizde, main metoduna gönderdiğimiz sonuc değişkeni ile asıl sonuc değişkeni farklıdır. Bunun sebebi main metodu içerisinden direk olarak yerel sınıf metotlarına veya değişkenlerine ulaşamadığımızdandır. Örnekte görüldüğü gibi metodumuz dışarısında boş bir metot tanımladık ve bu metottan yerel sınıfımıza erişmeye çalıştık. Böyle bir durumda metodumuz yerel sınıfı görmediğinden hata ile karşılaşacağız. Son olarak tanımladığımız ana metottan dönen sonucu ekrana yazdırdık ve örneği sonlandırdık. ! Istisnalar: Yerel sınıflar da dahili sınıflar gibi yapıcıya sahip olabilirler. Ders 75 - İsimsiz Sınıflar İsimsiz sınıflar, isim kullanılmadan tanımlanabilen sınıflardır. İsimsiz sınıflar, başka sınıflardan türetilemez ve bir arayüzü implement edemezler. Ayrıca isme sahip olmadıkları için yapılandırıcı metotlarıda yoktur. Bu konuyla ilgili kısa bir örnek yaparak konuyu sonlandıralım. //isimsizSinifOrnegi.java - 09.04.2014 1 2 interface Faktoriyel // interface tanımlandı 3 { 4 public double hesap(); 5 } 6 7 public class isimsizSinifOrnegi 8 { 9 public Faktoriyel faktoriyelAl(final double sayi) 10 { 11 return new Faktoriyel() 12 { 13 // arayüz içerisindeki metodları kullanmak için isimsiz bir sınıf 14 oluşturduk 15 @Override 16 public double hesap() 17 { 18 double x = 1; 19 for(int i = 1 ; i <= sayi ; i++) 20 x *= i; 21 return x; 22 } 23 }; // noktalı virgül kullanıldı 24 } 25 public static void main(String[] args) 26 { 27 isimsizSinifOrnegi i = new isimsizSinifOrnegi(); 28 // metodumuz faktöriyel tipinde değer döndürdüğü için bu tipte nesne 29 tanımlıyoruz 30 Faktoriyel f = i.faktoriyelAl(7); 31 System.out.println("7'nin faktoriyeli: " + f.hesap()); 32 } 33 } 34 Ekran çıktısı: 7'nin faktoriyeli: 1 5040.0 Örneğimizde yine sınıf içerisinde daha önceki örneğimizde olduğu gibi bir faktöriyel alma metodu tanımladık. Metodumuzu dönüş tipini, arayüzümüz olarak verdik ve bu sayede return kelimesinden sonra, arayüzün metodunu isimsiz bir sınıf içerisinde tanımlamadık. Faktöriyel alma metodumuzun parametresine baktığımızda, final kelimesiyle işaretlendiğini görüyoruz. Bunun sebebi ise; isimsiz sınıfların içerisinde kullanıldıkları metotların veya sınıfların, sadece final tipteki değişkenlerine erişebiliyor olmasındandır. İsimsiz sınıfımızdan sonra noktalı virgül kullandığımıza da dikkat edelim. Bunun sebebi ise return kelimesinden sonra tanımladığımız isimsiz metodumuzun, bir değer olarak algılanmasıdır. Istisnalar: ! Dahili sınıflar, nesneye yönelik programlamanın temel taşlarından biri olan Kapsülleme'ye destek verdiği için bir üstünlük sağlar. İç içe sınıfları yazarak, sınıflar arasındaki ilişkiyi düzenler ve bu sınıfları kolayca yönetmemizi sağlar. Ders 76 - Çok Biçimlilik (Polimorfizm) Kavramına Giriş Polimorfizm; yani Çok Biçimlilik, Kalıtım kavramı ile iç içedir. Birbirleriyle beslenirler. Kalıtım konusunda sınıfları türetmeyi görmüştük. Türetilen sınıflar, türediği üst sınıfın öğelerine sahip oluyorken bunun tersi geçerli değildi. Yani temel sınıflar, alt sınıfların üyelerine sahip olamazlar. Polimorfizm yapabilmek için Kalıtımmantığını bilmek gerekir. Polimorfizm, çoklu biçim veya çoklu şekil anlamına gelir. Yani Polimorfizm yapılarak bir nesne, farklı nesneler gibi davranabilir. Bir nesne, farklı sınıflardan oluşturulmuş nesneleri yüklenebilir. Örnek üzerinde Polimorfizm konusunu anlatalım. 1 //Polimorfizm.java - 09.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class UstSinif { public void yaz() { System.out.println("Burası üst sınıf"); } } class AltSinif1 extends UstSinif // miras alındı { public void yaz() // override edildi { System.out.println("Burası alt sınıf1"); } } class AltSinif2 extends UstSinif // miras alındı { public void yaz() // override edildi { System.out.println("Burası alt sınıf2"); } } public class Polimorfizm { public static void nesneAl(UstSinif nesne) { nesne.yaz(); } public static void main(String[] args) { UstSinif u1 = new UstSinif(); AltSinif1 a1 = new AltSinif1(); AltSinif2 a2 = new AltSinif2(); nesneAl(u1); // nesneAl metoduna parametre olarak gönderildi nesneAl(a1); // nesneAl metoduna parametre olarak gönderildi nesneAl(a2); // nesneAl metoduna parametre olarak gönderildi } } Ekran çıktısı: 1 2 3 Burası üst sınıf Burası alt sınıf1 Burası alt sınıf2 Örneğimizde 3 sınıfımız var. En tepede UstSinif, bunlardan türemiş olan AltSinif1 ve AltSinif2 sınıfları vardır. Bu türetilmiş sınıflar, super sınıftaki yaz() metodunu override yani iptal etmişlerdir. main() metodumuzda bu 3 sınıftan 3 nesne oluşturduk ve daha sonra bu nesneleri nesneAl() metoduna parametre olarak gönderdik, dikkat edelim. Bu nesneAl() metodu, parametre olarak UstSinif tipinde nesne adında bir parametre alıyor. Bu nesneparametresi, hem u1 hem a1 hem de a2 nesnelerinin yerine geçti. Yani bu 3 sınıf tipinde de nesneler aldı. Yani birçok biçime girdi. İşte Polimorfizm kavramının temelinde de bu yatar. Biz bu metoda 3 defa parametre gönderdik. Bu parametre olan nesnelerin her biri farklı sınıflardan türetilmişlerdir. nesneAl() metodunda ise, bu alınan nesne üzerinden yaz() metodu çağırılır. Peki, AltSinif1'den türetilen nesne, bu metoda gönderildiğinde, metodun parametresi UstSinif tipindendir. Acaba hangi sınıfa ait yaz() metodu çalışıyor? AltSinif1 sınıfı, UstSinif'daki metodu override ettiği için AltSinif1'deki yaz() metodu çağırılmıştır. Başka bir örnek verelim ve konumuzu daha iyi anlayalım. 1 //Polimorfizm.java - 09.04.2014 2 3 class Canli 4 { 5 public void yaz() 6 { 7 System.out.println("Canli Sınıfı"); 8 } 9 } 10 11 class Insan extends Canli 12 { 13 public void yaz() 14 { 15 System.out.println("Insan Sınıfı"); 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 } } class Hayvan extends Canli { public void yaz() { System.out.println("Hayvan Sınıfı"); } } class Bitki extends Canli { public void yaz() { System.out.println("Bitki Sınıfı"); } } public class Polimorfizm2 { public static void nesneAl(Canli c) { c.yaz(); } public static void main(String[] args) { Canli c = new Canli(); Insan i = new Insan(); Hayvan h = new Hayvan(); Bitki b = new Bitki(); nesneAl(c); nesneAl(i); // upcasting(yukarı çevrim) nesneAl(h); // upcasting nesneAl(b); // upcasting } } Ekran çıktısı: 1 Canli Sınıfı 2 Insan Sınıfı 3 4 Hayvan Sınıfı Bitki Sınıfı Bu örneğimizde nesneAl() metodu Canli tipinde bir parametre alıyor. Fakat bu Canli tipindeki parametreye biz Insan, Hayvan, Bitki tipinde de parametreler gönderdik. Buna kızmaz. Çünkü yukarı çevrimyaptık. Yani bizim gönderdiğimiz nesnenin olduğu sınıf, zaten Canli sınıfından türemiştir. Yani her bitki bir canlıdır veya her hayvan bir canlıdır. Yani metodumuz Canli tipinden parametre alıyor ama alınan parametrenin olduğu sınıf da (Hayvan) zaten Canli sınıfının bir alt sınıfıdır. Kalıtım ile ilişkisi de burada başlıyor. Alt sınıflardan oluşturulan nesneler, üst sınıfın referansına bağlanabiliyor. Burada Canli sınıfından yani Canli tipinden parametre alıyor fakat buna Hayvan tipinde bir parametre gönderiliyor. Peki bu c nesnemiz Canli tipinde midir, yoksa Hayvan tipinde mi? Polimorfizm dediğimiz gibi burada karşımıza çıkıyor. c nesnemiz üzerinden yaz() metodu çağırılınca Hayvan mı, yoksa Canli sınıfının mıyaz() metodu çağırılacak? Cevap Hayvan sınıfına ait yaz() metodu. Hayvan sınıfımız, Canli sınıfından türediği için öncelik Hayvan sınıfının yaz() metodudur. Eğer Hayvan sınıfında override yapmasaydık veya Hayvan sınıfımızın içi boş olsaydı ne olacaktı? O zaman çıktıdaki 3. satırda yine Canli sınıfı yazacaktı. Çünkü kendine yaz() metodu olmayınca üst sınıftakiyaz() metodunu çağıracaktı. Bu örnekte c nesnemiz, yani c parametremiz aslında yaptığı iş şudur: Canli c = new Canli(); 1 Canli c = new Insan(); 2 Canli c = new 3 Hayvan(); 4 Canli c = new Bitki(); Yani parametre olan c değerimizin 4 sınıfa ait referansları vardır. Peki, biz bu parametrenin tipini Canlideğil de Hayvan yapsaydık ne olacaktı? O zaman da sadece Hayvan tipindeki nesneyi parametre olarak alacaktı. Çünkü Hayvan sınıfından türemiş başka bir sınıf yoktur. Ama tüm sınıflar Canli sınıfından türemişlerdir. Yani kendi sınıfı ve alt sınıflarından oluşturulan nesneleri alabilecekti. Biz bu bilgileri verdikten sonra Polimorfizm ile ilgili az çok bir şeyler oluştu kafamızda. Polimorfizmde, bir nesnemiz birden fazla nesneye bağlanabilir. Istisnalar: ! Polimorfizm yaptığımızda hangi nesnenin metodunun çağırılacağı, çalışma anında belirlenir. Çünkü program çalıştığında nesneyi kullanacak olan metoda parametre göndeririz. Derleme anında bu metodun hangi nesneyi kullanacağı belli değildir. Eğer yukardaki son örneğimizde Polimorfizm kullanmasaydık nesneAl() metodumuzu aşağıdaki gibi uzun uzun yazmak zorunda kalacaktık. Polimorfizm bizi bundan kurtarıyor. Burada gelen parametremizin hangi sınıfa ait olduğu kontrol edilip ona göre yaz() metodu çağırılıyor. Polimorfizm ile nesnemiz üzerinde karşılaştırma yapmadan nesnenin referansına göre işlem yaptırabiliyoruz. 1 //09.04.2014 2 3 public static void nesneAl(Canli c) 4 { 5 if(c instanceof Canli) // c, canli sınıfından 6 oluşturulmuşsa 7 { 8 Canli c1 = c; 9 c1.yaz(); 10 } 11 else if(c instanceof Insan) 12 { 13 Insan c1 = (Insan)c; // c nesnesi insan sınıfına cast 14 edildi 15 c1.yaz(); 16 } 17 else if(c instanceof Hayvan) 18 { 19 Hayvan c1 = (Hayvan)c; 20 c1.yaz(); 21 } 22 23 24 25 26 27 else if (c instanceof Bitki) { Bitki c1 = (Bitki)c; c1.yaz(); } } Polimorfizm, bizi bu kodları yazmaktan kurtarır. Buradaki instanceof anahtar kelimesini de bir sonraki konuda anlatacağız. Bu anahtar kelimenin görevi, nesnelerin ait olduğu yani oluşturulduğu sınıfı kontrol eder. Eğer o sınıftan oluşturulmuş ise true değilse false döner. Cast işleminin sebebi de şudur: Parametremiz Canli tipindedir. Fakat bu parametreyi, örneğin Insansınıfındaki bir nesneye aktarmak istediğimizde, cast işlemi yapmak zorundayız. Çünkü atanan nesnelerin sınıfları farklıdır. Ders 77 - Geç Bağlama Bir önceki dersimizde metodlarımıza parametre olarak nesne gönderdik ve bu çağırılan metodların hangi nesne üzerinden çalıştırılacağını Java belirledi. Buna Geç Bağlama diyoruz. Yani bu bağlama işlemi çalışma zamanında belli olmuştu. Fakat eğer çalışma zamanında değil de derleme zamanında belli olmuş olsaydı, buna da Erken Bağlama diyecektik. Biz bu dersimizde Geç Bağlama'yı ele alacağız. Geç Bağlama'yı anlatmak için Erken Bağlama'dan olan farkını bir örnekle anlatmamız gerekiyor. Örnek olarak rastgele sayıları verelim. Rastgele sayı üreten bir programımız olsun. Bu rastgele sayılar derleme anında oluşturulmaz. Programımızı çalıştırdığımızda ancak bu rastgele olan sayılar üretilmeye başlar. Geç Bağlama'da da mantık bu şekildedir. Eğer rastgele olarak bir nesne üretir ve bu nesneleri de metodagönderirsek, çağırılan metodun hangi nesne üzerinden çağırılacağı çalışma anında belli olur. Buna bir örnek verelim ve Geç Bağlama'yı örnek üzerinde gösterelim. 1 //Polimorfizm.java - 09.04.2014 2 3 class Canli 4 { 5 public void yaz() 6 { 7 System.out.println("Canli Sınıfı"); 8 } 9 } 10 class Insan extends Canli 11 { 12 public void yaz() 13 { 14 System.out.println("Insan Sınıfı"); 15 } 16 } 17 class Hayvan extends Canli 18 { 19 public void yaz() 20 { 21 System.out.println("Hayvan Sınıfı"); 22 } 23 } 24 class Bitki extends Canli 25 { 26 public void yaz() 27 { 28 System.out.println("Bitki Sınıfı"); 29 } 30 } 31 public class Polimorfizm 32 { 33 public static void nesneAl(Canli c) 34 { 35 c.yaz(); 36 } 37 public static void main(String[] args) 38 { 39 Canli[] h = new Canli[3]; 40 for(int i = 0 ; i < 3 ; i++) 41 { 42 int indis = (int)(Math.random() * 3); // 43 rastgele 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 switch(indis) { case 0: h[indis] = new Bitki(); // upcasting nesneAl(h[indis]); break; case 1: h[indis] = new Hayvan(); // upcasting nesneAl(h[indis]); break; case 2: h[indis] = new Insan(); // upcasting nesneAl(h[indis]); break; } } } } Ekran çıktısı: Insan Sınıfı 1 Bitki Sınıfı 2 Hayvan 3 Sınıfı Ekran çıktısı 2: Hayvan 1 Sınıfı 2 Bitki Sınıfı 3 Insan Sınıfı Örneğimizde bir Geç Bağlama olayı gösterilmiştir. Canli sınıfından 3 elemanlı nesne dizisi üretiliyor. Daha sonra for döngümüz 3 kere dönüyor. Bu dönü içerisinde her seferinde bir rastgele sayı üretiliyor. Bu üretilen rastgele sayı switch içerisine koyuluyor ve kontrol yapılıyor. Sayımızın 0-1-2 olmasına göre farklı referanslardan nesneler üretiliyor. Bu referanslar her çalışma anında rastgele olarak belirleniyor. Her döngüde belirlenen indisli nesne, nesneAl() metoduna gönderiliyor ve gelen nesneye göre yaz() metodları çağırılıyor. Programımızı 2 kere çalıştırdık ve çıktıların farklı olduğunu gördük. İşte bu nesnelerin çalışma anında belirlenmesine Geç Bağlama deniliyor. Istisnalar: ! Eğer geç bağlama olmasını istemiyorsak, ana sınıftaki istenilen metodu final tanımlarız. Kalıtım konusunda,final anahtar kelimesinin override etmeyi engellediğini söylemiştik. Bir metod alt sınıflar tarafındanoverride edilmezse, parametre olarak gelen nesnenin mi, yoksa parametre tipindeki nesnenin mi metodunun çalıştırılacağı düşünülmez. Polimorfizm anlatırken instanceof anahtar kelimesinden bahsetmiştik. Polimorfizm ile buna artık gerek kalmasa da, bu konuyu da bir sonraki dersimizde anlatacağız. Ders 78 - Instanceof İle Tip Kontrolü Bu anahtar kelime, nesnelerin hangi sınıftan oluşturulduğunu bulmaya yardımcı olur. Örnek üzerinde göstererek anlatalım. //C.java - 09.04.2014 1 2 class A 3 { 4 } 5 class B 6 { 7 } 8 class C 9 { 10 public static void main(String[] 11 args) 12 { 13 A a1 = new A(); 14 B b1 = new B(); 15 System.out.println(a1 instanceof 16 A); 17 System.out.println(b1 instanceof 18 B); 19 } 20 } Ekran çıktısı: 1 true 2 true Bu örnekte main metodumuzda, A sınıfından a1 nesnesini, B sınıfından da b1 nesnesini oluşturduk. Bub1 nesnesi, A sınıfından oluşturulmamıştır. Alt satırlarda da her iki çıktımız true değerini verecektir. Çünkü a1ve b1 nesneleri, instanceof kelimesinden sonraki yazılmış sınıflardan türemişlerdir. Peki, sınıflarımız eğer kalıtım yoluyla türetilmişlerse nasıl bir mantık olacak? Örnek üzerinde anlatalım. 1 //D.java - 09.04.2014 2 3 class A 4 { 5 } 6 class B extends A 7 { 8 } 9 class C extends B 10 { 11 } 12 class D extends B 13 { 14 public static void main(String[] 15 args) 16 { 17 A a1 = new A(); 18 B b1 = new B(); 19 C c1 = new C(); 20 D d1 = new D(); 21 System.out.println(a1 instanceof 22 B); 23 System.out.println(b1 instanceof 24 B); 25 System.out.println(c1 instanceof 26 A); 27 System.out.println(b1 instanceof 28 C); 29 30 31 System.out.println(c1 instanceof A); System.out.println(c1 instanceof B); System.out.println(d1 instanceof B); System.out.println(d1 instanceof A); } } Ekran çıktısı: 1 false 2 true 3 true 4 false 5 true 6 true 7 true 8 true Bu örneğimizde temel mantık şu şekildedir. Örneğin; D sınıfını, B'den türetmişiz. B sınıfını da yukarıdaA'dan türetilmiştir. Dolayısıyla D sınıfından oluşturacağımız bir nesne, aynı zamanda A sınıfının da bir örneğidir (instance). Kalıtım konusundaki kullanımı ise bu şekildedir. Yukarıdaki örnekte mantığını anlattık. Şimdi de yukarıdaki sınıfların içini doldurarak bir örnek yapalım ve ifyapılarını da kullanalım. 1 //D.java - 09.04.2014 2 3 class A 4 { 5 public int aSayi = 5; 6 } 7 class B extends A 8 { 9 public int bSayi = 6; 10 } 11 class C extends B 12 { 13 public int cSayi = 7; 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 } class D extends B { public static void main(String[] args) { A a1 = new A(); B b1 = new B(); C c1 = new C(); D d1 = new D(); if(c1 instanceof A) { System.out.println("c nesnesi A sınıfının elemanına erişebilir:"); System.out.println(c1.aSayi); } else System.out.println("c1 nesnesi aSayi değişkenine erişemedi"); if(b1 instanceof D) System.out.println("b1 nesnesi, D sınıfına erişebilir"); else System.out.println("b1 nesnesi D sınıfına erişemez"); } } Ekran çıktısı: c nesnesi A sınıfının elemanına 1 erişebilir: 2 5 3 b1 nesnesi D sınıfına erişemez Örneğimizde c1 nesnesi aynı zamanda A sınıfının bir örneği olduğu için if şartımıza girecektir ve aSayideğişkenini yazacaktır. b1 nesnesi ise D sınıfının bir örneği olmadığı için else şartına girecektir. instanceof anahtar kelimesi ile bir değişkenin ait olduğu sınıfı şu şekilde karşılaştırabiliriz. Örnek verirsek; 1 //Karsilastirma.java - 09.04.2014 2 3 class Karsilastirma 4 5 6 7 8 9 10 11 12 { public static void main(String[] args) { String deneme = "ElektroArge"; System.out.println(deneme instanceof java.lang.String); } } Ekran çıktısı: 1 true String, bir sınıf olduğu için deneme adlı değişkenimiz aslında String sınıfından türemiştir. Karşılaştırırken ise java.lang.String şeklinde sınıfımızı yazıyoruz. Aynı şekilde aşağıdaki gibi bir karşılaştırma da yapabiliriz. Bu da true değeri döndürecektir. Stringharicindeki değişken tiplerimizi aşağıdaki gibi tanımlamak zorundayız. Çünkü String sınıfı, diğer tiplerden farklıdır. Yukarıda String değişken tanımlamıştık. Fakat String haricindeki değişkenleri, new ile nesne oluşturarak yapmalıyız. //Karsilastirma2.java - 09.04.2014 1 2 class Karsilastirma2 3 { 4 public static void main(String[] args) 5 { 6 Integer deneme = new Integer(4); 7 System.out.println(deneme instanceof 8 java.lang.Integer); 9 } 10 } 11 12 GETCLASS METODU İLE NESNENİN SINIFINI ÖĞRENME Yukarıdaki karşılaştırmayı yapmanın bir yolu daha var. O da getclass() metodudur. Bu metot, yalnız başına kullanıldığında nesnenin ait olduğu sınıfı verir. Şimdi basit bir örnek verelim ve kullanımını görelim. 1 package paket; 2 //D.java - 09.04.2014 3 4 class A 5 { 6 } 7 class B 8 { 9 } 10class D extends B 11{ 12 public static void main(String[] args) 13 { 14 A a1 = new A(); 15 B b1 = new B(); 16 D d1 = new D(); 17 System.out.println(d1.getClass().equals(A.class)); 18 System.out.println(b1.getClass().equals(A.class)); 19 System.out.println(a1.getClass().equals(A.class)); 20 System.out.println(a1.getClass()); 21 System.out.println(b1.getClass()); 22 System.out.println(d1.getClass()); 23 } 24} 25 26 Ekran çıktısı: false false 1 true 2 class 3 paket.A 4 class 5 paket.B 6 class paket.D Koda baktığımız zaman az çok anlıyoruz. İlk 3 satır bizim işimize yarayan satırlar. Son 3 satırı isegetclass() metodunun yalnız başına ne iş yaptığını göstermek için yazdık. İlk satırı ele alalım. d1.getclass() diyerek d1'in olduğu sınıfı elde ediyoruz. equals() metodunun içerisine de karşılaştıracağımız sınıfı yazıyoruz. Metodun içerisine yazdığımız ifadeyi sınıfadı.class yapısı ile yazıyoruz. Eğer aynı sınıflardansa true değerini, değilse false değerini elde ediyoruz. Yalnız başına getclass() metodu ise, çıktıdaki son satırlarda da gördüğümüz gibi sınıfın adını veriyor. Bunu paket adı ile beraber yazarak bize veriyor. Istisnalar: ! Java'da tüm sınıflar Object sınıfından türediği için, herhangi bir nesnemiz aynı azamanda Object sınıfının bir örneğidir. Dolayısıyla bir alt sınıf, aynı zamanda tüm üst sınıflarının bir örneği sayılır. Fakat üst sınıflardan oluşturulan nesneler, alt sınıfların bir örneği sayılmazlar Ders 79 - Math Sınıfına Giriş C dili ile biraz uğraştıysanız, bu sınıfa yabancı değilsiniz demektir. Math sınıfı, Java'da matematiksel işlemler yapmaya yarayan bir sınıftır. Bünyesinde matematiksel işlemler yapan metodları barındırır. Mesela;üs alan bir işlem yapacaksak, bunu döngüler ile uzun uzun yapmaktansa, tek bir metot ile yapabilirsiniz. Mathsınıfı bize bu metotları sağlar. Şimdi sıradaki derslermizle bu metotları örnek üzerinden anlatalım. Ders 80 - Math.pow Metodu İle Sayının Üssünü Alma Bu metot,üs alma işlemi yapar. 2 parametre alır. İlk parametre üssü alınacak sayıdır. Diğer parametre ise üssün derecesidir. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 class MathSinifiOrnekler 4 { 5 public static void main(String[] args) 6 { 7 8 9 10 11 12 13 System.out.println(Math.pow(3, 5)); int a = (int)Math.pow(2, 4); // cast işlemi yapıldı System.out.println(a); } } Bu örnekte ilk satırda doğrudan 3'ün 5. kuvvetini alarak ekrana yazdırdık. Sonuç double türünde ondalık bir sayı oldu. Normalde sonuç int tipinde olması gerekirdi. Çünkü sonuç 243'tür. Buradan anlıyoruz ki Mathsınıfından double türünden değerler dönüyor. Bir alt satırda da 2'nin 4. kuvvetinin sonucunu int'e cast ettik. Eğer etmeseydik doğrudan int a değişkenine atsaydık, hata verecekti. Sonuç double döndüğü için doğrudanint değişkenine atayamadık. Buradan şunu anlıyoruz. Istisnalar: ! Math sınıfında işlem sonucunda dönen değerler, double türünde olabileceğinden sonucu int'e cast etmek gerekir. Ders 81 - Math.sqrt Metodu İle Sayının Karekökünü Alma Bu metot, bir sayının karekökünü bulur. Dolayısıyla 1 parametre alır. Bu da double türünden değer döndürür. O yüzden bir değişkene atacaksak, cast etmemiz gerekir. Eğer sonucu yine double türünde bir değişkene atacaksak, cast işlemine gerek yoktur. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 class MathSinifiOrnekler 4 { 5 public static void main(String[] args) 6 { 7 System.out.println(Math.sqrt(25)); 8 int b = (int)Math.sqrt(25); 9 System.out.println(b); 10 System.out.println(Math.sqrt(50)); 11 } 12 } 13 14 Ekran çıktısı: 1 5.0 2 5 3 7.0710678118654755 Bu metottan da double türünde sonuç döndü. 2. satırda ise cast etmek zorunda kaldık. Son satırda da 50'nin tamsayı olarak karekökü olmadığı için küsüratlı bir sonuç elde ettik. Ders 82 - Math.abs Metodu İle Sayının Mutlak Değerini Alma Bu metot bir sayının mutlak değerini alır. Negatif bir sayıyı pozitife çevirip gösterir. Pozitif bir sayıyı ise aynen yazar. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 class MathSinifiOrnekler 4 { 5 6 7 8 9 10 11 12 13 14 public static void main(String[] args) { System.out.println(Math.abs(-40)); int b = Math.abs(-40); // cast'e gerek yok System.out.println(b); System.out.println(Math.abs(20)); } } Ekran çıktısı: 1 40 2 40 3 20 Bu metotta bir istisnayı gördük. Sonucu doğrudan int değişkenine atabiliriz. Cast işlemine gerek yoktur. Sonuç int tipinde döndü, çünkü pozitif sayıyı da aynen yazdı. Eğer bir int tipinde değil de double tipinde bir sayının mutlak değerini almaya çalışsaydık, o zaman cast etmemiz gerekirdi. Fakat diğer metotlarda int tipinde bir sayıyla bile işlem yapsak sonucu double türüne çeviriyordu. Biz int tipindeki bir değişkene atamaya çalıştığımız için hep cast işlemi yaptık. Eğer int b değil de double badlı değişkene atsaydık cast işlemine gerek kalmayacaktı. Amacımız bazı durumlarda double tipinde sonuç döndüğünü göstermektir. Ders İçinde Yazılmış Tüm Programlar ve Kodları Ektedir: Ders 83 - Math.floor Metodu İle Sayıyı Alt Değere Yuvarlama floor kelimesi İngilizcede zemin anlamına geldiği için bu metodun ne iş yaptığını kestirebilirsiniz. Verilen bir tamsayıyı bir alttaki değere yuvarlar. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 class MathSinifiOrnekler 4 { 5 public static void main(String[] args) 6 { 7 System.out.println(Math.floor(5.4)); 8 int b = (int)Math.floor(7.501); 9 System.out.println(b); 10 double c = Math.floor(8.0001); 11 System.out.println(c); 12 System.out.println(Math.floor(9)); 13 } 14 } 15 16 Ekran çıktısı: 1 5.0 2 7 3 8.0 4 9.0 Bu metot, bir nevi sayının virgülden sonraki kısmını atar. Bu metot da double türünde sonuç döndürür. Örnekte de görüldüğü gibi b değişkenine atarken cast etmek zorunda kaldık. Eğer sayımız 7.501 değil de 7 olsaydı yine onu 7.0 olarak çevirecekti ve yine cast etmemiz gerekecekti. Alt satırda da doğrudan doubletipindeki değişkene atadığımız için cast işlemine gerek kalmadı. İlk satırdaki gibi doğrudan yazdırdığımız zaman, zaten herhangi bir işleme gerek kalmadan sonucu yazıyor. Ders 84 - Math.ceil Metodu İle Sayıyı Üst Değere Yuvarlama Bu metot, Math.floor metodunun aksine, sayıyı üst değere yuvarlar. Bir nevi virgülden sonraki kısmı atar ve kalan sayıyı 1 artırır. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 class MathSinifiOrnekler 4 { 5 public static void main(String[] args) 6 { 7 System.out.println(Math.ceil(7.0001)); 8 int b = (int)Math.ceil(7.9999); 9 System.out.println(b); 10 System.out.println(Math.ceil(7)); 11 } 12 } 13 14 Ekran çıktısı: 1 8.0 2 8 3 7.0 Bu metot da double tipinde değer döndürür. Onu göstermek için int tipinde bir değişkene attık. Görüldüğü gibi 7.0001 bile olsa onu 8'e tamamlıyor, yani yuvarlıyor. Eğer son satırdaki gibi sadece 7 sayısını verirsek onu yuvarlamadan bırakıyor. Görüldüğü gibi 7'yi 7.0 olarak yazıyor. Bu da double tipinde değer döndüğünü gösteriyor. Ders 85 - Math.max Metodu İle Büyük Sayıyı Bulma Adından da anlaşıldığı üzere, verilen sayılardan büyüğünü bulan metottur. 2 parametre alır. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 class MathSinifiOrnekler 4 { 5 6 7 8 9 10 11 12 13 14 15 16 17 static void yaz(int a, int b) { System.out.println(Math.max(a, b)); } public static void main(String[] args) { MathSinifiOrnekler.yaz(55, 56); // metoda parametre gönderdik System.out.println(Math.max(4, 5)); System.out.println(Math.max(4, 4.0001)); } } Ekran çıktısı: 1 56 2 5 3 4.0001 Bu örnekte gördüğümüz gibi Math sınıfının metotlarını doğrudan kullanmak yerine parametre geçirerek de kullanabiliriz. Ayrıca bu örnekte son yazdığımız kodda küsüratlar sayesinde sayımız 4'ten büyük olmuştur. Ders 86 - Math.min Metodu İle Küçük Sayıyı Bulma Bu metot, Max metodunun tersine verilen iki sayıdan küçük olan sayıyı bulan metottur. Metot, 2 parametre alır. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 class MathSinifiOrnekler 4 { 5 static void yaz(int a, int b) 6 { 7 System.out.println(Math.min(a, b)); 8 } 9 public static void main(String[] args) 10 { 11 MathSinifiOrnekler.yaz(55, 56); // metoda parametre 12 gönderdik 13 System.out.println(Math.min(4, 5)); 14 15 16 17 System.out.println(Math.min(4, 4.0001)); } } Ekran çıktısı: 1 55 2 4 3 4.0 Daha önce max metodu için yaptığımız örneği bu sefer min metodu için yaptık. Değerlere baktığımızda metodumuzun bize verilen sayıların en küçüğünü bulduğunu görüyoruz. Hem yaz() metodunu çağırarak yaptık hem de doğrudan Math.min() metodu ile işlem yaptık. Ders 87 - Math.random Metodu İle Rastgele Sayı Üretme Bu metot, rastgele sayılar üretmek için kullanılır. Bu metot da double türünde değer döndürür ve 0.0 ile 1.0 arasında değer üretir. Bu konuya birkaç örnek verelim. 1 //RandomSinifi.java - 09.04.2014 2 3 class RandomSinifi 4 { 5 public static void main(String[] args) 6 { 7 System.out.println(Math.random()); 8 } 9 } 10 11 Ekran çıktısı: 1 0.025176312544407664 Dediğimiz gibi bu metot, 0-1 arasında double bir sayı üretti. Peki, bu sayı nasıl işimize yarayacak? Aşağıdaki kod parçasını inceleyelim ve bu metodu nasıl faydalı bir şekilde kullanırız onu görelim. int sayi = (int)(Math.random() * 10); 1 // double türünde sayı üretileceğinden int'e cast etmek 2 gerekir 3 System.out.println(sayi); Math.random() ile rastgele bir sayı ürettik. Üretilen değeri 10 ile çarpmamızın sebebi, bu metodun 0 ile 1 arasında double türünde değer üretmesidir. Bunu 10 ile çarparak virgülü sola kaydırırız. Mesela; metottan çıkan değer 0.654323 ise 10 ile çarptığımızda 6.554323 olur. Daha sonra sonucu int'e cast edince başındaki6 sayısını alır. Sonuç olarak bu fonksiyon 0 ile 10 arasında değer üretecektir. Biz bu fonksiyonun sonuna +10 eklersek; 10 ile 20 arasında sayı üretecektir. Buna 20 dahil değildir. Bir örnek verirsek: //RandomSinifi2.java - 09.04.2014 1 2 class RandomSinifi2 3 { 4 public static void main(String[] args) 5 { 6 System.out.println(Math.random()); 7 System.out.println((int)(Math.random() * 15)); 8 //0 - 15 arasında sayı üretecektir 9 System.out.println((int)(Math.random() * 15 + 10 20)); 11 //0 - 35 arasında sayı üretecektir 12 } 13 } 14 15 Ekran çıktısı: 1 0.5205707499643846 2 1 3 34 Yukardaki örnekte, metodumuzu hem çarpıyoruz hem de sonuca değer ekliyoruz. Böylece üretilecek sayımızın eleman kümesini genişletiyoruz. Bu anlattıklarımıza, döngüleri ve dizileri de kullanarak bir örnek verelim. //RandomSayi.java - 09.04.2014 1 2 import java.util.Random; 3 4 public class RandomSayi 5 { 6 public static void main(String[] args) 7 { 8 int dizi[] = new int[6]; 9 Random r = new Random(); 10 for (int a = 0; a < dizi.length ; a++) 11 { 12 dizi[a] = r.nextInt(100); 13 System.out.println("Dizinin " + (a + 1) + ". elemanı: " + 14 dizi[a]); 15 } 16 } 17 } 18 19 Ekran çıktısı: Dizinin 1. elemanı: 40 Dizinin 2. elemanı: 1 84 2 Dizinin 3. elemanı: 3 38 4 Dizinin 4. elemanı: 5 14 6 Dizinin 5. elemanı: 48 Dizinin 6. elemanı: 11 Bu örnekte 6 elemanlı dizimize, for döngüsü içerisinde rastgele 0 ve 100 arasında sayılar atadık. Daha sonra bu atadığımız dizi elemanlarını ekrana yazdırdık. Son olarak basit bir örnekle bitirelim. //MathSinifiOrnekler.java 09.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class MathSinifiOrnekler { public static void main(String[] args) { for (int i = 0 ; i < 4 ; i++) { int a = (int)(Math.random() * 10); System.out.println(a); } } } Ekran çıktısı: 1 4 2 9 3 9 4 3 Istisnalar: ! Math sınıfı, java.lang paketinden türediği için bu Math sınıfını ayrıca import etmeye gerek yoktur. Çünküjava.lang paketi zaten Java programlarında otomatik olarak import edilmiştir. RANDOM SINIFI İLE RASTGELE SAYI ÜRETME Rastgele sayı üretebilmek için Math sınıfının yanında Random sınıfı da kullanılır. Random sınıfı, sadece inttüründe değil float, byte, double gibi türlerde de sayı üretebilir. Rastgele sayı üretmenin bir diğer yolu olduğu için bu başlık altında kısaca değineceğiz. Bu sınıfı kullanmak için öncelikle sınıfı tanımladığımız yerin üst kısmına, paket isminden sonra şu sınıfıimport ediyoruz. [code2=]import java.util.Random;[/code2] // Random sınıfı import edildi Paket tanımlamaları hep bu kısma yapılır. İlk olarak Random sınıfından bir nesne oluşturuyoruz. Şimdi oluşturulan bu nesneden bir sayı üretiyoruz. Random r = new Random(); // random sınıfından r adında bir nesne 1 oluşturduk 2 int a = r.nextInt(10); // bu r nesnesinden int tipinde sayı üretiyoruz Random sınıfından r adında bir nesne oluşturuyoruz ve r nesnesi üzerinden nextInt() metoduna erişiyoruz. Bu metot, bize int tipinde rastgele bir sayı üretecektir. Burada parantez içerisinde 10 yazmamızın sebebi, 0'dan 10'a kadar değerler üretmesini istememizdir. Fakat buna 10 dahil değildir, 0 dahildir. Hangi değere kadar sayı üretilmesini istiyorsak, parantez içerisine onu yazarız. Eğer parantez içerisini boş bırakırsak -2147483648 ve +2147486647 arasındaki bütün int değerlerini üretir. Diğer türlerde sayı üretmek istiyorsak kullanacağımız kodlar: long l = r.nextLong(); // long tipinde bir sayı üretir 1 float f = r.nextFloat(); // float tipinde bir sayı üretir 2 double d = r.nextDouble(); // double tipinde rastgele bir sayı 3 üretir Rastgele sayımızı bu şekilde Random sınıfından türetilen nesne üzerinden oluşturuyoruz. Programımızı her çalıştırdığımızda istenilen tipte rastgele bir sayı üretecektir. Bu r nesnesi üzerinden farklı farklı metodlara erişebiliriz. Bu metotların listesi şu şekildedir: Buradaki metotlardan, rastgele sayı üreten nextDouble(), nextFloat() gibi metotları inceleyeceğiz. Şimdi bütün tipleri kullanarak örnek yapalım. //RandomSinifi3.java - 09.04.2014 1 2 import java.util.Random; 3 4 class RandomSinifi3 5 { 6 public static void main(String[] args) 7 { 8 Random r = new Random(); 9 System.out.println("Int: " + r.nextInt()); 10 // 0 ile 10 arasında üretecektir 11 12 System.out.println("Int: " + r.nextInt()); 13 System.out.println("Boolean: " + 14 r.nextBoolean()); 15 System.out.println("Double: " + 16 r.nextDouble()); 17 System.out.println("Float: " + r.nextFloat()); 18 System.out.println("Long: " + r.nextLong()); 19 System.out.println("Gaussian: " + 20 r.nextGaussian()); 21 } 22 } Ekran çıktısı: Int: 554977118 1 Int: -1875198449 2 Boolean: false 3 Double: 4 0.29761422254107595 5 Float: 0.54041606 6 Long: 8923612717938646514 7 Gaussian: 2.1147448804741766 Yukardaki örneğimizde her tipte rastgele bir sayı ürettik. Gaussian tipi, bir çeşit double veri tipidir. Programımızı her çalıştırdığımızda bu değerler değişecektir. Başka bir örnek verelim. 1 //RandomSayi2.java - 09.04.2014 2 3 import java.util.Random; 4 5 public class RandomSayi2 6 { 7 public static void main(String[] args) 8 { 9 int sayi = 5 ,deger = 0; 10 Random r = new Random(); 11 while(true) 12 { 13 int i = r.nextInt(11); 14 if(i != sayi) 15 deger++; 16 else 17 { 18 System.out.println("Sayı " + deger + ". denemede 19 bulundu"); 20 break; 21 } 22 } 23 } 24 } 25 Ekran çıktısı: Sayı 8. denemede 1 bulundu Bu örnekte while(true) ile sonsuz döngüye girdik. Daha sonra 0 ile 11 arasında bir değer üreterek bunu i değişkenine attık. Program başlangıcında belirlediğimiz sayi değişkenini, kaçıncı denemede bulacağını ifdöngüleri ile kontrol ettik. Rastgele üretilen sayı ile başlangıçta belirlediğimiz sayı aynı olduğunda break; ile döngüden çıktık. Son bir örnek verelim. //RandomSinifi4.java - 09.04.2014 1 2 import java.util.Random; 3 4 class RandomSinifi4 5 { 6 public static void main(String[] args) 7 { 8 Random r = new Random(); 9 for(int i = 0 ; i < 3 ; i++) 10 { 11 int sayi1 = r.nextInt(6); 12 sayi1 += 1; 13 int sayi2 = r.nextInt(6); 14 sayi2 += 1; 15 System.out.println("Zarda gelen 16 sayılar: "); 17 System.out.println(sayi1 + " - " + 18 sayi2); 19 } 20 } 21 } 22 Ekran çıktısı: 1 Zarda gelen 2 sayılar: 3 5-1 4 5 6 Zarda gelen sayılar: 3-2 Zarda gelen sayılar: 1-2 Örneğimizde for döngümüz ile 3 kere zar atıyoruz. sayi1 ve sayi2 değişkenlerini 1 artırmamızın sebebi ise şudur. Eğer nextInt() metodu ile 0 değeri üretilirse, bunu 1 yapmamız gerekiyor. Çünkü zarlarda 0 sayısı bulunmaz. Üst sınıf olarak ise 6 verdik. En fazla 5 sayısı üretilir. Artırma işlemi ile bu yine 6'ya çıkar ve en fazla 6 sayısı üretilir. Ders 88 - Math.toDegrees Metodu İle Radyanı Dereceye Çevirme Matematik sınıfımızın bu metodu radyanı dereceye çevirir. Parametre olarak aldığı double değerinderece karşılığını geriye döndürür. //MathSinifiOrnekler.java - 09.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 public class MathSinifiOrnekler { public static void main(String[] args) { System.out.println("0.5 Radyan " + Math.toDegrees(0.5) + " derecedir."); System.out.println("1 Radyan " + Math.toDegrees(1) + " derecedir."); System.out.println("1.5 Radyan " + Math.toDegrees(1.5) + " derecedir."); } } Ekran çıktısı: 1 0.5 Radyan 28.64788975654116 2 derecedir. 3 1 Radyan 57.29577951308232 derecedir. 1.5 Radyan 85.94366926962348 derecedir. Yukarıdaki örneğimizde radyan cinsinden değerleri derece cinsine çevirdik. Geriye dönen değerlerimizindouble değer olduğuna dikkat ediniz. Ders 89 - Math.toRadians Metodu İle Dereceyi Radyana Çevirme Matematik sınıfımızın bize sağladığı bu metot, toDegrees metoduna benzer. Parametre olarak aldığıderece cinsinden değeri radyan cinsine çevirir. //MathSinifiOrnekler.java - 09.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 public class MathSinifiOrnekler { public static void main(String[] args) { System.out.println("0 Derece " + Math.toRadians(0) + " radyandır."); System.out.println("45 Derece " + Math.toRadians(45) + " radyandır."); System.out.println("90 Derece " + Math.toRadians(90) + " radyandır."); } } Ekran çıktısı: 0 Derece 0.0 radyandır. 1 45 Derece 0.7853981633974483 2 radyandır. 3 90 Derece 1.5707963267948966 radyandır. Yukarıda verdiğimiz örnekte 45 ve 90 dereceyi radyan cinsine çevirmek için toRadians metodumuzu kullandık. Metodumuzun bize döndürdüğü değerin yine double tipte olduğuna dikkat ediniz. Ders 90 - Math.sin Metodu İle Sinüs Bulma Matematik sınıfımızın trigonometrik metotlarından biri olan sin metodu içerisine, parametre olarak aldığıradyan cinsinden açının sinüsünü döndürür. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 public class MathSinifiOrnekler 4 { 5 public static void main(String[] args) 6 { 7 System.out.println(Math.sin(Math.toRadians(0))); 8 System.out.println(Math.sin(Math.toRadians(90))); 9 System.out.println(Math.sin(Math.toRadians(45))); 10 } 11} 12 13 Ekran çıktısı: 1 0.0 2 1.0 3 0.7071067811865475 Örneğimizde matematik sınıfımızın sin ve toRadians metotlarını kullandık ve metodumuza parametre olarak radyan cinsinden 0.45 ve 90 dereceyi gönderdik. Derece cinsinden bu değerleri radyan cinsine çevirmek için toRadians metodunu kullandık. Sin(0)'ın matematiksel değeri 0, Sin(90)'ın matematiksel değeri 1, Sin(45)'in matematiksel değeri ise yaklaşık olarak 1/karekök 2'dir. 2. satırı ele alırsak, 90 dereceyi radyana çevirir ve çıkan sonucu sin metoduna parametre olarak göndermiş olur. Ders 91 - Math.asin Metodu İle Ters Sinüs Bulma Bu metot, sin metodunun tersine parametre olarak sinüs değerini alır ve bu sinüs değerine karşılık gelen açıyı yine radyan cinsinden gönderir. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 public class MathSinifiOrnekler 4 { 5 public static void main(String[] args) 6 { 7 System.out.println(Math.toDegrees(Math.asin(0))); 8 System.out.println(Math.toDegrees(Math.asin(1))); 9 System.out.println(Math.toDegrees(Math.asin(0.7071067811865476))); 10 } 11} 12 13 Ekran çıktısı: 1 0.0 2 90.0 3 45.00000000000001 Örneğimizde asin metodumuza daha önceki örneğimizden elde ettiğimiz açısal değerleri gönderdik ve gelen açıyı derece cinsine çevirmek için toDegrees metodunu kullandık. Ekran çıktımızda da görüldüğü gibi 0,90 ve 45 dereceyi metodlarımızla elde ettik. 2. satırı ele alırsak, 1'e karşılık gelen sinüs açısı 90'dır. 90'ı radyana çevirir ve elde edilen sonucutoDegrees metoduna gönderir. Yani sinüs değeri alır ve radyana çevirir. Ders 92 - Math.cos Metodu İle Cosinüs Bulma Bu metodumuz içerisine parametre olarak aldığı radyan cinsinden değerin cosinüs değerini döndürür. Bir derecenin cosinüs değerini öğrenmek istiyorsak, ilk olarak bu dereceyi radyana çevirmek gerekir. Çünkü bu metod radyanı parametre olarak alır. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 public class MathSinifiOrnekler 4 { 5 public static void main(String[] args) 6 { 7 System.out.println(Math.cos(Math.toRadians(0))); 8 System.out.println(Math.cos(Math.toRadians(60))); 9 System.out.println(Math.cos(Math.toRadians(45))); 10 } 11} 12 13 Ekran çıktısı: 1 1.0 2 0.5000000000000001 3 0.7071067811865476 Örneğimizde öncelikle derece cinsinden değerleri radyan cinsine çevirmek için toRadians metodunu kullandık. Daha sonrasında bu değerlerin cosinüs değerlerini bulmak için cos metodunu kullandık. Ders 93 - Math.acos İle Ters Cosinüs Bulma Bu metot yine asin metodunda olduğu gibi içerisine parametre olarak bir cosinüs değeri alır ve geriye bu cosinüs değerine ait radyan cinsinden açıyı gönderir. 1 //MathSinifiOrnekler.java - 09.04.2014 2 3 public class MathSinifiOrnekler 4 { 5 public static void main(String[] args) 6 { 7 System.out.println(Math.toDegrees(Math.acos(0))); 8 System.out.println(Math.toDegrees(Math.acos(1))); 9 System.out.println(Math.toDegrees(Math.acos(0.7071067811865476))); 10 } 11} 12 13 Ekran çıktısı: 1 90.0 2 0.0 3 45.0 Örneğimizde acos metodumuzua 0,1 ve 0.7071067811865476 değerlerini parametre olarak gönderdik. Dönen sonucu ise radyandan dereceye çevirmek için toDegrees() metodunu kullandık. Ekran çıktımızda da görüldüğü gibi sonuç olarak ise 90.0 ve 45 değerlerini elde ettik. Ders 94 - Math.PI İle Pi Sabitini Kullanma public static final double PI; değişkeni tanımlamak ile aynıdır. Math sınıfının içerisinde de static ve finalolarak tanımlanmıştır. Hem değeri değiştirilemez hem de sadece sınıf adı ile erişilebilir. Her ne kadar metot olarak gözükmese de, yani bir parametre almasa da pi sayısının bu sınıfta yer aldığını göstermek için anlatıyoruz. Kısa bir örnek verelim. //MathSinifiOrnekler.java 1 09.04.2014 2 3 public class MathSinifiOrnekler 4 { 5 public static void main(String[] 6 args) 7 { 8 System.out.println(Math.PI); 9 } 10 } 11 Ekran çıktısı: 1 3.141592653589793 Pi değişkeninin değeri bu sınıf içerisinde yer alır. Ders 95 - Logaritma Metodları Matematik sınıfımız içerisinde üç tane logaritma metodu bulunmaktadır. Hepsi genel olarak logaritma döndürmesine rağmen farklılık logaritma tabanlarından gelir. Metotlarımız şöyledir: Double: log(double deger): deger ile gönderilen değerin doğal logaritmasını(e tabanında) döndürür. Double: log10(double deger): deger ile gönderilen değerin 10 tabanındaki logaritmasını döndürür. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Double: log1p(double deger): deger ile gönderilen değerin 1 fazlasının doğal logaritmasını döndürür. //MathSinifiOrnekler.java - 09.04.2014 public class MathSinifiOrnekler { public static void main(String[] args) { System.out.print("2.718281828459 sayısının doğal logaritması:"); System.out.println(Math.log(2.718281828459)); // e ≈ 2.718281828459 ve ln(e) = 1 System.out.print("10 tabanında 5'in logaritmik değeri: "); System.out.println(Math.log10(5)); System.out.print("10 tabanında 10'un logaritmik değeri: "); System.out.println(Math.log10(10)); System.out.print("(1.7 + 1) 'in doğal algoritması: "); System.out.println(Math.log1p(1.7)); } 18 19 } Ekran çıktısı: 2.718281828459 sayısının doğal 1 logaritması:0.9999999999999832 2 10 tabanında 5'in logaritmik değeri: 0.6989700043360189 3 10 tabanında 10'un logaritmik değeri: 1.0 4 (1.7 + 1) 'in doğal algoritması: 0.9932517730102834 Örneğimizde tüm logaritma metodlarını kullandık. İlk bölümde doğal logaritma almak için log() metodunu kullandık. İkinci bölümde ise, verdiğimiz değerlerin 10 tabanında logaritmasını aldık. Üçüncü bölümde verdiğimiz değerin 1 fazlasının doğal logaritmasını bulmak için log1p() metodunu kullandık. Istisnalar: ! Math sınıfının içerisindeki metodlar static'tir. O yüzden doğrudan sınıf adını kullanarak metodlara erişebildik. Bir nesne oluşturmaya ihtiyacımız olmadı. Math sınıfına ait birçok metod vardır. Math sınıfında kullanılabilecek metodların ne kadar çok olduğunu aşağıdaki resimde görebilirsiniz. Ders 96 - String Sınıfına Giriş Bu bölümde daha önce birçok yerde karşılaştığımız String sınıfını açıklayacağız. String sınıfı, karakter katarları üzerinde işlem yapmayı kolaylaştırmak için oluşturulmuştur. String, sınıfı, java.lang kütüphanesi altında bulunur ve bize karakter dizeleri üzerinde işlem yapmamızı kolaylaştıran zengin bir kütüphane sunar. Ayrıca String sınıfı metotları, immutable metodlardır. Yani bu sınıfın metodları değiştirilemez. String sınıfı miras alınarak, yeni bir sınıf türetilemez. String sınıfı metotları genel olarak karakter dizelerini karşılaştırmak, karakter dizeleri içerisinde arama yapmak, alt dizgeleri (sub-string) ayıklamak, karakter dizeleri birleştirmek ve karakterleri büyütüp küçültmek gibi işlemlerde kullanılır. String sınıfının kullanımına basit bir örnek verip daha sonra metotların kullanımını açıklayalım. //StringOrnek.java - 09.04.2014 1 2 public class StringOrnek 3 { 4 public static void main(String[] args) 5 { 6 char dizi[] = {'E', 'l', 'e', 'k', 't', 'r', 'o', 'a', 'r', 'g', 7 'e'}; 8 String katar = new String(dizi); 9 String dizge = "String sınıfını öğreniyorum"; 10 11 System.out.println(katar); 12 System.out.println("String sınıfını 13 öğreniyorum."); 14 System.out.println("JAVA " + dizge); 15 16 } 17 } 18 Ekran çıktısı: 1 Elektroarge 2 String sınıfını öğreniyorum. 3 JAVA String sınıfını öğreniyorum String sınıfı, karakter dizilerinin yaptıklarından daha fazlalarını yapabilirler. Bu yüzden String sınıfı daha fazla kullanılır. Örnekte oluşturduğumuz karakter dizisinin içeriğini bir String sınıfı nesnesine gönderdik. Daha sonra bu nesneyi ekrana yazdırdık. İlk println() metoduyla ekrana yazdırdığımız metni, ikinci println() metodundaString nesnesi yardımıyla yazdırdık. Ders 97 - String Nesnesinin Uzunluğu Bir String nesnesinin uzunluğunu, yani taşıdığı karakter sayısını bulabilmek için String sınıfının length()metodunu kullanırız. Bir örnekle bu metodu açıklayalım. //StringOrnek.java - 09.04.2014 1 2 public class StringOrnek 3 { 4 public static void main(String[] args) 5 { 6 String dizge = "String sınıfı örneği"; 7 8 int a = dizge.length(); // uzunluğu bulundu 9 System.out.println("Karakter katarının uzunluğu: " 10 + a); 11 12 } 13 } 14 15 Ekran çıktısı: Karakter katarının uzunluğu: 1 20 Örnekte de görüldüğü gibi String nesnesinin uzunluğunu length() metodu yardımıyla bulduk ve ekrana yazdırdık. Ders 98 - Karakter Katarlarını Birleştirmek Java'da karakter katarlarını (String) birleştirmek için iki yöntem kullanılır. Bunlardan en çok kullanılanı ve birincisi + operatörü yardımıyla birleştirmektir. İkincisi ise contact() metodu yardımıyla birleştirmektir. + OPERATÖRÜ İLE STRING İFADELERİ BİRLEŞTİRME Daha önce de anlattığımız bu operatör, String ifadeleri birleştirir. Ayrıca String ile bir değişkeni de birleştirebilir. Örnek verirsek: //StringOrnek.java - 09.04.2014 1 2 public class StringOrnek 3 { 4 public static void main(String[] 5 args) 6 { 7 String d1 = "String"; 8 String d2 = "Nesnesi"; 9 String d3 = d1 + d2; 10 System.out.println(d3); 11 } 12 } 13 14 Ekran çıktısı: 1 StringNesnesi Görüldüğü gibi örnekte d3 içerisinde d1 ve d2 değişkenlerinin içeriklerini + operatörü yardımıyla birleştirip sakladık. Aynı şekilde bir String ifadesi ile bir değişkeni de birleştirebiliriz. Buna da bir örnek verelim. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 //StringOrnek2.java - 09.04.2014 public class StringOrnek2 { public static void main(String[] args) { ornek o1 = new ornek(); String d1 = "Okan"; String d2 = "Bilke"; int d3 = 3; System.out.println(d1+ " " + d2 + " " + d3 + " " + o1.islem()); } } class ornek { int islem() { return 4; } } Ekran çıktısı: Okan Bilke 3 1 4 Bu örnekte bir String ile değişkeni ve aynı zamanda da metottan dönen değeri birleştirmeyi anlattık. Aralarda boşluk olması için " " ifadesini yazdık. CONCAT METODU İLE STRING İFADELERİ BİRLEŞTİRME Bir karakter katarını yani bir String'i başka bir String ile birleştirmenin diğer bir yolu da concat()metodudur. Bunun da kullanımını gösterelim. 1 //StringOrnek3.java - 09.04.2014 2 3 public class StringOrnek3 4 { 5 public static void main(String[] 6 args) 7 { 8 9 10 11 12 13 14 String d1 = "String"; String d2 = "Nesnesi"; String d3 = d1.concat(d2); System.out.println(d3); } } Ekran çıktısı: 1 StringNesnesi Örneğimizde iki String değişkenini birleştirdik. concat() metodunun farkı, yalnızca String tipindeki değişkenleri birleştirebilir. concat() metodu, referans olarak aldığı String tipteki değişkeni çağrıldığı nesnenin içeriği ile birleştirir.String nesnesi ile bir değişkeni veya integer bir değeri birleştirmek isteseydik, concat() metoduyla bu işlemi doğrudan yapmak mümkün olmayacaktı. String nesnesi ile başka tipteki bir değişkeni + operatörü yardımıyla birleştirebiliriz. Ders 99 - String Nesnelerini Karşılaştırma Java'da String nesnelerini karşılaştırırken diğer veri tiplerine göre değişik metotlar kullanırız. En önemlisi iki String metodunun birbirine eşit olup olmadığını kontrol ederken, == operatörünü String nesneleri üzerinde kullanamayız. Istisnalar: ! Java'da String tipindeki iki veriyi == operatörü ile karşılaştırdığımızda nesneleri kontrol eder. Eğer verimiz aynı, fakat nesnelerimiz farklı ise hatalı sonuç verebilir. O yüzden Java'da String tipindeki değişkenleri özel metotlar ile karşılaştırırız. Örnek verirsek: 1 String a = 2 "Mehmet"; 3 4 5 6 7 String b = "Sezer"; if(a==b) { // işlemler } Bu şekilde bir karşılaştırma hatalı sonuç verebilir. Karşılaştırma metotları ve özellikleri şu şekildedir. EQUALS VE EQUALSIGNORECASE METODLARI İLE STRİNG NESNELERİ KARŞILAŞTIRMA Java'da iki String nesnesinin birbirine eşit olup olmadığını kontrol etmek için equals() veequalsIgnoreCase() metotlarını kullanırız. equals() metodu, referans olarak aldığı String nesnesini, kendisini çağıran String nesnesiyle karşılaştırır. Eğer iki String nesnesi de aynı karakterleri aynı sırada içeriyorsa geriye true değer döndürür. İki Stringnesnesi birbirine eşit değilse false değer döndürür. Bu metot harf büyüklüğüe duyarlıdır. Yani okan ile Okanaynı değildir. equalsIgnoreCase() metodu ise equals() metodunun yaptığı işlemlerin aynısını yapar, fakat bu metodun büyük küçük harf duyarlılığı yoktur. Bu iki metodu bir örnekle daha iyi açıklayalım. 1 //StringOrnek.java - 09.04.2014 2 3 public class StringOrnek 4 { 5 public static void main(String[] args) 6 { 7 String d1 = "Edirne"; 8 String d2 = "İstanbul"; 9 String d3 = "Edirne"; 10 String d4 = "İSTANBUL"; 11 12 System.out.println(d1 + " - " + d2 + " = " + d1.equals(d2)); 13 System.out.println(d2 + " - " + d4 + " = " + d2.equals(d4)); 14 System.out.println(d1 + " - " + d3 + " = " + d1.equals(d3)); 15 System.out.println(d2 + " - " + d4 + " = " + 16 d2.equalsIgnoreCase(d4)); 17 } 18 19 } Ekran çıktısı: Edirne - İstanbul = false 1 İstanbul - İSTANBUL = 2 false 3 Edirne - Edirne = true 4 İstanbul - İSTANBUL = true Örnekte öncelikle dört tane String nesnesi (değişkeni) oluşturduk. Görüldüğü gibi ilk iki satırda equals()metodu yardımıyla String nesnelerini karşılaştırdık. İlk satırda nesnelerimiz birbirine eşit olmadığı için metodumuz false değer döndürdü. Daha sonraki satırda ise büyük küçük harfe duyarlı olan equals() metodunu kullandığımız için metodumuz geriye false değer döndürdü. Daha sonraki satırda ise büyük küçük harfe duyarlı olan equals() metodunu kullandığımız için metodumuz geriye false değer döndürdü. Diğer satırda, karşılaştırdığımız iki String nesnesi zaten birbirine eşit olduğu için metodumuz geriye truedeğer döndürdü. En son satırda ise harf duyarlılığı olmayan euqalsIgnoreCase() metodunu kullandığımız için iki String nesnemiz birbirine eşit oldu ve metot geriye true değer döndürdü. Birinde İstanbul tamamen büyük yazıldı, diğerinde ise sadece ilk harfi büyük yazıldı. Fakat bu metot ikisini de eşit olarak gördüğü için truedeğeri döndü. Tabi bu dönen değerleri, ihtiyaca göre if veya switch yapılarının içerisine koyarak başka işlemler de yaptırabiliriz. COMPARETO VE COMPARETOIGNORECASE METODLARI İLE BÜYÜKLÜK KONTROLÜ Bazı durumlarda iki String nesnesinin birbirine eşit olup olmadığından çok, hangisinin büyük olduğu veya hangisinin küçük olduğu önemlidir. Bu gibi durumlarda compareTo() ve compareToIgnoreCase() metotlarını kullanırız. Bu karşılaştırma metotları sıralama uygulamalarında büyük önem kazanır. Bir dizgenin diğer dizgeden büyük veya küçük olması demek dizgelerin sözlük sıralamalarıyla alakalıdır. Örneğin; bir isim sözcüğü oluşturduğumuzu düşünelim ve sözlüğümüze iki isim ekleyelim. Bunlar, "Sezer" ve "Sezen" olsun. "Sezen" ismi sözlükte "Sezer" isminden önce gelir, yani "Sezen" ismi "Sezer" isminden daha küçüktür. 1. compareTo() metodu; referans olarak verilen String nesnesini kendisini çağıran String nesnesi ile karşılaştırır. Eğer geriye dönen değer 0'dan büyükse; çağıran String nesnesi, referans olarak gönderilen String nesnesinden büyüktür. 2. Geriye dönen değer 0'dan küçükse (yani olumsuz ise) referans olarak gönderilen değer, çağıran Stringnesnesinden büyüktür. 3. Geriye dönen değer 0 ise iki String nesnesi birbirine eşittir. compareTo() metodu, büyük - küçük harfe karşı duyarlıdır, compareToIgnoreCase() metodu ise büyük - küçük harfe duyarlı değildir. Şimdi karşılaştırma metotlarını örnek üzerinden açıklayalım. 1 //StringOrnek2.java - 09.04.2014 2 3 public class StringOrnek2 4 { 5 public static void main(String[] args) 6 { 7 String isim1 = "Sezer"; 8 String isim2 = "SEZER"; 9 String isim3 = "Sezen"; 10 String isim4 = "SEZEN"; 11 12 System.out.print(isim1 + " ve " + isim3 + " 13 Karşılaştırması: "); 14 System.out.println(isim1.compareTo(isim3)); 15 System.out.print(isim4 + " ve " + isim1 + " 16 Karşılaştırması: "); 17 System.out.println(isim4.compareToIgnoreCase(isim1)); 18 System.out.print(isim1 + " ve " + isim2 + " 19 Karşılaştırması: "); 20 System.out.println(isim1.compareToIgnoreCase(isim2)); 21 22 23 System.out.print(isim1 + " ve " + isim2 + " Karşılaştırması: "); System.out.println(isim1.compareTo(isim2)); } } Ekran çıktısı: Sezer ve Sezen Karşılaştırması: 4 SEZEN ve Sezer Karşılaştırması: 1 -4 2 Sezer ve SEZER Karşılaştırması: 3 0 4 Sezer ve SEZER Karşılaştırması: 32 Örneğimizde karşılaştırma yaptığımız ilk satıra dikkat edelim. 1. İlk satırda "Sezer" ve "Sezen" isimlerini karşılaştırdık ve metodumuz geriye pozitif değer döndürdü. Bu metodu çağıran String nesnesinin daha büyük olduğu anlamına gelmektedir. 2. Daha sonraki satırda büyük - küçük harf duyarlılığı olmayan compareTonIgnoreCase() metodunu "SEZEN" ve "Sezer" isimlerinin karşılaştırmak için kullandık. Metodumuz, kendisini çağıran Stringnesnesinin daha küçük olduğunu belirten negatif bir değer gönderdi (-4). 3. Bir sonraki satırda aynı metodu bu sefer "Sezer" ve "SEZER" isimleri için kullandık. Harf duyarlılığı olmayan bu metot bize bu iki String nesnesinin eşit olduğunu belirten 0 değerini gönderdi. Çünkü bu metot, büyük küçük harfe duyarlı değildir. Son satırda ise compareTo() metodunu yine "Sezer" ve "SEZER" isimlerini karşılaştırmak için kullandık. Büyük - küçük harf duyarlılığı olan bu metot, bize kendisini çağıran String nesnesinin daha büyük olduğunu belirten pozitif bir değer döndürdü. "Sezer" isminin "SEZER" isminden büyük olmasının sebebi; küçük harflerin ASCII tablosunda büyük harflerden daha sonra gelmesidir. REGIONMATCHES METODU İLE BELİRLİ BİR BÖLGENİN KARŞILAŞTIRILMASI Bu metot, String nesnesi içindeki belli bir bölgeyi, referans olarak vereceğimiz String nesnesinin belli bir bölgesi ile karşılaştırmaya yarar. Metodun kullanımına örnek vererek açıklayalım. //StringOrnek3.java - 09.04.2014 1 2 public class StringOrnek3 3 { 4 public static void main(String[] args) 5 { 6 String d1 = "Ankara Türkiye'nin başkentidir."; 7 String d2 = "Türkiye"; 8 boolean b; 9 10 b = d1.regionMatches(7, d2, 0, d2.length()); 11 if(b == true) 12 { 13 System.out.println(d1 + " içerisinde aranan bölgede " + d2 + " 14 bulundu."); 15 } 16 else 17 { 18 System.out.println(d1 + " içerisinde aranan bölgede " + d2 + " 19 bulunamadı."); 20 } 21 } 22 } 23 Ekran çıktısı: Ankara Türkiye'nin başkentidir. içerisinde aranan bölgede Türkiye 1 bulundu. Örnekte d1 içerisinde belirlediğimiz indis değerinden başlayarak d2 String nesnesini karşılaştırdık. 1. Metodumuzun ilk parametresi karşılaştırmaya hangi indis değerinden başlanacağını ifade eder. 2. İkinci parametre hangi String ile karşılaştırılacağını gösterir. 3. Üçüncü parametre, karşılaştırmaya parametre olarak verilen String nesnesinin hangi indis değerinden başlanacağını gösterir. 4. Dördüncü parametre ise, karşılaştırmanın kaç karakter devam edeceğini gösterir. STARTSWITH VE ENDSWITH METODLARI İLE BAŞLANGIÇ VE BİTİŞ KONTROLÜ Bu iki metot; String nesnesinin, referans olarak verilen String ile başlayıp başlamadığını veya sonlanıp sonlanmadığını kontrol eder. startswith() metodu, metodu çağıran String nesnesi, referans olarak verilenString ile başlıyorsa true; başlamıyorsa false değer döndürür. Aynı şekilde endsWith() metodu ise metodu çağıran String nesnesi, referans olarak verilen String ile bitiyorsa geriye true; bitmiyorsa false değer döndürür. Bu iki metot için de birer örnek yaparak konuyu daha iyi anlamaya çalışalım. 1 //StringOrnek4.java - 09.04.2014 2 3 public class StringOrnek4 4 { 5 public static void main(String[] args) 6 { 7 String dizge = "Elektroarge Elektronik Arastirma Gelistirme 8 Platformu"; 9 boolean kontrol; 10 11 kontrol = dizge.startsWith("Elektroarge"); 12 System.out.println(kontrol); 13 kontrol = dizge.startsWith("lektroarg"); 14 System.out.println(kontrol); 15 kontrol = dizge.endsWith("Plat"); 16 17 18 19 20 21 System.out.println(kontrol); kontrol = dizge.endsWith("Platformu"); System.out.println(kontrol); } } Ekran çıktısı: 1 true 2 false 3 false 4 true Örnekte ilk iki kısımda String nesnemizin önce "Elektroarge" daha sonra "lektroarg" ile başlayıp başlamadığını kontrol ettik. startWith() metodumuzun ilk olarak String nesnemizin ilk karakteri ile referans olarak verdiğimiz String'in ilk karakterini kontrol eder, iki karakter de eşitse son karaktere kadar bu işlemi tekrarlar. Metodumuz iki durumda da String nesnemizin referans olarak gönderdiğimiz String ile başlayıp başlamadığını kontrol etti ve ilk durumda true; ikinci durumda ise false değer döndürdü. endsWith() metodu,startsWith() metodunun diğer formu aşağıdaki örnekte gibidir: //StringOrnek5.java - 09.04.2014 1 2 public class StringOrnek5 3 { 4 public static void main(String[] args) 5 { 6 String dizge = "Elektroarge Elektronik Arastirma Gelistirme 7 Platformu"; 8 boolean kontrol; 9 10 kontrol = dizge.startsWith("Elektroarge", 1); 11 System.out.println(kontrol); 12 kontrol = dizge.startsWith("lektroarg", 1); 13 System.out.println(kontrol); 14 } 15 } 16 17 Ekran çıktısı: 1 false 2 true Örnekte görüldüğü gibi startsWith() metoduna hangi indis değerinden karşılaştırmaya başlayacağımızı belirtebilir. İkinci metot; true değerini döndürdü. Çünkü 1. indisten karşılaştırmaya yapınca ikinci harf olan A'dan başlıyor. Ders 100 - Karakter Metodları String sınıfının metotlarıyla String nesneleri içerisindeki belli karakterleri seçmek ve bunlara işlem yaptırmak mümkündür. String nesnelerine başlarkan String nesnelerini karakter dizilerine benzetmiştik.String nesneleri, karakter dizilerinde olduğu gibi karakterleri indis değerleriyle eşleyerek kaydetmez. Ama bu dersimizde göreceğimiz bazı String metotları kendi işlerini kolaylaştırmak amacıyla karakterleri indis değerleriyle eşleyerek işlem yaparlar. GETCHARS METODU İLE STRING İÇERİSİNDEKİ BİR BÖLÜMÜ DİZİYE AKTARMA Bu metot, String nesnesi içerisindeki belli sayıda karakteri bir diziye aktarmamızı sağlar. Metodun genel kullanımı şu şekildedir: getChars(int başlangıç, int bitiş, char kaynakDizi[], int 1 kaynakIndis); Metodumuzun aldığı ilk parametre olan başlangıç parametresi String nesnesi içerisinde kopyalanmaya başlanılacak indis değerini gösterir. Aynı şekilde bitiş parametresi ise String nesnesi içerisindekopyalanmanın sonlanacağı indis değerini gösterir. kaynakDizi[] ise String nesnesi içerisinden alınan karakterlerin kopyalanacağı kaynak dizidir. Son parametre olan kaynakIndis parametremiz ise kaynak dizimiz içerisine kopyalanacak karakterlerinhangi indis değerinden sonra kopyalanması gerektiğini bildirir. Metodumuzu tam olarak anlayabilmek için şimdi bir örnek yapalım. //StringOrnek.java - 11.04.2014 1 2 public class StringOrnek 3 { 4 public static void main(String[] args) 5 { 6 String dizge = "Bu derste String nesnesinin metotlarını 7 inceliyoruz"; 8 char[] kaynakDizi = new char[6]; 9 char[] kaynakDizi2 = new char[9]; 10 char[] kaynakDizi3 = new char[11]; 11 12 dizge.getChars(10, 16, kaynakDizi, 0); 13 System.out.println(kaynakDizi); 14 dizge.getChars(17, 26, kaynakDizi2, 0); 15 System.out.println(kaynakDizi2); 16 dizge.getChars(40, 51, kaynakDizi3, 0); 17 System.out.println(kaynakDizi3); 18 } 19 } 20 21 Ekran çıktısı: 1 String 2 nesnesini 3 inceliyoruz Örneğimizde 3 adet kaynak dizi oluşturduk ve bu kaynak dizilere belli indis değerlerinden başlayarak, belli indis değerlerinde sonlanacak karakterleri kopyaladık. CHARAT METODU İLE STRING İÇERİSİNDEKİ KARAKTERE ULAŞMAK Bir String nesnesi içerisinden belli bir noktadaki tek bir karakteri seçmek istediğimizde bu metodu kullanırız. Metodu bir örnekle daha iyi açıklayalım. //StringOrnek2.java - 11.04.2014 1 2 public class StringOrnek2 3 { 4 public static void main(String[] args) 5 { 6 String alfabe = 7 "ABCÇDEFGHIİJKLMNOÖPRSŞTUÜVYZ"; 8 System.out.print("Alfabenin 10. harfi: "); 9 System.out.println(alfabe.charAt(9)); 10 System.out.print("Alfabenin 19. harfi: "); 11 System.out.println(alfabe.charAt(18)); 12 } 13 } 14 15 Ekran çıktısı: Alfabenin 10. harfi: 1 I 2 Alfabenin 19. harfi: P Yukarıdaki örnekte charAt() metodu yardımıyla içerisine alfabeyi kaydettiğimiz String nesnesinin önce 10. karakterine daha sonra 19. karakterine ulaşıp ekrana yazdırdık. Daha öncede açıkladığımız gibi metodumuz geriye tek bir karakter döndürmektedir. TOCHARARRAY METODU İLE STRING NESNEYİ KARAKTER DİZİSİNE DÖNÜŞTÜRME Bir String nesnesini karakter dizisine dönüştürmek için toCharArray() metodunu kullanırız. Bu metot,String nesnesini karakter dizisine çevirerek geriye dizi olarak döndürür. Şimdi metodun daha iyi anlaşılması için metotla ilgili bir örnek yapalım. 1 //StringOrnek3.java - 11.04.2014 2 3 public class StringOrnek3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 { public static void main(String[] args) { String dizge = "Karakter dizisine aktarılacak string"; int uzunluk = dizge.length(); // oluşturduğumuz string nesnesinin uzunluğunda bir karakter dizisi oluşturduk. char[] karakterDizisi = new char[uzunluk]; // string nesnemizi karakter dizisine çevirdik ve char tipinde diziye attık. karakterDizisi = dizge.toCharArray(); for(int a = 0 ; a <= dizge.length() - 1 ; a++) System.out.print(karakterDizisi[a]); } } Ekran çıktısı: Karakter dizisine aktarılacak 1 string Yukarıdaki örnekte oluşturduğumuz String nesnesinin içeriğini, karakter dizisine çevirip, daha sonradan oluşturduğumuz karakter dizisine atadık. for döngüsü yardımıyla karakter dizimiz içerisindeki tüm elemanları yazdırdık. İsteseydik, bu dizinin tamamını değil de belirli bir kısmını yazdırabilirdik. Bunu for döngüsündekidizge.length() - 1 koduyla ayarladık. Gördüğünüz gibi bu metot, bir String'i diziye çeviriyor. String'in her harfi, dizinin bir elemanı oluyor. INDEXOF VE LASTINDEXOF METODLARI İLE STRING İÇERİSİNDE KARAKTER ARAMA String sınıfı, bize String içerisinde karakterleri arayabilmemiz için bu iki metodu sunar. indexof(), Stringnesnesi içerisinde aranılan karakterin ilk bulunduğu indis değerini verir. lastIndexOf() ise String nesnesi içerisinde aranılan karakterin son bulunduğu indis değerini verir. Her iki metot için de aranılan eleman bulunursa, indis değeri döndürülür; aranılan eleman bulunamazsa geriye negatif değer döndürür. Bu iki metodu anlayabilmek için bir örnek yapalım. //StringOrnek4.java - 11.04.2014 1 2 public class StringOrnek4 3 { 4 public static void main(String[] args) 5 { 6 String dizge = "Bu arama yapabilmek için test 7 cümlesidir"; 8 9 System.out.print("'a' karakteri için ilk indis: "); 10 System.out.println(dizge.indexOf("a")); 11 System.out.print("'a' karakteri için son indis: "); 12 System.out.println(dizge.lastIndexOf("a")); 13 System.out.print("'arama' kelimesi için ilk indis: "); 14 System.out.println(dizge.indexOf("arama")); 15 System.out.print("'deneme' kelimesi için son indis: 16 "); 17 System.out.println(dizge.lastIndexOf("deneme")); 18 } 19 } 20 Ekran çıktısı: 'a' karakteri için ilk indis: 3 1 'a' karakteri için son indis: 12 2 'arama' kelimesi için ilk indis: 3 3 'deneme' kelimesi için son indis: 4 -1 Yukarıdaki örnekte görüldüğü gibi aranılan karakter veya String, çağırılan String nesnesi içerisinde bulunursa indis değeri geriye döndürülüyor. Aranılan değer bulunamazsa, negatif değer döndürülüyor. Aranılacak parametreyi tırnak içerisinde veriyoruz. Görüldüğü gibi "denem" kelimesini bulamadı ve negatifdeğer döndürdü. Bu iki metodun istenilen bir noktadan sonra arama yapabilmek için aşırı yüklenmiş formu bulunmaktadır. Aranılacak değer referans olarak verildikten sonra, ikinci parametre olarak aramaya başlanılacak indis değeri giriliyor. Bu kısma da kısa bir örnek vererek konuyu sonlandıralım. //StringOrnek4.java - 11.04.2014 1 2 public class StringOrnek5 3 { 4 public static void main(String[] args) 5 { 6 String dizge = "Bu arama yapabilmek için test 7 cümlesidir"; 8 9 System.out.print("'a' karakteri için ilk indis: "); 10 System.out.println(dizge.indexOf("a")); 11 System.out.print("'a' karakteri için son indis: "); 12 System.out.println(dizge.lastIndexOf("a", 8)); 13 System.out.print("'i' karakteri için son indis: "); 14 System.out.println(dizge.lastIndexOf("i")); 15 System.out.print("'i' karakteri için ilk indis: "); 16 System.out.println(dizge.lastIndexOf("i", 37)); 17 } 18 } 19 20 Ekran çıktısı: 'a' karakteri için ilk indis: 3 1 'a' karakteri için son indis: 2 7 3 'i' karakteri için son indis: 4 38 'i' karakteri için ilk indis: 36 Ders 101 - String Düzenleme Metodları Java'da String nesnelerini düzenlemek için belirli metotlara ihtiyaç duyarız. Düzenleme metotlarından bazıları ve bu metotların kullanımlarını bu bölümde anlatacağız. SUBSTRING METODU İLE STRING İÇERİSİNDEN BİR BÖLÜM SEÇME Bu metot String nesnesinin belli bir bölümünü seçmek için kullanılır. Metodun genel kullanımı aşağıda gösterildiği gibidir. String : substring (int ilkIndis, int 1 sonIndıs) Metodun ilk parametresi olan ilkIndis parametresi, String nesnesi içerisinde karakterlerin seçilmeye başlanacağı indis değerini gösterir. İkinci parametre olan sonIndis parametresi ise, String nesnesi içerisinden karakter seçilmesinin sonlanacağı indis değerini gösterir. //StringOrnek.java - 09.04.2014 1 2 public class StringOrnek 3 { 4 public static void main(String[] args) 5 { 6 String dizge = "Bu örnek substring metodunun kullanımı için 7 yapıldı."; 8 String altDizge = ""; 9 String altDizge2 = ""; 10 11 // alt dizgelerimize string nesnesi içerisinden belirtilen karakterleri 12 atadık. 13 altDizge = dizge.substring(9, 18); 14 altDizge2 = dizge.substring(29, 38); 15 16 System.out.println(altDizge); 17 System.out.println(altDizge2); 18 } 19 } 20 Ekran çıktısı: 1 substring 2 kullanımı Yukarıdaki örnekte oluşturduğumuz String nesnesi içerisinden belli kısımları substring metodu yardımıyla seçtik ve diğer String nesnelerimize bu değerleri atadık. REPLACE METODU İLE STRING İÇERİSİNDEKİ KARAKTERİ DEĞİŞTİRME Bu metot, String nesnesi içerisinde belirtilen karakterleri başka karakter ile değiştirmeye yarar. Metodun genel kullanımı aşağıdaki gibidir: String : replace(char orjinalKarakter, 1 chardegistirilenKarakter); Metodumuzun aldığı ilk parametre olan orjinalKarakter parametresi, String nesnesi içerisindeki değiştirilmek istenen karakterdir. İkinci parametre degistirilenKarakter parametresi ise String nesnesi içerisindeki orjinalKarakter ile değiştirilecek karakteri belirtir. Metodun kullanımına bir örnek yapalım: 1 //StringOrnek2.java - 09.04.2014 2 3 public class StringOrnek2 4 { 5 public static void main(String[] args) 6 { 7 String dizge = "Bu örnek substring metodunun kullanımı için 8 yapıldı."; 9 String dizge2 = ""; 10 11 System.out.println("String nesnemizin orjinal hali: "); 12 System.out.println(dizge); 13 14 15 16 17 18 19 20 21 22 // string nesnemiz içerisindeki tüm 'e' karakterleri 'o' ile değiştirildi. dizge2 = dizge.replace('e', 'o'); // replace metodunu "dizge" adındaki değişken üzerinden kullandık System.out.println("String nesnemizin değiştirilmiş hali: "); System.out.println(dizge2); } } Ekran çıktısı: String nesnemizin orjinal hali: 1 Bu örnek substring metodunun kullanımı için 2 yapıldı. 3 String nesnemizin değiştirilmiş hali: 4 Bu örnok substring motodunun kullanımı için yapıldı. Örnekte oluşturduğumuz String nesnesi içerisindeki tüm 'e' karakterlerini 'o' karakteri ile değiştirmek içinreplace() metodunu kullandık. Metodu kullanırken, hangi String üzerinde işlem yapacaksak, replacemetodunu o String ile kullanmalıyız. TRIM METODU İLE STRING İFADENİN YANINDAKİ BOŞLUKLARI SİLME Bu metot, String nesnemizin sağındaki ve solundaki boşlukları silerek düzenlenmiş bir kopyasını döndürür. Metodun kullanımına örnek yaparak metodu daha iyi açıklayalım. 1 //StringOrnek3.java - 09.04.2014 2 3 public class StringOrnek3 4 { 5 public static void main(String[] args) 6 { 7 String dizge = " Bu cümlenin başındaki ve sonundaki 8 boşluklar 9 T rim metoduyla silinecektir. "; 10 11 12 13 14 15 16 17 18 System.out.println("String nesnesinin orjinal hali: "); System.out.println(dizge); System.out.println("String nesnemizin düzenlenmiş hali: "); System.out.println(dizge.trim()); } } Ekran çıktısı: String nesnesinin orjinal hali: 1 Bu cümlenin başındaki ve sonundaki boşluklar trim metoduyla 2 silinecektir. 3 String nesnemizin düzenlenmiş hali: 4 Bu cümlenin başındaki ve sonundaki boşluklar trim metoduyla silinecektir. Örneğimizde önce başında ve sonunda üç karakterlik boşluk bulunan bir String nesnesi oluşturduk. Daha sonra ekran çıktısından da olduğu gibi bu nesnemizin başındaki ve sonundaki boşlukları trim() metodu yardımıyla sildik. TOUPPERCASE VE TOLOWERCASE METODLARI İLE HARF KİPİNİ DEĞİŞTİRME Bu iki metot, String nesnesi içerisindeki harflerin kipini değiştirmek için kullanılırlar. toUppercase()metodu, String nesnemiz içerisindeki harfleri büyük harfler ile değiştirir. toLowerCase() metodu ise Stringnesnemiz içerisindeki harfleri küçük harfleri ile değiştirmek için kullanılır. 1 //StringOrnek4.java - 09.04.2014 2 3 public class StringOrnek4 4 { 5 public static void main(String[] args) 6 { 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 String dizge = "Bu ÖrNeK HaRf KiPi DeğişiMi MeToTlaRı içiN Yapıldı."; String kucuk = ""; String buyuk = ""; System.out.println("String nesnesinin orjinal hali: "); System.out.println(dizge); buyuk = dizge.toUpperCase(); System.out.println("Büyük harf kipi ile String nesnesi: "); System.out.println(buyuk); kucuk = dizge.toLowerCase(); System.out.println("Küçük harf kipi ile String nesnesi: "); System.out.println(kucuk); } } Ekran çıktısı: String nesnesinin orjinal hali: 1 Bu ÖrNeK HaRf KiPi DeğişiMi MeToTlaRı içiN Yapıldı. 2 Büyük harf kipi ile String nesnesi: 3 BU ÖRNEK HARF KİPİ DEĞİŞİMİ METOTLARI İÇİN 4 YAPILDI. 5 Küçük harf kipi ile String nesnesi: 6 bu örnek harf kipi değişimi metotları için yapıldı. VALUEOF METODU İLE VERİ TİPLERİNİ STRING VERİ TİPİNE ÇEVİRME Bu metot, Java'da veri tiplerini String tipine çevirmek için kullanılır. Metot aldığı parametreyi, geriyeString tipinde gönderir. Metodun hangi tipte veriler üzerinde kullanıldığını görmek için bir örnek yapalım. 1 //StringOrnek5.java - 11.04.2014 2 3 public class StringOrnek5 4 { 5 public static void main(String[] args) 6 { 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int i = 10; float f = 11.f; double d = 12.d; long l = 100000000; char c = 'c'; boolean b = false; Object o = new String("Deneme"); String s = ""; // değişik tipteki verileri string tipine çeviriyoruz. s = String.valueOf(i); s = s + "-" + String.valueOf(f); s = s + "-" + String.valueOf(d); s = s + "-" + String.valueOf(l); s = s + "-" + String.valueOf(c); s = s + "-" + String.valueOf(b); s = s + "-" + String.valueOf(o); System.out.println(s); } } Ekran çıktısı: 10-11.0-12.0-100000000-c-false1 Deneme Yukardaki örnekte değişik tipte verileri String tipine çevirmek için valueOf() metodunu kullandık. Daha sonra String tipine çevirdiğimiz bu verileri bir String nesnesi içerisinde birleştirdik. Alt satırlara doğru indikçe çığ tipi toplanarak giden bir s değişkenimiz var. Bu değişken, son satırda bütün metot sonuçlarını kendi üzerinde birleştirmiştir. Ders 102 - StringTokenizer ve StringBuffer Sınıfları Bu dersimizde String sınıfının dışında kullanılan ve belli başlı işlemleri yapan iki sınıfımızı inceleyeceğiz. Bunlar StringTokenizer ve StringBuffer sınıflarıdır. STRINGTOKENIZER SINIFINI KULLANARAK METNİ PARÇALAMA Bir String ifademizi parçalamak isteyebiliriz. Mesela; uzun bir cümlemiz var ve biz bu cümle içerisinden kelimeleri almak istiyoruz. Bunun için StringTokenizer sınıfını kullanmamız gerekir. StringTokenizer sınıfı, bir String ifadeyi belirli bir parametreye göre parçalar. Eğer uzun bir cümlemiz varsa, biz bu cümlede parametre olarak boşluk verirsek, ifademiz her boşlukta parçalara ayrılır. Ayrılan her parçaya token denir. Parçalama işlemini yapacak olan parametreye delimeter denir. Şimdi bir örnek yapalım ve konumuza örnek üzerinden devam edelim. //Tokenizer.java - 11.04.2014 1 2 import java.util.StringTokenizer; 3 public class Tokenizer 4 { 5 public static void main(String[] args) 6 { 7 String cumle = "Yenilirsen Değil Vazgeçersen 8 Kaybedersin"; 9 StringTokenizer s1 = new StringTokenizer(cumle); 10 while(s1.hasMoreTokens()) 11 // parçalanacak ifade varsa; true değeri döner ve döngü 12 işlenir 13 { 14 System.out.println(s1.nextToken()); // parçayı yazdır 15 } 16 } 17 } 18 Ekran çıktısı: 1 Yenilirsen 2 Değil 3 Vazgeçersen 4 Kaybedersin 1. Örneğimizde ilk olarak import işlemi yaptık. Çünkü StringTokenizer sınıfını kullanabilmek için bu sınıfıimport etmemiz gerekiyor. 2. Daha sonra main içerisinde bir cümle belirledik. 3. Sonra da StringTokenizer sınıfından bir nesne oluşturduk. Parametre olarak da StringTokenizersınıfının yapıcısına cumle değişkenini verdik. Yani bu değişken üzerinde parçalama işlemi yapılacak. 4. while döngümüzde bu s1 nesnesi üzerinden hasMoreTokens() metodunu çağırdık. Bu metot, parçalanacak bir ifade kalıp kalmadığını kontrol eder. 5. Eğer hala parçalanacak bir ifade varsa, döngü döner ve döngü içerisinde de s1 üzerinden nextToken()metodu çağırılır. Bu metot da her seferinde parçalanan bir ifadeyi döndürür. Bu örneğimizde boşluklara göre parçalama yaptık. Normalde StringTokenizer sınıfının yapıcısına cümlenin yanında hangi karaktere göre parçalama yapacağımızı da verirdik. Fakat bu örnekte vermedik. Çünkü boşluk ifadesi default parametredir. Biz boşluk değil de mesela - karakterine göre parçalama yapmak istersek, cümlenin yanına bu parametreyi de ekleriz. Şimdi bu anlattığımıza örnek verelim. 1 //Tokenizer2.java - 11.04.2014 2 3 import java.util.StringTokenizer; 4 public class Tokenizer2 5 { 6 public static void main(String[] args) 7 { 8 String cumle = "ElektroArge-Elektronik-Arastirma-Gelistirme9 Platformu"; 10 String bolucu = "-"; 11 StringTokenizer s1 = new StringTokenizer(cumle, bolucu); 12 while(s1.hasMoreTokens()) 13 // parçalanacak ifade varsa; true değeri döner ve döngü işlenir 14 { System.out.println(s1.nextToken()); // parçayı yazdır 15 16 17 18 19 } } } Ekran çıktısı: 1 ElektroArge 2 Elektronik 3 Arastirma 4 Gelistirme 5 Platformu Yukarıdaki örneğimizde bolucu adında bir değişken tanımladık. Yani "cümlemizde bu değişkenin değerini gördüğün her yerde ayırma yap". Bu sefer cümlemizde aralarda - ifadesi koyduk ki bunu gördüğü her yerdeayırma yapsın, yani token'lara bölsün. Istisnalar: ! StringTokenizer sınıfının yaptığını, split() metodunun yaptığı işe benzetebiliriz. Başka bir örnek verelim. 1 //Tokenizer3.java - 11.04.2014 2 3 import java.util.StringTokenizer; 4 public class Tokenizer3 5 { 6 public static void main(String[] args) 7 { 8 String cumle = "ElektroArge,-Elektronik-,Arastirma-Gelistirme9 ;Platformu"; 10 String bolucu = ",;"; 11 StringTokenizer s1 = new StringTokenizer(cumle, bolucu); 12 while(s1.hasMoreTokens()) 13 { 14 System.out.println(s1.nextToken()); 15 } 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 } 33 } 34 System.out.println("*********************"); String bolucu2 = "-;"; StringTokenizer s2 = new StringTokenizer(cumle, bolucu2); while(s2.hasMoreTokens()) { System.out.println(s2.nextToken()); } System.out.println("*********************"); String bolucu3 = "a"; StringTokenizer s3 = new StringTokenizer(cumle, bolucu3); while(s3.hasMoreTokens()) { System.out.println(s3.nextToken()); } Ekran çıktısı: 1 ElektroArge 2 -Elektronik3 Arastirma-Gelistirme4 Platformu 5 ********************* 6 ElektroArge, 7 Elektronik 8 ,Arastirma 9 Gelistirme 10 Platformu 11 ********************* 12 ElektroArge,-Elektronik-,Ar 13 stirm 14 -Gelistirme-;Pl 15 tformu Yukarıdaki örneğimizde 3 farklı bölme parametresi kullandık ve her biri için çıkan sonucu gösterdik. Örnekte bir istisna vardır, o da şu: İlk örnekte kesme işlemini yapan bolucu parametremiz ,; ifadesinden oluşuyor. Cümlemizde de ilk olarakvirgül(,) ifadesi aranıyor. Eğer bu ifade varsa kesme yapılıyor. Eğer yoksa bu sefer noktalı virgül(;) ile arama yapılıyor. Peki, bu istisna neden var? Çünkü bir cümlede birçok noktalama işareti varsa, bu noktalama işaretleri parametremize uygun bir şekilde verilir ve tüm kelimeler elde edilir. Hemen bir örnek daha yapalım. //Tokenizer4.java - 11.04.2014 1 2 import java.util.StringTokenizer; 3 public class Tokenizer4 4 { 5 public static void main(String[] args) 6 { 7 String cumle = "(3*5)+(4/10)"; 8 String bolucu="((*+/"; 9 StringTokenizer s1 = new StringTokenizer(cumle, 10 bolucu); 11 while(s1.hasMoreTokens()) 12 { 13 System.out.println(s1.nextToken()); 14 } 15 System.out.println("*************"); 16 String bolucu2 = "(*)+/"; 17 StringTokenizer s2 = new StringTokenizer(cumle, 18 bolucu2); 19 while(s2.hasMoreTokens()) 20 { 21 System.out.println(s2.nextToken()); 22 } 23 } 24 } 25 Ekran çıktısı: 1 3 2 5) 3 4 4 10) 5 ************* 6 3 7 5 8 4 9 10 Yukarıdaki örnekte bir matematiksel işlem var ve biz bu işlemdeki sayıları elde etmeye çalışıyoruz. Bunun için 2 tane bölücü ifade kullandık. Örnekte yalnızca bu iki kesme parametresi farklı. Bunu da şunun için yaptık. Cümlemizde hangi sıradaysa, biz de bölücümüzde o sırada yapmak zorundayız. Alttaki bölücüde uygun sıraya göre yazdık ve tüm sayıları saf haliyle elde ettik. İlk bölücüde (delimeter) sırasını farklı yaptık ve yanlış sonuç aldık. Cümledeki noktalama işaretleri de bu şekilde sıraya göre yapılmalıdır. StringTokenizer kullanırken token yerine element kullanılarak da aynı işi yapabiliriz. Bunun için sadece metotlarımızda değişiklik yaparız. Örnek üzerinde gösterelim. //Tokenizer5.java - 12.04.2014 1 2 import java.util.StringTokenizer; 3 public class Tokenizer5 4 { 5 public static void main(String[] args) 6 { 7 String cumle = "C:\\Windows\\System32"; 8 String bolucu = ":\\"; 9 StringTokenizer s1 = new StringTokenizer(cumle, 10 bolucu); 11 while(s1.hasMoreElements()) 12 { 13 System.out.println((String)s1.nextElement()); // 14 cast 15 } 16 } 17 } 18 Ekran çıktısı: 1 C 2 Windows 3 System32 Bu örneğimizde yalnızca hasMoreElements() ve nextElement() metotlarını değiştirdik. String tipinde cast etmemizin sebebi ise; üretilen sonucu String tipinde almamız gerektiğidir. Peki, cümlemizi pars ettik yani parçalara ayırdık ve ayrılan bu parçaları yani token'ların sayısını elde etmek istersek, ne yapmamız gerekir? Tabi klasik olarak sayaç ile yapabiliriz. Fakat bunun için hazırlanmış bir metodumuz var onu kullanalım ve örnek üzerinde gösterelim. //Tokenizer6.java - 12.04.2014 1 2 import java.util.StringTokenizer; 3 public class Tokenizer6 4 { 5 public static void main(String[] args) 6 { 7 String cumle = "Java dersleri için en önemli kaynak 8 elektroarge.com"; 9 StringTokenizer s1 = new StringTokenizer(cumle); 10 11 System.out.println(s1.countTokens()); 12 while(s1.hasMoreTokens()) 13 { 14 System.out.println((String)s1.nextToken()); 15 } 16 } 17 } 18 19 Ekran çıktısı: 1 7 2 Java 3 dersleri 4 için 5 en 6 önemli 7 kaynak 8 elektroarge.com Örneğimizde boşluk parametresine göre parsing işlemi yaptık. Elde edilen token sayısını isecountTokens() metodu ile bulduk. Fakat bu metodu, while döngüsünden önce yazdık. Eğer sonra yazarsak, hep 0 sayısını elde edeceğiz. STRINGBUFFER SINIFI İLE BAZI METİN İŞLEMLERİ Java'da String veri tipi, diğerlerinden farklıdır. String bir veri üzerinde birçok işlem yapılabilir ve bunlarString sınıfının metotları ile yapılır. Bir String tipindeki veriye ekleme çıkarma gibi işlemleri kitabımızın başında anlatmıştık. + operatörü kullanılarak, karakter katarları üzerinde ekleme işlemi yapılabiliyordu. Şimdi basit bir ekleme işlemi yapalım. 1 String ad = "Okan"; 2 ad += " Bilke "; 3 System.out.println(ad); Bu işlem sonucunda bize "Okan Bilke" ifadesi dönecektir. Fakat burada yapılan her ekleme işleminde aslında arkaplanda StringBuffer sınıfı kullanılır. Biz ekleme işlemi yaptığımızda aslında StringBuffer sınıfının ekleme görevi gören metotlarıyla bu işlem yapılır. Bu ekleme işlemini yapan metot, append() metodudur. Şimdi yukarıdaki örneği StringBuffer sınıfını kullanarak yapalım. 1 //StringBufferSinifi.java - 12.04.2014 2 3 public class StringBufferSinifi 4 { 5 public static void main(String[] args) 6 { 7 StringBuffer s = new StringBuffer("Okan"); 8 s.append("Bilke"); 9 System.out.println(s); 10 } 11 } 12 13 Ekran çıktısı: 1 OkanBilke StringBuffer sınıfından bir nesne oluşturduk ve ilk değer olarak bir String ifade girdik. Daha sonra oluşturulan nesne üzerinden append() metodunu çağırdık ve s nesnemizin sonuna eklenecek ifadeyi girdik. Daha sonra bu s nesnesini ekrana yazdırdık. Aslında ilk örneğimizde bu işlemler oluştu. Biz sadece sonucu gördük. Fakat bu işlemler arkaplanda StringBuffer sınıfı ile yapıldı. String ifadelere yalnızca String değil, başka tiplerde de veri ekleme yapabiliyorduk. Yine aynı şekildeStringBuffer sınıfını kullanarak, bu sefer başka tiplerde de eklemeler yapalım. Ayrıca her ekleme işlemini tek bir satırda yapalım. 1 //StringBufferSinifi2.java - 12.04.2014 2 3 public class StringBufferSinifi2 4 { 5 public static void main(String[] args) 6 { 7 StringBuffer s = new StringBuffer("x"); 8 s.append("--").append(55).append(5.1); 9 System.out.println(s); 10 } 11 } 12 13 Ekran çıktısı: 1 x--555.1 Bu örneğimizde s nesnesi oluşturduk ve ilk değer olarak x verdik. Daha sonra bu nesne üzerinden 3 defa arka arkaya append() metodunu çağırdık ve bu metot içerisine istediğimiz tipte verileri ekledik. Çünküappend() metodu, Object sınıfından aşırı yüklenmiştir ve tüm tipleri alabilir. Son olarak da bu nesnemizi ekrana yazdırdık. Bu nesne String tipinde olduğu için doğrudan ekrana yazdırabiliyoruz. StringBuffer sınıfının append() metodunun işlevini gördük. Bundan başka metotlar da vardır. Mesela; indisleri verilen yere bir ifade ekleyebiliriz. Bunu replace() metodu ile yaparız. Ayrıca indisi verilen yere istenilen değeri yerleştirebiliriz. Örnek verirsek; 1 //StringBufferSinifi3.java - 12.04.2014 2 3 public class StringBufferSinifi3 4 { 5 public static void main(String[] args) 6 { 7 8 9 10 11 12 13 14 15 16 17 StringBuffer s = new StringBuffer("Okan"); s.append("Bilke"); // ElektroArGe elde edilir. s.replace(0, 4, "Onur"); // yer değiştirme System.out.println(s); s.insert(4, "Okan"); // ekleme System.out.println(s); } } Ekran çıktısı: 1 OnurBilke 2 OnurOkanBilke Yukarıdaki örnekte ilk olarak ekleme yapıp OkanBilke metinin elde ettik. Daha sonra replace()metodunu kullanarak 0 ile 4. indisler arasını "Onur" metniyle değiştirdik ve sonucu ekrana yazdırdık. Son olarak da bu yeni metin üzerinden insert() metodunu kullanarak 4. indisten itibaren "Okan" metnini ekledik ve sonucu yazdırdık. Son olarak StringBuffer sınıfından 2 metot daha inceleyelim. Bunlar silme işlemi yapan delete() ve metni tersine çeviren reverse() metotlarıdır. 1 //StringBufferSinifi4.java - 12.04.2014 2 3 public class StringBufferSinifi4 4 { 5 public static void main(String[] args) 6 { 7 StringBuffer s = new 8 StringBuffer("Okan"); 9 s.append("Bilke"); 10 s.delete(0, 4); // silme işlemi yapar 11 System.out.println(s); 12 13 s.reverse(); // metni tersine döndürür 14 System.out.println(s); 15 } 16 } 17 Ekran çıktısı: 1 Bilke 2 ekliB Yukarıdaki örneğimizde de delete() ile 0. ve 4. indisler arasındaki bölgeyi sildik. Daha sonra kalan metnin, yani s nesnesinin reverse() ile tersini aldık. JAVA DİLİYLE PROGRAMLAMA Part II Ders 103 - Exceptions (İstisnalar) İstisnalar veya orjinal isimleriyle Exception'lar, kod blokları arasında oluşan anormal durumlardır. En basit olarak bir örnek vermek gerekirse; bir sayıyı sıfıra bölme bir istisnai durumdur veya bir diziye boyutundan fazla eleman atamak, sayı girilmesi istendiği durumda bir String girmek birer istisnai durumdur. Bu gibi durumlarda derleyici hata verecektir. Exception'lar hata tipi, hata oluştuğunda uygulamanın durumu ve hata hakkında açıklayıcı bir takım bilgiler içerir. Exception'lar sayesinde hata yakalamak ve sorunu çözmek daha da kolaylaşır. Yukarıda söylediklerimizin dışında, açık bir dosya üzerinde yazma işlemi yapıldığında, dosyanın gösterilen adreste olmaması gibi durumlarda da hata ile karşılaşılacaktır. Bunlar da bir diğer istisnalardır. Bir öğrenci not sistemi uygulaması yaptınız diyelim. Java'nın tüm üstünlüklerini kullandınız, fakat öğrenci not yerine yanlışlıkla adını girerse ne olacak? Eğer bu girilen veriyi kontrol etmezseniz çalışırken birden bire hata oluşacak ve programınız çalışmayacaktır. Sıradaki derslerimiz, bu şeklide programınızda oluşabilecek hataları nasıl kontrol edeceğinizi anlatmaktadır. Programınızda oluşabilecek bu tür hatalara sebebiyer verecek şeyler birer istisnadır. Peki, bu şekilde istisnalar ile karşılaşırsak ne yapmamız gerekir? Bundan sonraki derslerimizde bunun çözümüne değinilecektir. Ders 104 - Hata Yakalama (Try - Catch Blokları) Önceki dersimizde anlattığımız istisnalardan 0'a bölme konusuna bir örnek verelim. Dersimizi örnek üzerinden detaylı bir şekilde anlatalım. 1 //Trycatch.java - 12.04.2014 2 3 public class Trycatch 4 { 5 public static void main(String[] 6 args) 7 { 8 int a = 10; 9 10 11 12 13 14 15 16 int b = 0; int c; c = a / b; System.out.println("Sonuc: " + c); } } Ekran çıktısı: Exception in thread "main" java.lang.ArithmeticException: / 1 by zero 2 at Trycatch.main(Trycatch.java:11) Çıktımızda da görüldüğü gibi programımız çalışma zamanında bir hata verecektir. Derleyicinin vereceği hata, java.lang.ArithmeticException hatasıdır. Java, hatalar konusunda çok sıkı davranır ve hataları anında kullanıcıya gösterir. Geliştireceğiniz kodlarda hata her zaman bu kadar basit ve anlaşılır olmayacaktır. Hatayı anlayıp ayıklayabilmek için try-catch bloğu kullanmalıyız. Bu try-catch bloğu sayesinde, hata ile karşılaştığımızda ne yapmamız gerekir veya hata olsa da olmasa da programımızda neler yaptırmak istiyoruz, bunları programımıza anlatabiliriz. Temel try - catch bloğu kullanımı aşağıdaki gibidir: try 1 { 2 // istisnai durum kontrolü yapacak kod 3 } 4 catch (Exception_türü e) 5 { 6 // (Exception_türü) hatası durumunda 7 çalışacak kod 8 } 9 finally 10 { 11 // hata alınsa da alınmasa da çalışacak kod 12 } Hata oluşma ihtimali olan kodumuzu try bloğu içerisine alırız. try bloğu çalıştığında eğer bir hata olursacatch bloğuna girilir. Hangi türde bir hata olduysa bu hata ekrana yazdırılır. Burada tanımlananException_türü tipindeki e nesnesi bize hata hakkında bilgiler verir. Yukarıdaki bölme örneğini şimdi de try - catch bloğu yardımıyla yapalım. //Trycatch2.java - 12.04.2014 1 2 public class Trycatch2 3 { 4 public static void main(String[] args) 5 { 6 int a = 10; 7 int b = 0; 8 int c; 9 try 10 { 11 c = a / b; 12 System.out.println("Sonuc: " + c); 13 } 14 catch (ArithmeticException ae) 15 { 16 System.out.println("Bir hata ile karşılaşıldı: " + 17 ae.toString()); 18 } 19 } 20 } 21 22 Ekran çıktısı: Bir hata ile karşılaşıldı: java.lang.ArithmeticException: / 1 by zero Yukarıdaki örnekte görüldüğü gibi derleyici değişkenlere atamaları yaptıktan sonra try bloğunu işleme alıyor. Biz diyoruz ki "Bölme işlemine bak, burada bir hata olabilir." O yüzden hata olabilecek yerleri try içerisine aldık. Bu kodda bir hatamız var. Bu bölme işleminde, sıfıra bölme hatasıyla karşılaşıldığı anda catch bloğuna geçip hata mesajımızı gösteriyor. Normalde derleyici hata ile karşılaştığında programı durdururdu ve bir hata mesajı verirdi. Biz bu catch içerisinde diyoruz ki programı durdurma, kullanıcıya hatayı göster. Hata mesajımızın ilk bölümü hatanın tipi ile ilgilidir. İkinci bölüm ise hatanın neden kaynaklandığı ile ilgilidir. Burada ilk bölüm olan hatanın tipi ArithmeticException'dır. Hatanın neden kaynaklandığı ise, ae nesnesinin içerisinde saklıdır. Biz ae nesnesini ae.toString() ile ekrana yazdırarak hatanın sebebini öğreniriz. Istisnalar: Eğer catch bloğunda tanımladığımız hata tipi ile karşılaştığınız hata ! tipi uyuşmuyorsa, muhtemelen hatayı yakalayamayacaksınız. Bu gibi durumlarda catch bloğunda genel hata tipi (Exception) tanımlamak veya birden fazla catch bloğu bulundurmak hatayı yakalamanızı kolaylaştıracaktır. Notumuzda şunu demek istiyoruz: Yukarıda ilk bölüm hatanın tipidir demiştik. Bu hatanın tipi kısmınaException yazarak bunu önleyebiliriz. Bu, bütün hata tiplerini kapsar, genel hata tipidir. Şimdi hata yakalamaya başka bir örnek verelim. //Trycatch3.java - 12.04.2014 1 2 public class Trycatch3 3 { 4 public static void main(String[] 5 args) 6 { 7 int dizi[] = new int[]{1, 3, 8, 23, 8 44}; 9 System.out.println(dizi[6]); 10 } 11 } 12 Ekran çıktısı: Exception in thread "main" 1 java.lang.ArrayIndexOutOfBoundsException: 6 2 at Trycatch3.main(Trycatch3.java:8) Bu örnekte dizimizin 6. indisli elemanını ekrana yazdırmak istiyoruz. Fakat dizimizde 6. indis bulunmamaktadır. Dolayısıyla olmayan bir elemana erişmek hata verecektir. Yukarıdaki çıktıda hatamızın sebebi yazmaktadır. java.lang.ArrayIndexOutOfBoundsException hatamızın sebebidir. Yani dizideki indeksin dışında bir elemana erişmeye çalıştık. Peki, bunu try catch blokları ile nasıl kontrol altına alacağız? //Trycatch4.java - 12.04.2014 1 2 public class Trycatch4 3 { 4 public static void main(String[] args) 5 { 6 int dizi[] = new int[]{1, 3, 8, 23, 44}; 7 try 8 { 9 System.out.println("Try bloğu 10 içerisindeyiz"); 11 System.out.println(dizi[6]); 12 } 13 catch (ArrayIndexOutOfBoundsException 14 a) 15 { 16 System.out.println(a.toString()); 17 } 18 } 19 } 20 Ekran çıktısı: Try bloğu içerisindeyiz 1 java.lang.ArrayIndexOutOfBoundsException: 2 6 Hata olabilecek bir ifade olan dizi[6] ifadesi try içerisine yazıldı. Bir hata oluştuğunda ise; hatanın sebebicatch içerisine yazıldı. Eğer try catch kullanmasaydık, program çalışmayacaktı, fakat şimdi programımız çalıştı. Hatta çalıştığını görmek için "Try bloğu içerisindeyiz" yazısını da ekledik ve çıktıda da gördük. Eğer try - catch kullanmasaydık bu mesajı dahi göremeyecektik, çünkü program hatay bulunca çalışmayacaktı. catch bloğu içerisinde hatamızın sebebini yazdırmak yerine, herhangi bir String ifadesi de yazdırabiliriz. Hemen bir örnek verelim. //Trycatch5.java - 12.04.2014 1 2 public class Trycatch5 3 { 4 public static void main(String[] args) 5 { 6 int dizi[] = new int[]{1, 3, 8, 23, 44}; 7 try 8 { 9 System.out.println("Try bloğu 10 içerisindeyiz"); 11 System.out.println(dizi[6]); 12 } 13 catch (ArrayIndexOutOfBoundsException 14 a) 15 { 16 System.out.println("Hata oluştu"); 17 } 18 } 19 } 20 Ekran çıktısı: Try bloğu 1 içerisindeyiz 2 Hata oluştu Bu örnekte a nesnesi üzerinden hatanın sebebini yazdırmak yerine kendi belirlediğimiz bir ifadeyi yazdırdık. try - catch ile hata yakalamaya bir örnek daha verelim. Önce hatamıza sebep olacak bir örnek verelim. Daha sonrada try - catch ile programımızı kontrol edelim. 1 //Trycatch6.java - 12.04.2014 2 3 import java.util.Scanner; 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Trycatch6 { public static void main(String[] args) { Scanner s = new Scanner(System.in); System.out.println("Vize notunuzu girin:"); int vize = s.nextInt(); System.out.println("Vize notunuz: " + vize); } } Ekran çıktısı: Vize notunuzu girin: 1 50Okan 2 Exception in thread "main" 3 java.util.InputMismatchException 4 at java.util.Scanner.throwFor(Unknown Source) 5 at java.util.Scanner.next(Unknown Source) 6 at java.util.Scanner.nextInt(Unknown Source) 7 at java.util.Scanner.nextInt(Unknown Source) 8 at Trycatch6.main(Trycatch6.java:11) Biz bu örnekte Scanner sınıfını kullanarak kullanıcıdan vize notunu girmesini istedik. Bu girilen değer inttipinde bir değişkene atandı. Fakat kullanıcı yanlışlıkla bir String ifade girerse bu hataya sebep olacaktır ve programımız çalışmayacaktır. Şimdi try - catch ile bu hatamızı kontrol altına alalım ve programımız hemen durmasın çalışmaya devam etsin. 1 //Trycatch7.java - 12.04.2014 2 3 import java.util.Scanner; 4 5 public class Trycatch7 6 { 7 public static void main(String[] args) 8 { 9 int vize; 10 Scanner s = new Scanner(System.in); 11 12 System.out.println("Vize notunuzu 13 girin:"); 14 try 15 { 16 vize = s.nextInt(); 17 } 18 catch (Exception e) 19 { 20 System.out.println("Bir hata oluştu:"); 21 System.out.println(e.toString()); 22 System.out.println("Vize notu 23 alınamadı"); 24 } 25 } } Ekran çıktısı: 1 Vize notunuzu girin: 2 54asd 3 Bir hata oluştu: 4 java.util.InputMismatchException 5 Vize notu alınamadı Kullanıcıdan değer aldığımız metodu try içerisine yazdık. Hata ile karşılaşıldığında e nesnesi üzerinden hatamızın sebebi yazdırıldı. Biz bu sebebi yazdırmanın yanında kendimiz de bir mesaj yazdırdık. try - catchkullanarak, programımızın tabiri caizse patlamasını engelledik. Hata oluşsa da program çalışır, birden durmaz. Diyelim ki kpss puanı hesaplayan bir programımız var. Bu programda eğer biz kullanıcıdan doğru veyanlış sayısını alırken try içerisinde kontrol ettirmezsek programımız donar ve hata verir. Eğer bu kontrolü yaparsak hata yakalandığı anda kullanıcıya şöyle bir mesaj gösterebiliriz (Lütfen bir sayı girin). Böyle bir mesaj verdiğimizde kullanıcı istediği kadar String bir veri girsin, bu mesaj hep görüntülenecektir ve program çalışmayacaktır. Try - catch ifadesini bir metod içerisinde de kullanabiliriz. 1 //Trycatch8.java - 12.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class Trycatch8 { public static void main(String[] args) { Trycatch8 nesne = new Trycatch8(); nesne.hataYakala(); } public void hataYakala() { String dizi[] = new String[]{"Okan", "Bilke"}; try { System.out.println("Dizinin 1.elamanı: " + dizi[0]); System.out.println("Dizinin 2.elemanı: " + dizi[1]); System.out.println("Dizinin 3.elemanı: " + dizi[2]); } catch (Exception e) { System.out.println("Dizi yazdırılırken hata oluştu, oluşan hata: "); System.out.println(e.toString()); } } } Ekran çıktısı: Dizinin 1.elamanı: Okan 1 Dizinin 2.elemanı: Bilke 2 Dizi yazdırılırken hata oluştu, oluşan hata: 3 java.lang.ArrayIndexOutOfBoundsException: 4 2 Hata kontrolünü, bir metot içerisinde yaptık. Dizinin elemanlarını yazdırırken ilk 2 elemanı yazdı, fakat son ifadede hata verdi. Çünkü 2. indisimiz bulunmamaktadır. Hatamız oluştuğunda da e nesnesi üzerinden hatamızı yazdırdık. Eğer try - catch kontrolü yapmasaydık, ilk iki elemanı da yazdırmayacaktı doğrudan program hata verecekti. Istisnalar: ! JavaSE-7 ile gelen yenilikle beraber catch bloğu içerisinde, oluşabilecek hatalar tek satırda tanımlanabiliyor. Bunu ileriki derslerimizde detaylı olarak anlayacağız. Ders 105 - Finally Bloğu Programımızda hata ile karşılaştığımızda yapmamız gereken şeyi önceki dersimizde öğrendik. Şimdi ise başka bir bloktan bahsedeceğiz. try catch bloklarında bir takım işlemler yaptık. Hata yakalandığında catchiçerisine işlemlerimizi yazdık. Peki, hata yakalansa da yakalanmasa da yapılmasını istediğimiz şeyleri nereye yazacağız? Daha sonra göreceğimiz io, yani dosyaya yazma ve dosyadan veri okuma işlemlerinde hata olsa da olmasa da dosyamızı kapatmamız gerekir. finally bloğu genelde bu işlemler için kullanılır. Başka bir örnek verirsek, veritabanı işlemlerinde veritabanı bağlantı işlemlerini try içerisinde yaparız. Eğer bir hata olsa da olmasa da veritabanı ile olan bağlantımızı kapatırız. Biz bu IO konularına değinmediğimiz için normal bir örnek üzerinde anlatalım. Bir örnek üzerinde görelim. 1 //Finally.java - 12.04.2014 2 3 public class Finally 4 { 5 public static void main(String[] args) 6 { 7 int dizi[] = new int[]{4, 3, 6}; 8 try 9 { 10 System.out.println(dizi[0]); 11 System.out.println(dizi[1]); 12 System.out.println(dizi[2]); 13 System.out.println(dizi[-2]); // hata oluşacak 14 } 15 catch (Exception e) 16 { 17 System.out.println(e.toString()); 18 19 20 21 22 23 24 25 26 27 } finally { System.out.println("Burası finally bloğu"); System.out.println("Hata olsa da olmasa da bu bloğa girildi"); } } } Ekran çıktısı: 4 1 3 2 6 3 java.lang.ArrayIndexOutOfBoundsException: 4 -2 5 Burası finally bloğu 6 Hata olsa da olmasa da bu bloğa girildi Programımızda try içerisinde görüldüğü gibi bir hata oluşacak. Hata oluştuğunda hatamızın türünü ekrana yazdırdık. Hata olsa da olmasa da finally bloğuna girildi. Bu bloğu yazmak zorunlu değildir tabi. Bu blokta ne varsa, program çıktısında aynen gösterilir. Dediğimiz gibi bu finally bloğunda genelde açık olan dosyalar ve veritabanı bağlantıları kapatılır. Çünkü açık olan bir dosya üzerinde işlem yaparsak, hata ile karşılaşırız. Istisnalar: ! JavaSE-7 ile gelen yenilikle beraber, finally bloğunda kapatılması gereken dosyalar, try bloğunda belirtiliyor. Bu konu detaylı olarak ileriki derslerimizde incelenecektir. Ders 106 - Finally Bloğunda Try - Catch Kullanımı finally bloğu içerisinde tekrar bir try - catch bloğu yazabiliriz. Bunu iç içe yazdığımız if ifadeleri gibi düşünebiliriz. Bununla ilgili bir örnek yapalım. 1 //Finally.java - 12.04.2014 2 3 public class Finally 4 { 5 public static void main(String[] args) 6 { 7 int dizi[] = new int[]{4, 3, 6}; 8 try 9 { 10 System.out.println(dizi[4]); 11 } 12 catch (Exception e) 13 { 14 System.out.println(e.toString()); 15 } 16 finally 17 { 18 try 19 { 20 System.out.println(dizi[1]); 21 } 22 catch (Exception e1) 23 { 24 System.out.println(e1.toString()); 25 } 26 } 27 } 28 } 29 30 Ekran çıktısı: java.lang.ArrayIndexOutOfBoundsException: 1 4 2 3 İlk try içerisinde hata ile karşılaştığımız için catch bloğuna girildi ve hatamız ekrana yazdırıldı. Daha sonra her şartta girilmesi gereken finally bloğuna girildi. Bu blok içerisindeki try bloğunda da bir ifade yazdırdık. Fakat burada bir hata olmadığı için dizi[1] ifadesini ekrana yazdırdı. Bu yöntem de yine aynı şekilde dosyada okunacak veri kalmadıysa dosyanın kapatılması gibi işlemlerde kullanılır. Ders 107 - Birden Fazla Hata Yakalama Uygulama geliştirirken bazen bir kod bloğu arasında birden fazla hata tipiyle karşılaşabiliriz. Bu gibi durumlar için birden fazla catch bloğu tanımlamak daha uygundur. Bu sayede uygulamamız hata tiplerine karşı daha duyarlı hale gelecektir. Genel Yapısı: try 1 { 2 // hata kontrolü yapılacak kod 3 } 4 catch (Hata_türü1 e) 5 { 6 // Hata_türü1 hatası olduğunda çalışacak 7 blok 8 } 9 catch (Hata_türü2 e) 10 { 11 // Hata_türü2 hatası olduğunda çalışacak 12 blok } Yukarıdaki gibi tanımladığımız ikinci catch bloğu sayesinde kod bloğu, Hata_türü2 tipindeki hatalara da duyarlıu hale geldi. Örnekteki gibi daha fazla catch bloğu tanımlamamız mümkündür. Bunu switch yapısına benzetebiliriz. Hangisine uyarsa, o catch bloğuna girer. Bir örnek verelim: 1 //CokluHataYakalama.java - 12.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.io.*; public class CokluHataYakalama { public static void main(String[] args) { char veriler[] = new char[1000]; File f = new File("C:\\Kitap\\hatayakalama.txt"); // dosya adresi verildi try { FileReader fr = new FileReader(f); fr.read(veriler); // dosyadan veri okuma yapıldı String veri = new String(veriler); System.out.println(veri); } catch (IOException e) // bu bloğa girilecektir { System.out.println("Hata oluştu: "); System.out.println(e.toString()); } catch (ArrayIndexOutOfBoundsException e2) { System.out.println("Hata oluştu: "); System.out.println(e2.toString()); } } } Ekran çıktısı: Hata oluştu: 1 java.io.FileNotFoundException: C:\Kitap\hatayakalama.txt (Sistem belirtilen yolu 2 bulamıyor) İleriki derslerimizde anlatacağımız dosya okuma ve yazma işlemleri ile ilgili bir örnek verdik. En yukarıda belirttiğimiz adreste öyle bir dosya bulunmamaktadır. O yüzden bu dosyadan bir veri okuyamayız. Dolayısıyla ilk catch bloğuna girecektir. Çünkü io, yani giriş çıkış ile ilgili bir hata aldık. Eğer bunlardan önce, indeksi olmayan bir dizinin elemanına erişmeye çalışsaydık,o zaman 2. catch bloğuna girecekti. Ders 108 - Throw Anahtar Kelimesi Geliştirici uygulamanın herhangi bir yerinde kendisi Exception verebilir ve daha sonra throw kelimesiyle fırlattığı bu Exception'u başka bir yerde kullanabilir. Örnek olarak yine 0'a bölme örneğine bakalım. 1 //ThrowKullanimi.java - 12.04.2014 2 3 import java.util.Scanner; 4 5 public class ThrowKullanimi 6 { 7 public static int sayiBol (int sayi1, int sayi2) 8 { 9 if (sayi2 == 0) 10 { 11 throw new ArithmeticException("İkinci sayı 0(sıfır)'dan farklı 12 olmalı"); 13 } 14 int sonuc = sayi1 / sayi2; 15 return sonuc; 16 } 17 18 public static void main(String[] args) 19 { 20 Scanner sc = new Scanner(System.in); 21 try 22 { 23 System.out.println("İlk sayıyı giriniz"); 24 int a = sc.nextInt(); 25 System.out.println("İkinci sayıyı giriniz");; 26 int b = sc.nextInt(); 27 int sonuc; 28 sonuc = sayiBol(a, b); 29 System.out.println("Sonuc: " + sonuc); 30 } 31 catch (NullPointerException ne) 32 { 33 System.out.println(ne.toString()); 34 35 36 37 } } } Ekran çıktısı: İlk sayıyı giriniz 1 3 2 İkinci sayıyı giriniz 3 0 4 Exception in thread "main" java.lang.ArithmeticException: İkinci sayı 5 0(sıfır)'dan farklı olmalı 6 at ThrowKullanimi.sayiBol(ThrowKullanimi.java:11) 7 at ThrowKullanimi.main(ThrowKullanimi.java:27) Yukarıdaki örnekte görüldüğü gibi uygulama önce sayıların girilmesini bekliyor. Sayılar girildikten sonrasayiBol metoduna referans olarak ekliyor. sayiBol metodu içerisinde payda 0 ise; ArithmeticExceptionveriyor ve main metodundaki try - catch bloğu, bu hatayı yakalıyor. sayiBol() metodumuzun içerisinde oluşan hataya göre hata mesajı yazabiliyoruz. Eğer hata olmazsa if koşuluna zaten girmeyecek ve program normal akışında ilerleyecektir. Ders 109 - Throws Anahtar Kelimesi Bazı metotlar, içerisinde hata oluşturabilecek bir kod içerir. Önceki derslerimizde öğrendiğimiz yöntemlerde biz hata oluşabilecek kodları try catch içerisine alıyorduk ve bir hata verdiğinde, onu kontrol altına alarak programın durmasını engelliyorduk. Peki, biz hatamızı o metot içerisinde değil de başka bir yerde kontrol edebilir miyiz? Bir örnek verelim ve onun üzerinden anlatalım. 1 //ThrowKelimesi.java - 21.04.2014 2 3 public class ThrowsKelimesi 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 { public void metod1() { int dizi[] = new int[] {2, 5, 4}; try { System.out.println("Burası metod1'dir"); System.out.println(dizi[3]); } catch (Exception e) { System.out.println(e.toString()); } } public void metod1Cagir() { System.out.println("Burası metod1'i çağırır"); metod1(); } public static void main(String[] args) { ThrowsKelimesi t1 = new ThrowsKelimesi(); t1.metod1Cagir(); } } Ekran çıktısı: Burası metod1'i çağırır 1 Burası metod1'dir 2 java.lang.ArrayIndexOutOfBoundsException: 3 3 1. metod1() içerisinde hataya sebep olabilecek bir işlem yaptık ve hata verildi. Biz bu hatayı Exceptionhata tipi ile kontrol ettik. Bu örnekte hangi hatanın vereceğini biliyoruz, fakat eğer bilmemiş olsaydık genel olarak Exception hata tipini kullanırdık. Çünkü o bize çıktıda zaten hangi hatadan kaynaklandığını söyleyecektir. 2. Bu metod1'i metod1Cagir() adlı metot içerisinden çağırdık. main metodumuzda da bu sınıftan bir nesne oluşturup metod1Cagir() adlı metodu çağırdık. 3. Ekran çıktımız tahmin ettiğimiz gibi oldu. metod1() çağırılana kadar herşey normal, fakat metod1()'in içerisine girildiğinde bir hata ile karşılaşıldı ve verilen hata nesnesi üzerinden toString() metodu çağırılarak hatamızın sebebi yazdırıldı. Gördüğümüz gibi hatanın tipini Exception olarak verdik, fakat çıktımızda hatamızın tipini ArrayIndexOutOfBoundsException olarak verdi. Yani hatamızın sebebiniException tipini kullanarak da öğrenebiliriz. Şimdi gelelim asıl konumuza... Yukarıdaki örnekte hata kontrolü, içinde bulunulan metot tarafından gerçekleştirildi. Peki, biz hata kontrolünü burada yapmak istemiyorsak ne yapmalıyız? Bunun için yapmamız gereken, hata kontolünü metodumuzun çağırıldığı yerde yapmaktır. Metodun çağırıldığı yerde try - catch mekanizması kurulur. Hatamızın oluşabileceği metotta ise throwsanahtar kelimesi kullanılır. Bu anahtar kelime sayesinde, metot içerisinde bir hata oluştuğunda hatayı içeren nesne, çağırıldığı metoda aktarılır. Yukarıdaki örneği bir de throws anahtar kelimesi ile yapalım. 1 //ThrowKelimesi2.java - 21.04.2014 2 3 public class ThrowsKelimesi2 4 { 5 public void metod1() throws Exception 6 { 7 int dizi[] = new int[] {2, 5, 4}; 8 System.out.println("Burası metod1'dir"); 9 System.out.println(dizi[3]); 10 } 11 12 public void metod1Cagir() 13 { 14 System.out.println("Burası metod1'i çağırır"); 15 try 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 { metod1(); } catch (Exception e) { System.out.println(e.toString()); } System.out.println("Metod1 çağırıldı"); } public static void main(String[] args) { ThrowsKelimesi2 t1 = new ThrowsKelimesi2(); t1.metod1Cagir(); System.out.println("metod1Cagir() metodu çağırıldı"); } } Ekran çıktısı: Burası metod1'i çağırır 1 Burası metod1'dir 2 java.lang.ArrayIndexOutOfBoundsException: 3 3 4 Metod1 çağırıldı 5 metod1Cagir() metodu çağırıldı Hemen açıklamasını yapalım. 1. metod1() içerisinde bir try - catch kullanmadık. Throws anahtar kelimesini, metot adından sonra yazdık ve oluşabilecek hata tipini de en sona yazdık. Yani ifademiz şu şekilde oldu. public void metod1() throws 1 Exception 2. Bunu yaparak "Eğer bu metodda bir hata oluşursa, hatayı bir üst metoda aktar. Bizi çağıran metot bu hata ile ilgilensin." dedik. 3. Bunu çağıran metod1Cagir() metodunda ise try - catch kontrolünü kurduk. Bu kontrolün içerisinde de metodumuzu çağırdığımız satırı ekledik. Eğer bir hata olursa da e nesnesi üzerinden bu hatayı yazdırdık. Bu e nesnesi, aslında metod1'e ait bir nesnedir. Yani oradaki hatanın bilgilerini tutar. 4. main() metodumuzda da, yani programımızın başladığı metotta da bu metod1Cagir() metodunu çağırdık. Çağırdıktan sonra da bir String yazdırdık. Görüldüğü gibi hata oluşsa da bu metin ekrana yazıldı. Yani bu da demek oluyor ki programımız çökmedi. throws anahtar kelimesinin kullanılma amacı budur. Hangi metottaki bir hatayı bir üst metoda fırlatmak istiyorsak, o metodu throws ile işaretlemeliyiz. Eğer metot içerisinde throws ile işaretlenmiş metodu çağırırken Exception'u yakalamak istemiyorsanız, o metodu da throws anahtar kelimesi ile işaretlemeniz gerekir. Burada önemli olan throws ile işaretlediğiniz her fonksiyonu ya try - catch bloğu arasında çağıracaksınız ya da throws ile işaretlenmiş metodu çağırdığınız metodu da throws anahtar kelimesi ile işaretleyeceksiniz. Örneğin; public class sinif 1 { 2 public void fonksiyon() throws 3 Exception 4 { 5 // hata oluşturabilecek kodlar 6 } 7 8 public void fonksiyon2() throws 9 Exception 10 { 11 fonksiyon(); 12 } } Yukarıda görüldüğü gibi throws anahtar kelimesi ile işaretlenmiş fonksiyon, fonksiyon2 tarafından çağırılıyor ve fonksiyon2 hatayı yakalamayacağını throws anahtar kelimesiyle belirtiyor. Yani fonksiyon2 de hatayı kontrol etmeyip, kendini çağıran metoda aktarıyor. fonksiyon2'yi çağıran fonksiyonu da throwsanahtar kelimesi ile işaretlemeliyiz veya try catch bloğu ile hatayı yakalamalıyız. Örneğin: //ThrowKelimesi3.java - 21.04.2014 1 2 public class ThrowsKelimesi3 3 { 4 public void metod1() throws Exception 5 { 6 int dizi[] = new int[] {2, 5, 4}; 7 System.out.println("Burası metod1'dir"); 8 System.out.println(dizi[3]); 9 } 10 11 public void metod2() throws Exception 12 { 13 System.out.println("Burası metod2'dir"); 14 metod1(); 15 } 16 17 public static void main(String[] args) 18 { 19 ThrowsKelimesi3 t1 = new ThrowsKelimesi3(); 20 try 21 { 22 t1.metod2(); 23 } catch (Exception e) 24 { 25 System.out.println(e.toString()); 26 } 27 System.out.println("Main metodunda hata kontrolü 28 yapıldı"); 29 } 30 } 31 32 Ekran çıktısı: Burası metod2'dir 1 Burası metod1'dir 2 java.lang.ArrayIndexOutOfBoundsException: 3 3 4 Main metodunda hata kontrolü yapıldı Bu örnekte metod1 içerisinde oluşan hata, throws ile çağırıldığı yer olan metod2'ye fırlatıldı. metod2 de bu hatayı kabul etmeyip throws ile çağırıldığı yere verdi. Bu metot da main içerisinden çağırıldığı için mecburenmain metodunda try - catch kullanmak zorunda kaldık. Yani metod1'de kontrol edilmesi gereken hata, fırlatılarak son nokta olan main içerisinde kontrol edildi. Buradaki e nesnesi de, metod1'deki hatadır. Fırlatıldığı zaman hata ile ilgili bilgileri bünyesinde taşımıştı. Eğer main içerisinde de kontrol etmeseydik programımız zaten hiç çalışmayacaktı. throws anahtar kelimesini kullanırken unutulmaması gereken, bir diğer önemli nokta ise işaretlenen hata tipidir. İlk işaretlediğimiz fonksiyon metodu Exception hata tipiyle işaretlenmişti. Dolayısıyla bu metodu çağıran metotlar bu hata tipine karşı duyarlı olmak zorunda veya kendisini de bu hata tipine karşı throwsanahtar kelimesi ile işaretlemelidir. Ders 110 - Exception Türü Oluşturma Java kütüphanelerinde birçok hata türüne karşı hata tipi tanımlanmıştır. Ancak bazı durumlarda özel hata tipi tanımlamamız gerekebilir. Bu hatanın anlaşılabilirliğini artıracak ve çözüm üretmemizi daha da kolaylaştıracaktır. Böyle durumlarda Exception sınıfını miras alan bir alt sınıf türetmemiz gerekecektir. Örneğin: 1 //hataTipim.java - 21.04.2014 2 3 public class hataTipim extends Exception 4 { 5 String hataMetni = "Özel hata tipi"; 6 String hataTipi = "hataTipim"; 7 8 public void hataTipim() 9 { 10 // yapıcı metod 11 } 12 13 public String toString() 14 { 15 hataMetni += String.format(" : " + hataTipi); 16 // toString metodu ile hata ile ilgili bilgiler 17 gönderilir 18 return hataMetni; 19 } 20 } 21 Yukarıdaki örnekte görüldüğü gibi hataTipim isminde bir hata tipi tanımladık. Hata metnini göndermek için diğer Exception sınıflarında da olduğu gibi toString() metodunu kullanmak yeterli olacaktır. //sinif.java - 21.04.2014 1 2 public class sinif 3 { 4 public void fonksiyon() throws 5 hataTipim 6 { 7 throw new hataTipim(); 8 // metod içerisine yazılacak kodlar 9 } 10 } 11 12 Sınıf içerisinde metodumuzu throws anahtar kelimesi ve kendi hata tipimizle işaretledik. 1 //Throws.java - 21.04.2014 2 3 public class Throws 4 { 5 public static void main(String[] args) 6 { 7 sinif nesne = new sinif(); 8 try 9 { 10 nesne.fonksiyon(); 11 } 12 catch (hataTipim ht) 13 { 14 System.out.println(ht.toString()); 15 } 16 } 17 } 18 19 En son olarak sınıf içerisinde kendi hata tipimizle işaretlediğimiz metodu try catch bloğu yardımıyla hatayı yakalamaya zorlamamız gerekiyor. Böylece kendi hata tipimizi tanımlamış olduk. Hata tipi içerisinde kullanılan metotlar, sadece toString() metodu ile sınırlı değildir. Exception sınıflarının kullandığı ortak metotlar vardır. Bunları da hata sınıfımız içerisinde kullanabiliriz. Hata mesajlarını elde etmede kullanabileceğimiz bazı Exception sınıfı ortak metotları şunlardır: String getMessage(): Oluşan hata ile ilgili bilgiyi içeren mesajı gönderir. Ancak hatanın tipi ile ilgili bilgi içermez. String toString(): Oluşan hata ile ilgili detaylı bilgi içeren mesajı gönderir. Gönderilen mesaj içerisinde hata tipi ":" işareti ve hata mesajı bulunmaktadır. String getLocalizedMessage(): Oluşan hata ile ilgili yerel bir mesaj gönderir. getMessage()metodundan farkı alt Exception sınıfları bu metodu override yaparak hata mesajını yerelleştirebilirler. Void printStackTrace(): Oluşan hatanın sebebi ve hatanın hangi satırda oluştuğu ile ilgili bilgiyi konsola yazdırır. Ders 111 - Hata Türleri Bazı hata türlerinin ne anlama geldiğini bilmek işimizi kod yazarken daha da kolaylaştıracaktır. Bilgiğimiz gibi hatalar, tiplerine göre ayrılmaktadır. En çok karşılaşılan bazı hata türleri ve açıklamaları şöyledir: 0'a bölme gibi mantıksal matematik hatalarında oluşur. Dizinin indeksinin aşılması durumunda oluşur. Diziye boyutundan fazla eleman ArrayIndexOutOfBoundsException yüklemek veya dizinin olmayan indeksine erişmek başlıca yapılan hatalardır. Herhangi bir nesne değişkenine ilk değer atanmadan kullanılmaya çalışılırsa NullPointerException oluşur. Oluşturulmamış bir dosyaya erişim FileNotFoundException durumunda bu hata meydana gelir. Karakteri okuyamamak gibi genel IOException giriş/çıkış hataları. Sayı girilmesi gereken yerde karakter NumberFormatException girilmesi durumunda oluşur. Diziye kendi türü dışında veri girilmesi ArrayStoreException durumunda oluşur. (tip uyuşmazlığı) Herhangi bir nesne değişkenine farklı tip ClassCastException değer girilmesi durumunda oluşur. String'de var olmayan bir indekse StringIndexOutOfBoundsException erişilmeye çalışılması durumunda oluşur. ArithmeticException Java'da bütün hata tipleri Throwable hata tipinden türemişlerdir. Biz programlarımızda, hangi tür hatanın verilebileceğini bilmediğimiz için her hatayı Exception tipinde belirledik. Diyelim ki throws ile bir hata nesnesini, çağırıldığı metoda aktardık. Bu metotta hata nesnemizi yakalayabilmek için kullanmamız gereken hata tipi, hatanın olduğu tipi kapsamalıdır. Bunu örnek ile şöyle açıklayalım. 1 //ThrowsKelimesi.java - 21.04.2014 2 3 public class ThrowsKelimesi 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { public void metod1() throws Exception { int x = 0, y = 4; System.out.println(y / x); } public void metod2() { try { metod1(); } catch (ArithmeticException e) { System.out.println(e.toString()); } } public static void main(String[] args) { ThrowsKelimesi nesne = new ThrowsKelimesi(); nesne.metod2(); } } Ekran çıktısı: Exception in thread "main" java.lang.Error: Unresolved compilation 1 problem: 2 Unhandled exception type Exception 3 4 at ThrowsKelimesi.metod2(ThrowsKelimesi.java:15) 5 at ThrowsKelimesi.main(ThrowsKelimesi.java:26) Örneğimizde hatamızı Exception tipi ile verdik. Fakat bu hatayı kontrol ederken ArithmeticException ile kontrol etmeye çalıştık. Bu hata verecektir. Çünkü yakalamaya çalıştığımız ArithmeticException tipi, aktardığımız Exception tipinden daha az kapsamlıdır. Yakalamaya çalıştığımız tipin daha kapsamlı olması gerekir. O yüzden diğerleri kapsayan tip olan Exception tipi ile biz programlarımızdaki hataları yakalamaya çalıştık. Bütün hata tiplerinden yola çıkarak programımızda oluşan hataları 2 grupta toplayabiliriz. Şimdi bunları inceleyelim. RUNTIMEEXCEPTION HATA TÜRÜ Runtime kavramını, diğer programlama dillerinden de duymuş olabilirsiniz. İsminden de anlaşılacağı üzereruntime exception hataları, çalışma zamanında meydana gelen hatalardır. Diyelim ki programımız normal akışında ilerliyor. Kullanıcı int tipinde veri girmesi gereken yerde Stringtipinde bir veri girdi. Biz bu girilen değeri değişkene atadığımız yerde try - catch kullanmadıysak, program çalışırken hata verecektir. Bunlar Runtime Exception hatası olarak bilinir. Yani çalışma sırasında oluşan hatalardır. Derleme anında da hatalar oluşabilir. Java, derleme hatasında oluşabilecek hatalara karşı bizi uyarmaz. Yazılımcının, yazdığı kodlara dikkat etmesi gerekir. Yazdığımız bazı kodları mutlaka try - catch içerisine yazmamız gerektiğini söyleyecektir. Mesela; dosya bağlantılarında try - catch koymamızı ister. Fakat çalışma anında oluşan hatalar için Java, önceden bir uyarı vermez. Programın akışında bu hataya rastladığında hatasını verir. Yani kullanıcının girdiği veriyi int değişkenine atsın dediğimizde, burada hata yoktur. KullanıcıString değer girerse program çalışırken hata verir. ÇÖZÜLEMEYEN HATALAR (ERROR) Bu tür hatalar için verilebilecek en önemli örnek, belleğin yetmediği durumlardır. Bu tür hataları ne kadartry - catch içerisine alsak da hatayı çözemeyiz. Bazen bellekte gereksiz yere kullanılmayan nesneler bulunur. Bu kullanılmayan nesneler de, bu tür hatalara sebep olabilir. Ders 112 - I/O Kavramına Giriş Giriş çıkış işlemleri genelde, bir dosyadan verileri okumak veya bir dosyaya verileri yazmak için kullanılır. Dosyalar arasında veri aktarımı yapmanın dışında ağ üzerinden de bunu gerçekleştirebilir. Biz bu dosyadan okuma ve dosyaya yazma işlemlerini konsol üzerinden anlatacağız. Normalde giriş çıkış işlemleri için applet'ler kullanılsa da bunu da öğrenmekte fayda var. Çok kullanılan bir yapı olmasa bile verileri text üzerinde tutmak için kullananlar vardır. Verileri depolamak, istenildiğinde çekip okumak, başka bir dosyaya yazmak için de kullanılır Giriş çıkış işlemleri için kullanmamız gereken paket java.io paketidir. Yazacağımız programlarda bu paketiimport etmemiz gerekiyor. Bu paketin içerisinde ileriki derslerimizde anlatacağımız sınıflar bulunur. Konsol ile çalıştığımız için bu paketi kullanıyoruz. Okuma yazma işlemleri için konsol dışındaki yöntemleri kullanırsak başka bir paket ile çalışmalıyız. Son zamanlarda yeni geliştirilen NIO (java.nio) paketi ile, daha ileri düzeyde ve daha performanslı giriş çıkış işlemleri yapılabilmektedir. Java'da giriş çıkış işlemleri Stream mantığı ile yapılır. Akım anlamına gelen Stream, programımız ile dosya arasında köprü görevi görür. Yani bir nevi verilerin iletildiği kanaldır. Java'da veri aktarım işlemlerini, karakter bazlı ve byte bazlı olarak ikiye ayırabiliriz. Karakter bazlı aktarım işlemi, verileri karakter halinde taşır. Unicode desteği vardır. Yani diğer alfabeleri destekler. Byte bazlı aktarım işleminde ise karakter toplulukları halinde aktarım yapılır. Bu yöntem, karakter bazlı aktarıma göre daha performanslıdır. KARAKTER TABANLI VERİ TAŞIMA Karakter tabanlı veri iletimi, Writer ve Reader sınıfları ile yapılır. Bu sınıflar da kendi içerisinde alt sınıflara ayrılır. Karakter tabanlı işlemlerde Unicode desteği vardır. Reader sınıfı kendi içinde alt sınıflara ayrılır. Bunlardan bazıları: InputStreamReader BufferedReader FileReader FilterReader StringReader Writer sınıfı kendi içerisinde alt sınıflara ayrılır. Bunlardan bazıları: OutputStreamWriter BufferedWriter FileWriter FilterWriter StringWriter PrintWriter Bu sınıflarla çalışmak için her bir sınıfı ayrı ayrı import etmek gerekir. Bunun yerine java.io.* sınıfınıimport ederek bütün sınıfları kullanabiliriz. Bu alt sınıflardan birkaçını anlatacağız. Konu başlığı altında detaylarına ineceğiz. BYTE TABANLI VERİ TAŞIMA Byte tabanlı veri iletimi InputStream ve OutputStream sınıfları ile yapılır. Java'daki tüm sınıflar Objectsınıfından türediği için bu sınıflar da Object sınıfından türemişlerdir. Byte tabanlı işlemlerde Unicode desteği yoktur. InputStream kendi içinde alt sınıflara ayrılır. Bunlardan bazıları: BufferedInputStream DataInputStream FilterInputStream PrintStream RandomAccessFile FileInputStream OutputStream de kendi içerisinde alt sınıflara ayrılır. Bunlardan bazıları: BufferedOutputStream DataOutputStream FileOutputStream FilterOutputStream Bu sınıflarla çalışmak için her bir sınıfı ayrı ayrı import etmek gerekir. Bunun yerine java.io.* sınıfınıimport ederek bütün sınıfları kullanabiliriz. Biz örneklerimizde her iki yolu da kullandık. Istisnalar: ! Byte ve karakter tabanlı işlemlerde kullanılan sınıfların isimleri size karışık gelmiş olabilir. Eğer read ve writekelimeleri varsa, o sınıf karakter tabanlı işlem yapar. OutputStream veya InputStream ile bitiyorsa byte tabanlı işlem yapar. Istisnalar: ! Her iki yöntemde de buffer kullanılır. Türkçesi tampon olan buffer, verileri aktarırken bir ara katmandır. Veriler yazılmadan veya okunmadan önce burada tutulur. Istisnalar: ! Bir dosya üzerinde işlem yaptıktan sonra o, dosyayı kapatmadan tekrar o dosya üzerinde bir işlem yapmak istersek hata alabiliriz. Ders 113 - File Sınıfının Kullanımı Bu sınıf, bilgisayar üzerindeki bir dosyanın bilgilerine erişmeyi sağlar. File sınıfını bilgisayar üzerindeki herhangi bir dosya ile ilişkilendirerek, bu dosya hakkında birçok bilgiye ulaşırız. Bu sınıfın yapıcısına, işlem yapacağımız dosya veya klasörün path adresini veririz. Bu path, dosyanın bilgisayar üzerindeki adresidir. Kullanımı: File f = new File("Dosya 1 Yolu"); File sınıfının f adında bir nesne oluşturduk. Dosya işlemleri bu nesne üzerinden yapılır. Parantezler içerisine de işlem yapılacak dosyanın yolu verilmelidir. Bu File sınıfı, dosya ve klasörler için kullanılır. Örnek bir dosya yolu verelim: 1 C:\elektroarge\java\io.txt; 2 D:\Resimler\manzara.jpg; Windows işletim sisteminde klasör adları birbirinden \ ile ayrılırken, Linux ortamında / ile ayrılırlar. Biz Windows üzerinde çalıştığımız için \ kullandık. Ayrıca yukarıda tek \ ile ayırdık. Programlarımızda çift \\ ile ayırma yapacağız. Çünkü bir String ifadesinde \ koyduğumuzda Eclipse bunu boşluk bırakma, alt satırda inme gibi işaretler olarak algılıyor. Dosyamızın ya da klasörümüzün yolunu, doğrudan yapıcıya göndermek yerine bir String nesnesine atıp, o nesneyi de gönderebiliriz. Örnek verirsek: String dosyaYolu = 1 "C:\\elektroarge\\java.txt; 2 File f = new File(dosyaYolu); Şimdi bu f nesnesi üzerinden erişebileceğimiz metotlardan bazılarına bakalım. Bu metotlar, dosyamız üzerinde bazı kontrolleri yapar. Istisnalar: ! Buradan sonraki anlattığımız konularda, parametre olarak verdiğimiz path değişkeninde belirtilen dosyayı, önceden sizin kendi bilgisayarınızın o dizininde oluşturduğunuzu varsayıyoruz. CREATENEWFILE METODU İLE DOSYA OLUŞTURMA Bu metot, belirtilen adreste yeni bir dosya oluşturur. Örnek verirsek: 1 //FileSinifi.java - 21.04.2014 2 3 import java.io.File; 4 import java.io.IOException; 5 6 public class FileSinifi 7 { 8 public static void main(String[] args) 9 { 10 File f = new File("C:\\elektroarge\\ornek2.txt"); 11 try 12 { 13 14 15 16 17 18 19 20 21 22 f.createNewFile(); // yeni dosya oluşturuldu } catch (IOException e) { e.printStackTrace(); } } } Belirtilen adres yanlış ise, kaydın eklenmesinde hata olabileceği için try catch içerisinde işlemlerimizi yaptık. Bu metot ile belirtilen dizinde ornek2 adında bir dosya oluşturduk. GETNAME METODU İLE DOSYANIN ADINI ÖĞRENME Bu metot, dosyamızın adını verir. Örnek üzerinde gösterelim. //FileSinifi2.java - 21.04.2014 1 2 import java.io.File; 3 4 public class FileSinifi2 5 { 6 public static void main(String[] args) 7 { 8 File f = new 9 File("C:\\elektroarge\\ornek2.txt"); 10 System.out.println(f.getName()); 11 } 12 } 13 14 Ekran çıktısı: 1 ornek2.txt Bu metot ile dosyamızın ismini öğrendik. GETABSOLUTEPATH METODU İLE DOSYANIN YOLUNU ÖĞRENME Bu metot, bize dosyamızın yolunu verir. //FileSinifi3.java - 21.04.2014 1 2 import java.io.File; 3 4 public class FileSinifi3 5 { 6 public static void main(String[] args) 7 { 8 File f = new 9 File("C:\\elektroarge\\ornek2.txt"); 10 System.out.println(f.getAbsolutePath()); 11 } 12 } 13 14 Ekran çıktısı: 1 C:\elektroarge\ornek2.txt DELETE METODU İLE DOSYAYI SİLME delete() metodu, dosyamızı bulunduğu dizinden siler. Örnek verirsek: 1 //FileSinifi4.java - 21.04.2014 2 3 import java.io.File; 4 5 public class FileSinifi4 6 { 7 public static void main(String[] args) 8 { 9 File f = new 10 File("C:\\elektroarge\\ornek2.txt"); 11 f.delete(); 12 System.out.println(f.exists()); // dosya var 13 mı? 14 } 15 } Ekran çıktısı: 1 false Dosyamızı sildikten sonra exist() metodu ile var olup olmadığının kontrolünü yaptık. Dosyamızı sildiğimiz için false değeri döndü. MKDIR METODU İLE KLASÖR OLUŞTURMA DOS komutları ile çalıştıysanız, bu isim size yabancı gelmeyecektir. Bu metot, belirtilen yola belirtilen isimdeki klasörü oluşturur. //FileSinifi5.java - 21.04.2014 1 2 import java.io.File; 3 4 public class FileSinifi5 5 { 6 public static void main(String[] args) 7 { 8 File f = new 9 File("C:\\elektroarge\\örnekklasör"); 10 f.mkdir(); 11 } 12 } 13 14 f nesnemize verdiğimiz adreste örnekklasör adlı klasör oluşturuldu. RENAMETO METODU İLE DOSYANIN ADINI DEĞİŞTİRME Bu metot, dosya adımızı değiştirmek için kullanılır. Bu metot, içerisine, yeni bir File tipinde nesnevermemiz gerekiyor. //FileSinifi6.java - 22.04.2014 1 2 import java.io.File; 3 4 public class FileSinifi6 5 { 6 public static void main(String[] args) 7 { 8 File f = new 9 File("C:\\elektroarge\\veriler.txt"); 10 File f2 = new 11 File("C:\\elektroarge\\bilke.txt"); 12 f.renameTo(f2); 13 } 14 } 15 Metoda parametre olarak f2 nesnesini verdik. Bu nesne, yeni dosyamızın yeni yolunu belirtiyor. Değiştirebilmemiz için aynı klasörde olması gerekir. CANREAD VE CANWRITE METODLARI İLE YAZMA OKUMA KONTROLÜ Adından da anlaşıldığı gibi bu metotlar, dosyamızın okunabilirliğini ve yazılabilirliğini kontrol eder. Duruma göre true veya false değerleri döndürür. 1 //FileSinifi7.java - 22.04.2014 2 3 import java.io.File; 4 5 6 7 8 9 10 11 12 13 14 15 public class FileSinifi7 { public static void main(String[] args) { File f = new File("C:\\elektroarge\\veriler.txt"); if(f.canRead() == true && f.canRead() == true) System.out.println("Hem yazılabilir hem okunabilir"); } } Ekran çıktısı: Hem yazılabilir hem 1 okunabilir Bizim dosyamızın erişiminde herhangi bir kısıtlama olmadığı için iki kontrolden de true değeri döndü ve ifşartımızın içine girildi. Eğer dosyamızın yolu yanlış yazıldı ise veya üzerinde herhangi bir kısıtlama var ise falsedeğeri döner. File sınıfının metodlarından bazılarını kullanarak son bir örnek vererek dersimizi bitirelim. 1 //FileSinifi8.java - 22.04.2014 2 3 import java.io.File; 4 5 public class FileSinifi8 6 { 7 public static void main(String[] args) 8 { 9 File f = new File("C:\\elektroarge\\sehirler.txt"); 10 if (f.exists()) // böyle bir dosya var ise 11 { 12 System.out.println("Dosya adı : " + f.getName()); 13 System.out.println("Dosya yolu : " + 14 f.getAbsolutePath()); 15 System.out.println("Dosya boyutu : " + 16 f.getTotalSpace()); 17 System.out.println("Dosya okunabilir mi : " + 18 f.canRead()); 19 20 } } } Ekran çıktısı: Dosya adı : sehirler.txt 1 Dosya yolu : 2 C:\elektroarge\sehirler.txt 3 Dosya boyutu : 209609289728 4 Dosya okunabilir mi : true Bu örneğimizde sehirler.txt adlı dosya üzerinde çalıştık. Eğer dosya var ise, yani belirtilen klasörde böyle bir dosya mevcutsa istenilen metotlar çalıştırılır. Temel olarak birkaç metodu inceledik. Bu nesnemiz üzerinden erişebileceğimiz metotların çokluğu aşağıdaki şekilde görülmektedir. Ders 114 - FileReader İle Dosya Oluşturma Bu sınıf ile dosya okuma işlemi yaptığımızda veriler karakter bazlı olarak okunur. Karakter bazlı işlem yaptığı için karakter encoding vardır. Buffer kullanılmaz. Performansı düşüktür. Karakter bazlı işlem yapıldığı için okunan veriler, char tipindeki bir diziye atılmalıdır. Çünkü işlemler karakter tabanlıdır. Yazma işlemlerinde diziye gerek yoktur. 1. FileReader sınıfı ile okumaya yapabilmek için ilk olarak File sınıfından bir nesne oluşturmak ve bu nesneye dosya yolunu vermek gerekir. 2. Daha sonra FileReader sınıfından bir nesne oluşturup, sınıfın yapıcısına File sınıfından oluşturduğumuz nesneyi parametre olarak verilmelidir. 3. Okunan verileri doldurmak için char tipinde bir dizi oluşturulur. 4. read() metodu ile okunan veriler bu diziye doldurulur. 5. Doldurulan bu dizi, String tipinde bir nesneye atılır. 6. Son olarak bu nesne ekrana yazdırılır. Bu sınıfın kullanımına bir örnek verelim. 1 //FileReaderSinifi.java - 22.04.2014 2 3 import java.io.*; 4 5 public class FileReaderSinifi 6 { 7 public static void main(String[] args) 8 { 9 File f = new 10 File("C:\\elektroarge\\sehirler.txt"); 11 char veriler[] = new char[(int) f.length()]; 12 try 13 { 14 FileReader f2 = new FileReader(f); 15 f2.read(veriler); 16 String okunan = new String(veriler); 17 System.out.println(okunan); 18 } 19 catch (FileNotFoundException e) 20 { 21 e.printStackTrace(); 22 } 23 catch (IOException e) 24 { 25 e.printStackTrace(); 26 } 27 } 28 29 } Ekran çıktısı: 1 İstanbul 2 Edirne 3 Giresun 4 Çorum 5 Samsun 6 Çanakkale 7 Kastamonu Burada yaptığımız adımları tek tek anlatalım. 1. File sınıfından f adında bir nesne oluşturduk ve dosya yolunu verdik. 2. f2 adında bir nesne oluşturduk ve f nesnemizi bu sınıfın yapıcısına gönderdik. 3. veriler adında bir char dizisi oluşturduk. Eleman sayısını, dosya uzunluğu olarak verdik. 4. f2 nesnesi üzerinden read() metodunu çağırdık. Okunan veriler, veriler adlı diziye atandı. Yani bu metot, okuduğu verileri bu diziye doldurdu. 5. Bu diziyi, okunan adında bir String nesnesine attık. 6. Son adımda ise, bu okunan nesnesini yazdırdık. Bu sınıf ile ilgili son bir şey söyleyelim. İçi boş olan bir dosya okunduğu zaman -1 değeri döner. Aşağıdaki programda a değişkeninin değeri -1 olacaktır. 1 //FileReaderSinifi2.java - 22.04.2014 2 3 import java.io.*; 4 5 public class FileReaderSinifi2 6 { 7 public static void main(String[] args) 8 { 9 File f = new 10 File("C:\\elektroarge\\sehirler.txt"); 11 try 12 13 14 15 16 17 18 19 20 21 22 23 { FileReader f2 = new FileReader(f); int a = f2.read(); System.out.println("a değeri: " + a); } catch (IOException e) { e.printStackTrace(); } } } Ekran çıktısı: a değeri: 1 1 Sehirler dosyasının içerisindeki tüm bilgileri önceden sildik. Bu dosyadan okuma işlemi yaptığımızda sonuç olarak -1 değeri dönecektir. Dönen bu -1 değerini bir if içerisine koyarak çeşitli kontroller yapabiliriz. Dosya boş ise veya dolu ise gibi kontroller koyabiliriz. Ders 115 - FileWriter İle Dosyaya Yazma FileWriter sınıfı, FileReader sınıfı gibi karakter bazlı işlem yapar. Yukarıda saydığımız özellikler, bu sınıf için de geçerlidir. Buffer kullanılmaz. Performansı düşüktür. Yazma işleminde dizi oluşturmaya gerek yoktur. Kullanım şekli ve nesne oluşturulması aşağıdaki gibidir. FileWriter nesne = new FileWriter ("yol", 1 true); İlk parametre, üzerinde çalışılacak dosyanın bilgisayardaki adresidir. Diğer parametrenin yazılma zorunluluğu yoktur. Eğer true olarak yazılırsa, o dosyadaki bilgilerin devamına ekleme yapılır. Eğer yazılmazsa dosyadaki veriler silinerek yazma işlemi gerçekleştirilir. Istisnalar: ! Dosyaya veri yazma işlemlerinde dosyanın kapatılmasına dikkat edilmelidir. Zorunlu olmasa da hata ile karşılaşabilirsiniz. Örnek vererek bu sınıfın nasıl kullanıldığına bakalım. //FileWriterSinifi.java - 22.04.2014 1 2 import java.io.*; 3 4 public class FileWriterSinifi 5 { 6 public static void main(String[] args) 7 { 8 File f = new 9 File("C:\\elektroarge\\bossayfa.txt"); 10 try 11 { 12 // yazma işlemleri 13 FileWriter yazdir = new FileWriter(f); 14 String yazilacak = "Bu bir deneme 15 yazısıdır"; 16 yazdir.write(yazilacak); 17 yazdir.close(); // bağlantı kapatıldı. 18 // okuma işlemleri 19 char veriler[] = new char[(int) f.length()]; 20 FileReader f2 = new FileReader(f); 21 f2.read(veriler); 22 String okunan = new String(veriler); 23 System.out.println(okunan); 24 } 25 catch (IOException e) 26 { 27 e.printStackTrace(); 28 } 29 } 30 } 31 Ekran çıktısı: Bu bir deneme 1 yazısıdır Burada yaptığımız adımları tek tek anlatalım. 1. File sınıfından f adında bir nesne oluşturduk ve dosya yolunu verdik. Bu dosyaya bir şeyler yazacağımız için adını bossayfa koyduk. 2. yazdir() adında bir nesne oluşturduk ve f nesnemizi bu sınıfın yapıcısına gönderdik. İşlemlerimizi buyazdir() nesnesi üzerinden yapacağız. 3. yazilacak adında bir String oluşturduk ve yazdıracağımız metni bu değişkene atadık. 4. yazdir nesnesi üzerinden write() metodunu çağırdık ve parametre olarak yazdıracağımız değişkeni verdik. 5. Son olarak bağlantımızı kapattık. Çünkü aynı program içerisinde bir de okuma işlemi yapacağız. Yazdırdıklarımızı görmek için bu okuma işlemini yaptık. Okuma işlemini bir önceki konuda anlatıldığı için aynı şeyleri söylemeyeceğiz. Istisnalar: Yazma işleminde, mevcut olmayan bir dosyaya veri yazmak ! istediğimizde hata ile karşılaşmayız. Bu yüzdencatch bloğu sayısını 1'e indirdik. Dosya olmadığı zaman, oluşturulur ve o dosyaya veriler yazılır. Dolayısıyla bir hata oluşmaz. Şimdi de okuma ve yazma işlemlerini beraber yapalım, fakat okuduğu verileri başka bir dosyaya yazsın. 1 //FileReaderSinifi.java - 22.04.2014 2 3 import java.io.*; 4 5 public class FileReaderSinifi 6 { 7 public static void main(String[] args) 8 { 9 File f = new 10 File("C:\\elektroarge\\sehirler.txt"); 11 File ff = new 12 File("C:\\elektroarge\\sehirler2.txt"); 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 char veriler[] = new char[(int) f.length()]; try { // okuma işlemleri FileReader f2 = new FileReader(f); f2.read(veriler); String okunan = new String(veriler); f2.close(); // yazma işlemleri FileWriter yazdir = new FileWriter(ff); yazdir.write(okunan); yazdir.close(); // bağlantı kapatıldı } catch (IOException e) { e.printStackTrace(); } } } Başka bir dosyaya yazmak için yazılacak dosya için yeni bir File sınıfı nesnesi ve yeni bir FileWriternesnesi oluşturmak gerekiyor. Bu yeni FileWriter nesnesine, ikinci oluşturduğumuz nesneyi parametre olarak gönderiyoruz. okunan adlı String veriyi de write() metoduna gönderiyoruz. İşimiz bitince de dosyayı kapatıyoruz. Ders 116 - FileInputStream İle Dosya Okuma Bu sınıf ile dosya okuma byte bazlı olarak yapılır. Byte bazlı okumalarda karakter encoding olmaz. Byte bazlı işlemlerde, okunan veriler byte tipinde bir diziye aktarılır. Okuma işlemleri byte bazlı olanlarda bu şekilde yapılır. Bu sınıfı kullanabilmek için ilk olarak bu sınıftan bir nesne oluştururuz. Daha sonra bu nesneye, okunacakFile nesnesi parametre olarak verilir. Istisnalar: ! Bu sınıfı kullanabilmek için import java.io.FileInputStream; ifadesi ile bu sınıfı import etmemiz gerekir. Fakat import java.io.*; ifadesini kullandığımız için buna gerek kalmayacaktır. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class FileInputStream_FayliOxuma { public static void main(String[] args) throws FileNotFoundException, IOException { File f = new File("C:\\Users\\Anonymous\\Desktop\\yazi.txt"); byte[] inform = new byte[(int)f.length()]; FileInputStream fis = new FileInputStream(f); fis.read(inform); String metin = new String(inform); System.out.println(inform); } } Istisnalar: ! Bu sınıf ile okuma işlemi yaptığımızda, bu sınıftan nesne oluştururken o bloğu try - catch içerisine almamız gerekir. Olmayan bir dosya ile çalışmak hata verebilir. Hemen bir örnek ile başlayalım. 1 İstanbul 2 Edirne 3 Ankara 4 Çorum 5 Giresun Burada yaptığımız adımları tek tek anlatalım. 1. File sınıfından f adında bir nesne oluşturduk ve dosya yolunu verdik. 2. oku adında bir nesne oluşturduk ve f nesnemizi bu sınıfın yapıcısına gönderdik. 3. dizi adında bir byte dizisini oluşturduk. Eleman sayısını, dosya uzunluğu olarak verdik. 4. oku nesnesi üzerinden read() metodunu çağırdık. Okunan veriler dizi adlı diziye atandı. Yani bu metod, okuduğu verileri bu diziye doldurdu. 5. Bu diziyi, okunan adında bir String nesnesine attık. 6. Son adımda ise bu okunan nesneyi yazdırdık. Dediğimiz gibi okuma ve bağlantı için try - catch bloğu oluşturduk. Okuma ve bağlantı hatalarında, hata mesajı ekrana yazılacaktır. Bu sınıfın genel kullanımı bu şekildedir. Verileri byte olarak okur. Ders 117 - FileOutputStream İle Dosyaya Yazma FileOutputStream ile verileri dosyaya yazdırmanın FileWriter sınıfından bir farkı, byte tabanlı olduğu için dosyaya veri yazdırmak için bir byte dizisi oluşturmamızdır. Diğerinde char dizisi oluşturmuştuk. Veriler bloklar halinde aktarılır. Byte tabanlı işlemler bloklar halinde yapılır. Byte tabanlı olduğunu, sonundaki OutputStreamifadesinden anlıyoruz. Kod olarak çok bir fark yoktur. Örnek vererek gösterelim. 1 //FileOutputStreamSinifi.java - 22.04.2014 2 3 import java.io.*; 4 5 public class FileOutputStreamSinifi 6 { 7 public static void main(String[] args) 8 { 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 File yol = new File("C:\\elektroarge\\veriler.txt"); try { FileOutputStream yazdir = new FileOutputStream(yol); String metin = "FileOutputStream ile Yazdırma"; byte veriler[] = metin.getBytes(); yazdir.write(veriler); yazdir.close(); // dosya kapatıldı // okuma işlemleri char okunacak[] = new char[(int) yol.length()]; FileReader f2 = new FileReader(yol); f2.read(okunacak); // dizi dolduruldu String okunan = new String(okunacak); System.out.println(okunan); } catch (IOException e) { e.printStackTrace(); } } } Ekran çıktısı: FileOutputStream ile 1 Yazdırma Bu örnekte farklı olarak söyleyeceğimiz şey getBytes() metodudur. String tipindeki verimizi bytetipindeki diziye atan metottur. Çünkü bu sınıfın getBytes() metodu yalnızca byte tipinde parametre alır. Doğrudan String ifademizi veremiyoruz. Ders 118 - BufferedReader İle Dosyadan Okuma Reader sınıfından türeyen bu sınıf, karakter tabanlı işlem yapar. Dosyadan okuma işlemleri buffer kullanılarak yapılır ve performansı fazladır. Bir örnek verelim: //BufferedReaderr.java - 22.04.2014 1 2 import java.io.*; 3 4 public class BufferedReaderr 5 { 6 public static void main(String[] args) 7 { 8 try 9 { 10 File f = new 11 File("C:\\elektroarge\\buffer.txt"); 12 FileReader fr = new FileReader(f); 13 BufferedReader br = new 14 BufferedReader(fr); 15 String satir = br.readLine(); 16 while (satir != null) 17 { 18 System.out.println(satir); 19 satir = br.readLine(); 20 } 21 br.close(); 22 } 23 catch (Exception e) 24 { 25 e.printStackTrace(); 26 } 27 } 28 } 29 Ekran çıktısı: Bu bir deneme 1 yazısıdır İlk olarak File sınıfından bir nesne oluşturduk ve yapıcıya dosyanın yolunu verdik. Daha sonar FileReader nesnesi oluşturduk ve bu sınıfın yapıcısına da File sınıfından oluşturulan f nesnesini verdik. BufferedReader sınıfından oluşturulmuş br nesnesiyle de fr nesnesini birbirine bağladık. Okuma işlemini readLine() metodu ile yaptık ve dönen değerleri while döngüsü ile yazdırdık. BufferedReader sınıfı aynı zamanda kullanıcıdan veri girişine de izin verir. Bu sınıfı kullanarak klavyeden girilen değeri alabiliriz. Bununla ilgili de bir örnek yapalım. //BufferedReaderr2.java - 22.04.2014 1 2 import java.io.*; 3 4 public class BufferedReaderr2 5 { 6 public static void main(String[] args) 7 { 8 try 9 { 10 InputStreamReader is = new 11 InputStreamReader(System.in); 12 BufferedReader br = new BufferedReader(is); 13 14 System.out.println("Birşeyler yazın :"); 15 String deger = br.readLine(); 16 System.out.println("Girilen: " + deger); 17 br.close(); 18 } 19 catch (Exception e) 20 { 21 e.printStackTrace(); 22 } 23 } 24 } 25 26 Ekran çıktısı: Birşeyler yazın : 1 Okan Bilke 2 Girilen: Okan 3 Bilke Kullanıcıdan veri almak için yine readLine() metodu kullanılır. Bu metot, girilen input'u boşluklarla beraber alır. BufferedReader sınıfı, veri girişi kullanacağı zaman InputStreamReader sınıfı ile beraber kullanılır. Ders 119 - BufferedWriter İle Dosyaya Yazma Writer sınıfından türeyen bu sınıf, karakter bazlı işlem yapar. Buffer kullandığı için flush metodu ilebuffer içerisinde bulunan verilerin dosyaya yazdırılması gerekir. Bu sınıf, FileWriter sınıfı ile kullanılırken performansı önemli derecede artırır. Bir örnek yapalım. //BufferOrnek.java - 22.04.2014 1 2 import java.io.*; 3 4 public class BufferOrnek 5 { 6 public static void main(String[] args) throws 7 Exception 8 { 9 File f = new File("C:\\elektroarge\\buffer.txt"); 10 FileWriter fw = new FileWriter(f, false); 11 BufferedWriter yaz = new BufferedWriter(fw); 12 yaz.write("Bu bir deneme yazısıdır"); 13 yaz.flush(); 14 yaz.close(); 15 } 16 } 17 18 FileWriter sınıfından bir nesne oluşturarak yapıcısına File sınıfından oluşturduğumuz nesneyi verdik. Yanına da false parametresini ekledik. Çünkü içerideki bilgileri silip yeniden yazmasını istiyoruz. Bu parametreyi vermeseydik, yine aynı işi yapardı. Daha sonra BufferedWriter sınıfından bir nesne oluşturuyoruz. Bu sınıfın yapıcısına fw nesnesini veriyoruz. Artık bu yaz nesnesi üzerinden write() metodunu çağırarak istediğimiz metni parametre olarak gönderiyoruz. Bu işlem ile veriler buffer'e yazılır. Son olarak da flush() metodunu çağırıyoruz ve buffer'da bulunan verileri dosyaya yazdırıyoruz. Daha sonra dosyamızı kapatıyoruz. Ders 120 - BufferedInputStream İle Dosya Okuma Bu sınıf, bir soyut sınıf olan FilterInputStream sınıfından türemiştir. Bu sınıfın adından şunu anlıyoruz.Buffer kullanarak veri aktarımı yapar ve aynı zamanda byte tabanlı iletim sağlar. Buffer kullandığı için performans avantajı vardır. Byte tabanlı işlem yapıldığı için okuma işleminde bir byte dizisi oluşturulmalı ve .ekilen elemanlar bu diziye alınmalıdır. Bu sınıfı, FileInputStream sınıfı ile beraber kullanırız. Bu sınıftan oluşturduğumuz nesneyi,BufferedInputStream sınıfının yapıcısına göndeririz. Şimdi bir örnek verelim: //BufferOrnek.java - 22.04.2014 1 2 import java.io.*; 3 4 public class BufferOrnek 5 { 6 public static void main(String[] args) 7 { 8 File f = new File("C:\\elektroarge\\buffer.txt"); 9 byte dizi[] = new byte[1000]; 10 try 11 { 12 FileInputStream f2 = new FileInputStream(f); 13 BufferedInputStream bf = new 14 BufferedInputStream(f2); 15 int okunan = 0; 16 while((okunan = bf.read(dizi)) != -1) 17 { 18 String veriler = new String(dizi, 0, okunan); 19 System.out.println(veriler); 20 } 21 bf.close(); 22 } 23 catch (IOException e) 24 { 25 e.printStackTrace(); 26 } 27 } 28 } 29 30 Ekran çıktısı: Okan Bilke 1 Elektroarge BufferedInputStream sınıfının yapıcısına, bir üst satırda oluşturduğumuz f2 nesnesini verdik. While döngüsü ile -1 dönene kadar yani dosya sonu gelene kadar okuma işlemi yaptık. Verileri read() metodu ile okuduk. String tipindeki veriler adlı nesneye okunan kadarını attık. Son olarak bu veriler nesnesini yazdırdık. Istisnalar: ! Buffer kullanarak verileri okumak, aynı zamanda bellekten veri okumak gibidir. Dolayısıyla diğer yöntemlere göre çok daha hızlı işlem yapılır. Ders 121 - BufferedOutputStream ile Dosyaya Yazma Bu sınıf, bir soyut sınıf olan FilterOutputStream sınıfından türemiştir. Bu sınıfı kullanırken bir byte dizisi tanımlamaya gerek yoktur. Çünkü okuma işlemi yapılmadığı için, içi doldurulması gereken bir diziye de ihtiyaç yoktur. Bu sınıfı, FileOutputStream sınıfı ile beraber kullanırız. Bu sınıftan oluşturduğumuz nesneyi,BufferedOutputStream sınıfının yapıcısına göndeririz. Bir örnek verelim. 1 //BufferOrnek.java - 22.04.2014 2 3 import java.io.*; 4 5 public class BufferOrnek 6 { 7 public static void main(String[] args) 8 { 9 File f = new File("C:\\elektroarge\\buffer.txt"); 10 try 11 { 12 BufferedOutputStream bf = new 13 BufferedOutputStream(new FileOutputStream(f)); 14 bf.write("Java'yı seviyorum".getBytes()); 15 bf.flush(); // buffer içerisindekiler dosyaya yazıldı 16 bf.close(); // dosya kapatıldı 17 } 18 catch (IOException e) 19 { 20 e.printStackTrace(); 21 } 22 } 23 } 24 Örnekteki flush() metodu ve write() metodu, BufferedOutputStream sınıfına ait metotlardır. write() metodunu kullanırken String verimizin getBytes() metodu ile işlem yapılır. Bu, metni byte olarak yazmak içindir. Bu örnekte dikkatimizi çeken bir şey var. try ifadesinden sonraki nesne tanımlamada, yapıcıya parametre gönderme işleminde aynı anda bir sınıf oluşturduk ve bu sınıfın yapıcısına da f nesnesini gönderdik. Bu şekilde tanımlama da yapılabilir. Normal olarak tanımlama yapsaydık aşağıdaki gibi yapmamız gerekirdi. FileOutputStream f2 = new FileOutputStream(f); 1 BufferedOutputStream bf = new 2 BufferedOutputStream(f2); Ders 122 - Scanner Sınıfı İle Dosya Okuma Scanner sınıfı, kullanıcıdan veri alma görevi gördüğü gibi bir dosyayı da okuyup ekrana yazdırabilir. Önceki derslerimizde Scanner sınıfı ile klavyeden veri girişi yaparken System.in parametresini kullanmıştık. Scanner sınıfı, bu girilen parametreye göre farklı işler yapabilir. Şimdi bu parametreyi değiştirerek dosyadaki bilgileri yazdırmaya çalışalım. Bir örnek verelim ve onun üzerinden anlatalım. //ScannerSinifi.java - 22.04.2014 1 2 import java.io.*; 3 import java.util.Scanner; 4 5 public class ScannerSinifi 6 { 7 public static void main(String[] args) 8 { 9 File f = new File("C:\\elektroarge\\scanner.txt"); 10 try 11 { 12 Scanner s = new Scanner(f); 13 while(s.hasNextLine()) 14 { 15 String veri = s.nextLine(); 16 System.out.println(veri); 17 } 18 } 19 catch (FileNotFoundException e) 20 { 21 System.out.println("Dosyaya bağlanırken hata 22 oluştu"); 23 } 24 } 25 } 26 27 Ekran çıktısı: 1 Okan Bilke 2 Onur Bilke 3 ElektroArge File sınıfını kullanarak f adında bir nesne oluşturduk. Bu nesnemize de okunacak verilerin olduğu dosyanın yolunu verdik. Scanner sınıfının yapıcısına parametre olarak ise, bu f nesnesini gönderdik. Scannersınıfından oluşturduğumuz s nesnesi ile artık okuma işlemi yapabiliriz. while döngüsü içerisindeki şartımız, döngünün, dosyada okunacak bir şey kalmayana kadar devam etmesini sağlar. Bu while döngüsü içerisinde de nextLine() ile satır satır okuma yaparız ve okuduğumuzu konsola yazdırırız. while döngüsünün içerisinde yazdığımız metodu açıklayalım. Bu metodun nextLine() metodundan ne farkı vardır? hasNextLine(): Scanner sınıfı eğer bir satır okuyabiliyorsa true, okuyamıyorsa false değeri döner. hasNextInt(): Scanner sınıfı eğer bir int değer okuyabiliyorsa true, okuyamıyorsa false değeri döner. hasNextFloat(): Scanner sınıfı eğer bir float değer okuyabiliyorsa true, okuyamıyorsa false değeri döner. hasNextByte(): Scanner sınıfı eğer bir byte değer okuyabiliyorsa true, okuyamıyorsa false değeri döner. hasNextShort(): Scanner sınıfı eğer bir short değer okuyabiliyorsa true, okuyamıyorsa false değeri döner. Gördüğünüz gibi bu metotlar, boolean tipinde değer döndürürler. Diğer bildiğimiz, kullanıcıdan veri alan metotlardan (nextLine) farkı budur. Dosyada okunacak bir verinin olup olmadığını kontrol etmek için kullanılır. Okunacak veri yoksa false döner. Başka bir örnek verelim. 1 //ScannerSinifi2.java - 22.04.2014 2 3 import java.io.*; 4 import java.util.Scanner; 5 6 public class ScannerSinifi2 7 { 8 public static void main(String[] args) 9 { 10 File f = new File("C:\\elektroarge\\scanner.txt"); 11 try 12 { 13 Scanner s = new Scanner(f); 14 System.out.println(s.hasNextInt()); 15 } 16 catch (FileNotFoundException e) 17 { 18 System.out.println("Dosyaya bağlanırken hata 19 oluştu"); 20 } 21 } 22 } 23 Ekran çıktısı: 1 false Dosyamızda sadece String tipinde veriler olduğu için hasNextInt() metodundan false değer dönecektir. Şimdi de dosyamızdaki sayıları okuyup, 2'ye bölünenleri ekrana yazdıralım. 1 //ScannerSinifi3.java - 22.04.2014 2 3 import java.io.*; 4 import java.util.Scanner; 5 6 public class ScannerSinifi3 7 { 8 public static void main(String[] args) 9 { 10 File f = new File("C:\\elektroarge\\scanner.txt"); 11 try 12 { 13 Scanner s = new Scanner(f); 14 while(s.hasNextInt()) 15 { 16 int sayi = s.nextInt(); 17 if(sayi % 2 == 0) 18 System.out.println(sayi); 19 } 20 } 21 catch (FileNotFoundException e) 22 { 23 System.out.println("Dosyaya bağlanırken hata 24 oluştu"); 25 } 26 } 27 } 28 Önce dosyamızın içindeki verileri görelim: Çıktımız ise şu şekilde olacaktır: 1 12 2 78 3 56 Istisnalar: ! Yukarıda anlattığımız gibi bir dosyadan verileri okuma işleminde parametre olarak File nesnesi, yani bir dosya vermiştik. Bunun yerine bir String veri de verebiliriz. Buna bir örnek vererek dersimizi sonlandıralım. 1 //ScannerSinifi4.java - 22.04.2014 2 3 import java.util.Scanner; 4 5 public class ScannerSinifi4 6 { 7 public static void main(String[] args) 8 { 9 String metin = "ElektroArge Okan 10 Bilke"; 11 12 13 14 15 16 17 } 18 } 19 Scanner s1 = new Scanner(metin); while (s1.hasNext()) { String a = s1.next(); System.out.println(a); } Ekran çıktısı: 1 ElektroArge 2 Okan 3 Bilke Scanner sınıfının yapıcısına bir String ifade verdik ve işlemlerimizi bu String üzerinden gerçekleştirdik. Ders 123 - Scanner Sınıfı Yapıcıları Scanner nesnesi, Scanner sınıfının farklı yapıcılarına göre farklı işlemler yapar. System.in parametresi ile kullanıcıdan veri girişi almıştık. Scanner sınıfının yapıcısına File nesnesi göndererek de dosyadan okuma yapmıştık. Şimdi bu yapıcı metotları gösterelim. Scanner (File kaynakDosya) : Dosyayı okuma işlemi yapar. Scanner (File kaynakDosya, String veriSeti) : Dosyayı okuma işlemi yapar. Scanner (String kaynakString) : Bir String ifadeyi okur. Scanner (InputStream kaynak) : Bir input akımını okuma işlemi yapar. Scanner (InputStream kaynak, String veriSeti) : Bir input akımını okuma işlemi yapar. Scanner (Readable kaynak) : Bir kaynağı okuma işlemi yapar. Scanner (ReadableByteChannel kaynak) : Bir kanalı okuma işlemi yapar. Scanner (ReadableByteChannel kaynak, String veriSeti) : Bir kanalı okuma işlemi yapar. Biz bunlardan dosyadan okuma ve bir String veriden okuma işlemini yaptık. Diğerlerine girmeyeceğiz. Ders 124 - Rastgele Erişimli Dosyalarda Okuma ve Yazma Bu dersimizi anlatmadan önce rastgele erişimli dosyaların, sıralı dosyalardan farkını açıklayalım. Rastgele erişimli dosyalarda aranılan bir kayda, indeks numarası verilerek erişilebilir. Fakat sıralı erişimli dosyalarda ise, bir kayda ulaşabilmek için tüm dosyayı baştan sona kadar taramak gerekir. Dolayısıyla bir veriye erişmede veya veriyi aramada, sıralı erişimli dosyaların dezavantajı vardır. Arama işlemi için zaman kaybı olur. Bu zamana kadar sıralı erişimli dosyalar üzerinde işlem yaptık. Bir dosyayı okurken dosya sonuna gelip gelmediğini kontrol etmiştik. Rastgele erişimli dosyalar ile çalışmak için RandomAccessFile sınıfı kullanılır. Bu sınıf da java.io paketinin altında bulunur. Bu yöntem ile dosyalar üzerinde işlem yapacaksak yazma ve okuma için ayrı ayrı sınıflar oluşturmamıza gerek yoktur. Parametre olarak verdiğimiz farklı modlar ile hangi işlemi yapmak istediğimizi biz söyleyeceğiz. Peki, bu modlar nelerdir, onlara bakalım. r: Dosyayı okumak için kullanılır. rw: Dosyada hem okuma hem de yazma işlemi yapmak için kullanılır. rws: Okuma ve yazma işlemleri yapılırken bu veriler de diske yazılır. Rastgele erişimli dosyalar üzerinde işlem yapmak için RandomAccessFile sınıfını kullanacağız. Bununla hem okuma hem de yazma işlemleri yapılır. Bu modları kullanarak örnek yapalım. //RandomDosyalar.java - 22.04.2014 1 2 import java.io.*; 3 4 public class RandomDosyalar 5 { 6 public static void main(String[] args) throws Exception 7 { 8 File f = new File("C:\\elektroarge\\random.txt"); 9 RandomAccessFile islem = new RandomAccessFile(f, 10 "rw"); 11 byte veri = islem.readByte(); 12 System.out.println((char)veri); 13 14 String satir = islem.readLine(); 15 System.out.println(satir); 16 17 islem.seek(f.length()); // imleç dosya sonuna 18 konumlanır 19 islem.seek(0); // imleç dosya başına konumlanır 20 String satir2 = islem.readLine(); 21 System.out.println(satir2); 22 } 23 } 24 Ekran çıktısı: O 1 kan Bilke - Elektronik Araþtýrma Geliþtirme 2 Platformu 3 Okan Bilke - Elektronik Araþtýrma Geliþtirme Platformu 1. random.txt dosyamızı okuma ve yazma modunda açtık. 2. RandomAccessFile sınıfının bir metodu olan readByte() ile dosyadan bir karakter okuduk ve bytetipindeki değişkene attık. 3. Alt satırda ise bunu tekrar char tipine cast ettik. Çünkü okunan veri byte tipindedir. 4. Görüldüğü gibi dosyadaki ilk harf olan J harfini ekrana yazdı. 5. Daha sonra yine RandomAccessFile sınıfının bir metodu olan readLine() metodu ile satırın tamamını okuduk. Tabi bunu islem nesnemiz üzerinden yapıyoruz. Fakat burada O harfimizi yazmadığını gördük. Bunun sebebi; bir önceki satırda bir karakter aldık ve imlecimiz O harfinin arkasına konumlandı, yani ilerledi. 6. islem.seek(f.length()); ile dosyanın sonuna konumlandık. Bunu, nasıl yapıldığını göstermek için denedik. 7. islem.seek(0); ile tekrar dosyanın başına konumlandık. 8. Son satırda ise tüm satırı yazdırmak istediğimizde J harfinin de yazıldığını gördük. Bir başka örnek yapalım: //RandomDosyalar2.java - 22.04.2014 1 2 import java.io.*; 3 4 public class RandomDosyalar2 5 { 6 public static void main(String[] args) throws Exception 7 { 8 File f = new File("C:\\elektroarge\\random.txt"); 9 RandomAccessFile islem = new RandomAccessFile(f, 10 "rw"); 11 islem.seek(0); 12 byte veriler[] = "Onur".getBytes(); 13 islem.write(veriler); 14 } 15 } 16 17 Program çalışmadan önce dosyamızın ilk hali yukarıdaki gibidir. Program çalıştıktan sonra ise aşağıdaki gibi olur. "Okan" yazısının yerine "Onur" yazısı gelmiştir. seek() metodu, imleci belirtilen indise konumlandırır ve işlemler bu indisin olduğu yerden itibaren yapılmaya başlanır. İmleci "Okan" yazısının başına yani 0. indise koyduk. Arama işlemleri için de bu şekilde bir mantık uygulanır. Bu örnekte modumuzu rw değil de r yapsaydık hata ile karşılaşacaktık. Çünkü biz dosyayı hem okuduk içerisine konumladık hem de dosyaya bir şeyler yazdık. Dosyaya veri yazma ile ilgili bir örnek daha verelim. 1 //RandomDosyalar3.java - 22.04.2014 2 3 import java.io.*; 4 5 public class RandomDosyalar3 6 { 7 public static void main(String[] args) throws Exception 8 { 9 File f = new File("C:\\elektroarge\\random.txt"); 10 11 RandomAccessFile islem = new RandomAccessFile(f, 12 "rw"); 13 islem.writeBytes("Java, çok güçlü bir dildir"); 14 islem.close(); 15 } 16 } writeBytes() metodu ile String bir veri yazabiliriz. islem.getFilePointer(); metodu ile de o anki pointer konumunu döndürür. Yukarıdaki örnek üzerinde deneseydik 26 sayısını döndürecekti. Aşağıdaki örneği inceleyelim. //RandomDosyalar4.java - 22.04.2014 1 2 import java.io.*; 3 4 public class RandomDosyalar4 5 { 6 public static void main(String[] args) throws Exception 7 { 8 File f = new File("C:\\elektroarge\\random.txt"); 9 RandomAccessFile islem = new RandomAccessFile(f, 10 "rw"); 11 islem.writeBytes("Java, çok güçlü bir dildir"); 12 System.out.println(islem.getFilePointer()); 13 islem.writeInt(3333); 14 System.out.println(islem.getFilePointer()); 15 islem.writeDouble(256.6); 16 System.out.println(islem.getFilePointer()); 17 } 18 } 19 20 Ekran çıktısı: 1 26 2 30 3 38 İlk olarak 26 sayısını döndürür. Daha sonra bir int değeri ekledik. Bu int değeri 4 byte yer kapladığı için pointer 4 basamak daha ilerledi. Son olarak double bir veri ekledik. Bu da 8 byte olduğu için 8 basamak ilerledi. Ders 125 - Object Serialization (Nesne Serileştirme) Serileştirme işlemi, bir nesneyi bir yerden başka bir yere taşımak, nesneyi depolayıp istenildiğini zaman tekrar elde etmek için kullanılır. Java'nın artılarından birisi de bu serileştirme işlemidir. Serileştirme işlemini kullanarak bir nesnenin anlık olarak tuttuğu bilgiler bir yere kaydedilir ve istenildiği zaman aynı şekilde bu bilgiler elde edilir. Bu şekilde nesneyi diske kaydedip istediğimiz yerde kullanabiliriz. Serileştirme işlemi yapılırken nesne bilgileri, byte olarak diske kaydedilir. Bu nesneye tekrar ulaşılmak istendiğinde bu byte veriler kullanılarak nesne tekrar elde edilir. Serileştirme işlemi nesneleri ağ üzerinden taşımak için kullanılır. Bu nesnenin her yerde çalışmasını, bubyte olarak saklanmış veriler sağlar. Bu byte veriler, ağ üzerinden başka bir bilgisayara gönderilir ve o bilgisayarda bu byte veriler tekrar nesneye dönüştürülür. Java'nın platform bağımsızlığının bir başka göstergesi de bu Serileştirme kavramıdır. Bir nesne Windowsortamından Linux ortamına taşınabilir. Tabi yine bunu JVM sağlar. Nesneler byte olarak kaydedildiği için başka bir ortamda da bu byte veriler okunarak o nesne tekrar elde edilir. Bu şekilde bir nesnenin byte olarak saklanmasına Serialization, bu byte veriden tekrar nesne oluşturulmasına da DeSerialization denir. SERIALIZABLE ARAYÜZÜ Java'da serileştirme yapabilmek için ilk yöntem Serializable arayüzünü kullanmaktır. Bunun için sınıfımızın, Serializable arayüzünü gerçekleşmesi gerekir. Yani o sınıfımız, java.io.Serializable arayüzünü kullanmış olmalıdır. Bu yöntem ile bir örnek yapalım. İlk olarak Calisan adında bir sınıf oluşturuyoruz ve aşağıdaki kodları yazıyoruz. 1 //Calisan.java - 22.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package Serializable; import java.io.*; public class Calisan implements Serializable // implement işlemi { private String ad; // değişkenlerimizi tanımladık private String soyad; public Calisan(String ad, String soyad) // yapıcımız { this.ad = ad; this.soyad = soyad; } public String getAd() // getter metodları { return ad; } public String getSoyad() { return soyad; } } Calisan sınıfını, Serializable sınıfından implement ediyoruz. Bu yöntem ile serileştirme işlemi için bunu yapmamız gerekir. Daha sonra ad ve soyad değişkenleri tanımlıyoruz. Yapıcımızı, getter metotları yazıyoruz. Şimdi ise serileştirme için Serialization adlı bir sınıf oluşturalım ve aşağıdaki kodları yazalım. 1 //Serialization.java - 22.04.2014 2 3 package Serializable; 4 import java.io.*; 5 6 public class Serialization 7 { 8 public static void main (String[] args) 9 { 10 Calisan isci = new Calisan("Okan", 11 "Bilke"); 12 ObjectOutputStream o1 = null; 13 FileOutputStream f1 = null; 14 try 15 { 16 f1 = new 17 FileOutputStream("bilgiler.txt"); 18 // dosya yolu verildi 19 o1 = new ObjectOutputStream(f1); 20 o1.writeObject(isci); 21 // isci nesnesi dosyaya yazdırıldı 22 } 23 catch (IOException i) 24 { 25 i.printStackTrace(); 26 } 27 finally 28 { 29 try 30 { 31 if (o1 != null) 32 o1.close(); 33 if (f1 != null) 34 f1.close(); 35 } catch (IOException ex) 36 { 37 ex.printStackTrace(); 38 } 39 } 40 } 41 } Burada ilk olarak isci nesnesi oluşturuyoruz ve ilk değerlerini gönderiyoruz. Sonra o1 ve f1 nesnelerini oluşturuyoruz. İlk değer olarak null veriyoruz, yoksa hata verecektir. Dosya işlemlerini try içerisinde yapıyoruz. f1 nesnesine dosya adımızı veriyoruz. Bu dosya, doğrudan projenin olduğu klasörde oluşacaktır.o1 nesnesinin olduğu sınıfın yapıcısına da f1'i parametre olarak veriyoruz. Bu ObjectOutputStream sınıfı, nesne yazdırmak için kullanılır. Daha sonra isci nesnesini dosyaya yazdırıyoruz. Son olarak da dosya kapatma işlemlerini gerçekleştirdik. Bu işlemler ile nesnemizi byte olarak dosyaya kaydettik. Daha sonra Deserialization işlemi ile bu nesnenin bilgilerini aynen elde edeceğiz. Şimdi de Deserialization işlemi için Deserialization sınıfı oluşturalım ve aşağıdaki kodları yazalım. 1 //Deserialization.java - 22.04.2014 2 3 package Serializable; 4 import java.io.*; 5 6 public class Deserialization 7 { 8 public static void main (String[] args) 9 { 10 FileInputStream f2 = null; 11 ObjectInputStream o2 = null; 12 try 13 { 14 f2 = new FileInputStream("bilgiler.txt"); 15 o2 = new ObjectInputStream(f2); 16 Calisan isci = (Calisan) o2.readObject(); // cast işlemi 17 System.out.println("Elde edilen nesne:" + isci.getAd() + " 18 " + isci.getSoyad()); 19 } 20 catch (IOException e) 21 { 22 e.printStackTrace(); 23 } 24 catch (ClassNotFoundException e) 25 { 26 e.printStackTrace(); 27 } 28 finally 29 { 30 try 31 { 32 if (o2 != null) 33 o2.close(); 34 if (f2 != null) 35 f2.close(); 36 } catch (IOException e) 37 { 38 e.printStackTrace(); 39 } 40 } 41 } 42 } 43 Ekran çıktısı: Elde edilen nesne: Okan 1 Bilke Deserialization işlemi için başlangıçta yaptığımız adımlar aynıdır. Fakat sınıflarımız Input olarak değiştirildi. Çünkü bir okuma işlemi yapacağız. o2 nesnesi üzerinden readObject metodunu kullanarak nesnemizi dosyadan okuyoruz. Fakat bunu Calisan sınıfına cast etmemiz gerekiyor. Okunan nesnenin sınıfını belli etmek için bunu yapıyoruz. Daha sonra bunu isci adlı nesneye atıyoruz ve bu nesne üzerinden adı ve soyadı getiren getAd() ve getSoyad() metotlarını çağırıyoruz. İşlem sonunda da dosyaları kapatıyoruz. EXTERNALIZABLE ARAYÜZÜ Serializablearayüzünü kullanarak nesnelerini nasıl dosyaya aktarırız ve daha sonra tekrar aynı şekilde bu nesneyi elde ederiz, bunu gördük. Şimdi ise serileştirme için 2. yöntem olan Externalizable arayüzünü anlatacağız. Bu şekilde serileştirme yapabilmek için sınıfımızı Externalizable arayüzünden implement etmemiz gerekir. Peki, hangi durumda bu 2. yöntemi kullanacağız. Eğer serileştirmek istediğimiz nesnenin her özelliğini serileştirmek istemiyorsak, bu yöntemi kullanmalıyız. Bir önceki yöntemde nesnemizin her alanını serileştirdik. 1. yöntemde readObject() metodu ile nesnemizin tamamını okuduk. Fakat bu yöntemde nesnemizin okunmasını istediğimiz yerlerini, readExternal() metodumuza parametre olarak göndereceğiz.writeExternal() ile de serileştirmek istediğimiz yerleri, bu metoda parametre olarak veririz. Tatbikî bu iki metot birbirinin tersi işleri yapıyor. Peki, bu yöntem bize ne avantaj sağlar? Başkalarının bilmemesi gereken yerler, serileştirme işlemine tabi tutulmazlar. Çünkü bu alanların tersi işlem yapılarak tekrar elde edilmesi sakıncalıdır. Bu yüzden 1. yöntem ile serileştirme yapıldığında bu gizli alanlar da serileştirme işlemine girer. Bu tür şeyler için 2. yöntem kullanılır. Yani sınıfımızı, Externalizable arayüzünden implement etmek gerekir. Bir örnek vererek konumuzu kapatalım. Calisan adlı bir sınıf oluşturalım. 1 //Calisan.java - 22.04.2014 2 3 package Externalizable; 4 import java.io.*; 5 6 public class Calisan implements Externalizable 7 { 8 private String ad, soyad; 9 private int maas; 10 // parametreli yapıcı 11 12 public Calisan(String ad, String soyad, int maas) 13 { 14 this.ad = ad; 15 this.soyad = soyad; 16 this.maas = maas; 17 } 18 19 public Calisan() // varsayılan yapıcı 20 { 21 } 22 23 public String getAd() 24 { 25 return ad; 26 } 27 public String getSoyad() 28 { 29 return soyad; 30 } 31 public int getMaas() 32 { 33 return this.maas; 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 } // serileştirme yapan writeExternal metodu public void writeExternal(ObjectOutput yazdir) { try { yazdir.writeObject(this.ad); yazdir.writeObject(this.soyad); } catch (Exception e) { System.out.println("Hata oluştu"); } } // serileştirilen nesneyi geri okuyan readExternal metodu public void readExternal(ObjectInput oku) { try { this.ad = (String)oku.readObject(); this.soyad = (String)oku.readObject(); } catch (Exception e) { System.out.println("Hata oluştu"); } } } Şimdi buradaki kodlarımızı açıklayalım. 1. Bir çalışan için 3 değişken tanımladık. Maaş verisini gizlemek istiyoruz. Bunun için Externalizablearayüzünü kullanmamız gerekir. 2. Alınan değerleri, değişkenlerimize atayacak olan parametreli yapıcıyı yazıyoruz. 3. Varsayılan yapıcıyı yazıyoruz. Bu 2. yöntemi kullanırsak, varsayılan yapıcı yazmamız gerekir. 4. Değerleri döndüren getter metotlarını yazıyoruz. 5. Serileştirme işlemini yapacak olan writeExternal() metodunu yazıyoruz. İşlemlerimizi try catch içerisinde yapıyoruz. Çünkü dosya işlemleri try ifadesi içerisinde yazılmalıdır. Serileştirme yaparken maaşın bilinmesini istemediğimiz için writeObject() metodumuza bu değeri göndermedik. writeExternal()metoduna parametre olarak yazdir nesnesini veriyoruz. Çünkü verilerimiz bu nesnede saklı. 6. Serileştirilen nesneyi geri getiren readExternal() metodu ise, oku nesnesini parametre olarak alıyor. Buoku nesnesinin tipi de ObjectInput sınıfıdır. Bu oku nesnesi üzerinden readObject() metodunu çağırıyoruz ve String tipine cast ediyoruz. Çünkü ad ve soyad değişkenlerimiz String tipindedir. Eğer buradaki try içerisinde this.maas=(int)oku.readInt(); metodumu yazsaydık hata alacaktık. Çünkü maaşımızı geri getiremeyiz. 7. Oluşabilecek hatalara karşı catch içerisinde mesajımızı yazdırdık. Buradaki oku ve yazdir nesnelerini diğer sınıflarda oluşturacağız. Şimdi ise serileştirme işlemini yapacak olan Serialization sınıfını yazıyoruz. 1 //Serialization.java - 22.04.2014 2 3 package Externalizable; 4 import java.io.*; 5 6 public class Serialization 7 { 8 public static void main(String[] args) 9 { 10 try 11 { 12 Calisan calisan1 = new Calisan("Okan", "Bilke", 1500); 13 FileOutputStream f1 = new 14 FileOutputStream("C:\\elektroarge\\calisan.txt"); 15 ObjectOutputStream o1 = new ObjectOutputStream(f1); 16 o1.writeObject(calisan1); 17 o1.close(); 18 } 19 catch (Exception e) 20 { 21 e.printStackTrace(); 22 } 23 } 24 } 25 1. Bu sınıfımıza calisan1 nesnesine ad, soyad, maaş değerlerini giriyoruz. Bu parametreler, az önce anlattığımız sınıfın yapıcısına gider ve değerleri ilgili değişkenlere atanır. 2. Yazdırma işlemi yapacağımız için FileOutputStream ObjectOutputStream sınıfını kullanıyoruz ve gerekli parametreleri verdik. 3. o1 nesnesi üzerinden writeObject() metodunu çağırdık ve nesnemizi gönderdik. Bu metot, serileştirme işlemini yapan metoddur. 4. Son olarak dosyamızı kapattık. Şimdi de son olarak Deserialization işlemini yapan Deserialization sınıfını yazıyoruz. 1 //Deserialization.java - 22.04.2014 2 3 package Externalizable; 4 import java.io.*; 5 6 public class Deserialization 7 { 8 public static void main(String[] args) 9 { 10 try 11 { 12 Calisan calisan1; 13 FileInputStream f2 = new 14 FileInputStream("C:\\elektroarge\\calisan.txt"); 15 ObjectInputStream oku = new ObjectInputStream(f2); 16 calisan1 = (Calisan)oku.readObject(); 17 System.out.println(calisan1.getAd()); 18 System.out.println(calisan1.getSoyad()); 19 System.out.println(calisan1.getMaas()); 20 oku.close(); 21 } 22 catch (Exception e) 23 { 24 e.printStackTrace(); 25 } 26 } 27 } 28 1. Calisan sınıfındaki verilerle işlem yapabilmek için calisan1 nesnesi oluşturduk. 2. Okuma işlemi yapacağımız için Input türündeki sınıflardan nesneler oluşturduk ve gerekli parametreleri verdik. 3. oku nesnesi üzerinden readObject() metodunu çağırdık ve yine nesne olarak kaydetmek istediğimiz için Calisan sınıfına cast ettik. Bu readObject() metodu, ObjectOutputStream sınıfına ait bir metottur. 4. Daha sonra bu calisan1 nesnesi üzerinden getAd(), getSoyad, getMaas metotlarını çağırdık. 5. Son olarak dosyamızı kapattık. Okan Bilke 0 1 2 3 Deserialization sınıfını çalıştırdığımızda yukarıdaki çıktıyı elde edeceğiz. Maaş değişkeni int tipinde olduğu için onun varsayılan değerini verdi. Yani maaşı serileştirmedik o yüzden değerini elde edemedik. Fakat 1500değerini vermiştik. Istisnalar: ! implement edeceğimiz sınıf, değişkenlerimizin olduğu sınıftır. Bu sınıf, Externalizable veya Serializablesınıfından implement edilmelidir. Istisnalar: ! Externalizable arayüzünü kullanarak bir Serileştirme yaptığımızda, Serializable arayüzü kullanmaya göredaha az disk alanı harcanacaktır. Bu da Externalizable arayüzü kullanmanın başka bir avantajıdır. TRANSIENT ANAHTAR KELİMESİ transient anahtar kelimesi, bir önceki konuda anlattığımız gibi serileştirilmesini istemediğimiz veriler için kulanılır. Bu anahtar kelimesini kullanacaksak sınıfımızı Serializable arayüzünden implement etmemiz gerekir. Çünkü Externalizable arayüzünü kullandığımızda zaten istemediğimiz verileri serileştirmiyorduk. Bu şekilde serileşmesini istemediğimiz verilerin başına transient anahtar kelimesini getirdiğimizde, o veri serileştirilemeyecek ve dolayısıyla elde etmek istediğimizde sonuç alamayacağız. Diyelim ki kişinin adına erişilmesin istiyoruz. Calisan sınıfında ad değişenini tanımlarken şu şekilde tanımlamalıyız. private transient String 1 ad; Bunun dışında Serializable arayüzünü kullanma, yani 1. yöntemdeki her şey ile aynıdır. Yalnızca serileştirilmesini istediğimiz yerlerin başına bu kelime yazılır. Bu yöntem, Externalizable yönteminin alternatifidir. Daha çok kod yazmak yerine tek kelime ile aynı işi yapabiliriz. Istisnalar: ! 3 yöntemde de bir ortak nokta vardır. Serileştirme işlemlerinde hangi sıra ile verileri serileştirdiysek, elde ederken de o sıra ile elde edilir. Istisnalar: ! Serileştirilecek elemanların olduğu sınıfın içerisinde, başka bir sınıfa ait nesne varsa, o nesnenin ait olduğu sınıfın da serileştirilebilir bir sınıf olması gerekir. Ders 126 - Koleksiyonlara Giriş Yazılım geliştirirken bazen tek bir değişken içerisinde birden fazla eleman tutmak isteyebiliriz. Bu gibi durumlarda Java'nın Collection sınıfını kullanmak daha doğru olacaktır. Collection sınıfı ArrayList, bağlı liste yapısı (LinkedList) ve HashSet gibi veri yapılarını içerir. Genellikle Collection sınıfları veri depolamak, depolanan veriyi çekmek, veriyi işlemek ve depolanan veriler içerisinde veri aramak gibi işlemler için kullanılırlar. Koleksiyonlar sıralı veya sırasız şekilde olabilirler. Java koleksiyonlarının avantaj ve dezavantajlarını şöyle sıralayabiliriz. JAVA KOLEKSİYONLARININ AVANTAJLARI Verileri bir araya toplamamızı ve veriler üzerinde işlem yapmamızı kolaylaştırır. Yazılımcı, koleksiyon sınıfı içerisindeki algoritmaları kullanarak, yeni algoritma yazmak zorunda kalmaz. Bu da yazılımın daha kolay anlaşılmasını ve tekrar kullanılmasını sağlar. Yazılımcıya uygulamanın performansını artıran kullanışlı algoritma ve veri yapıları sağlar. Belli bir boyutları yoktur. İçerisine veri ekleyip çıkardıkça boyutları değişir. Yani yazılımcının önceden koleksiyonu boyutlandırmasına gerek yoktur. JAVA KOLEKSİYONLARININ DEZAVANTAJLARI Koleksiyonlarda aynı değişkenler gibi veri tipleri vardır. Yani veri eklerken koleksiyonun veri tipine uygun verileri ekleyebiliriz. Derleme anında veri tipini denetimi yapılmaz. Ders 127 - Collection Arayüzü Collection arayüzü, koleksiyon arabirimlerinin hiyerarşik olarak en tepesinde bulunan birimdir. Java.Utilpaketi içerisinde bulunan bu arayüz, bize birkaç arayüz ve bunlar altında bulunan sınıfları sunar. Aşağıdaki diyagram bize koleksiyon hiyerarşisini gösteriyor. Collection: Koleksiyon arayüzlerinin hiyerarşik olarak en tepesinde bulunan, en genel koleksiyon arayüz sınıfıdır. o List: Liste yapısını örnek alan koleksiyon tipidir. İçerisinde bir elemandan birden fazla bulundurmaya izin verir. Elemanları sıralı bir biçimde tutar. o Queue: Kuyruk yapısını benimseyen koleksiyon tipidir. Liste tipinden türetilmesine karşın liste tipinin ana özelliği olan indis değerleriyle işlem yapmamasıyla liste türünden ayrılır. o Set: İçerisinde sakladığı elemanlar sıralı bir biçimde tutulmaz. Ayrıca bu koleksiyon tipi içerisinde kopya eleman bulundurmaz. Yani her elemandan sadece bir tane bulunabilir. SortedSet: Verileri sıralı bir biçimde tutar. Set tipinde de olduğu gibi bu tip kopya eleman bulundurmaya izin vermez. Map: Elemanlarla bunlara karşılık verilen anahtar değerleri eşleştiren arayüzdür. Tekrarlı anahtar değerleri içermez. Map arayüzü, koleksiyon arayüzü ile benzerlik gösterir. Ancak aralarındaki temel fark; map arayüzünün elemanlarının her birinin bir anahtar değer ile eşleştirilerek saklanmasıdır. o Sorted Map: Map arayüzünün özelliklerini taşır, ancak bu arayüzde anahtar değerleri artan bir sırada saklanır. Koleksiyon sınıfları ortak bir takım metotları kullanır. Metotlar bazı koleksiyon sınıflarında farklılık göstermesine karşın genel olarak aynıdır. Koleksiyon sınıflarının ayrıntılarına geçmeden bu metotları ve metotlardan bazılarının görevlerini bilmek fayda sağlayacaktır. add: Koleksiyon nesnesine referans verilen elemanı ekler. remove: Koleksiyon nesnesinden referans verilen elemanı siler. size: Koleksiyon nesnesindeki eleman sayısını verir. isEmpty: Koleksiyon nesnesinin boş olup olmadığını kontrol eder. contains: Koleksiyon nesnesi içerisinde referans olarak belirtilen elemanı arar. iterator: Koleksiyon nesnesini iterasyon nesnesine referans olarak göndermeye yarar. Ders 128 - Iterator Koleksiyon arayüzünün detaylarına geçmeden önce iterator arayüzünü öğrenmek faydalı olacaktır.Iterator() metodu koleksiyon nesnelerini yinelememizi sağlar. Iterator arayüzü metotları; koleksiyon nesnesi altındaki elemanlar arasında başlangıçtan sonuna kadar tek tek geçiş yapmamızı, elemanları güvenle silmemizi sağlar. Iterator arayüzünün metotlarını şöyle sıralayabiliriz: hasNext: Koleksiyon nesnesinin bir sonraki elemanının var olup olmadığını kontrol eder. Koleksiyon nesnesinin bir sonraki elemanı mevcut ise true; mevcut değil ise false değer döndürür. next: Koleksiyon nesnesini bir sonraki elemana ulaşması için iterasyon yapar ve iterasyon nesnesinin gösterdiği elemanı geri döndürür. remove: Koleksiyon nesnesi üzerindeki iterasyon nesnesinin gösterdiği elemanı siler. Iterator arayüzün metotlarını bir örnekte kullanarak açıklayalım. 1 //Iterator.java - 23.04.2014 2 3 import java.util.Collection; 4 5 public class Iterator 6 { 7 public static void main(String[] args) 8 { 9 Collection c = new Collection(); 10 Iterator i = c.iterator(); 11 12 while (i.hasNext()) 13 { 14 System.out.println("Sıradaki eleman : " + 15 i.next()); 16 i.remove(); 17 } 18 } 19 } 20 Yukarıdaki örnekte önce bir koleksiyon nesnesi tanımlayıp, daha sonra bu koleksiyon nesnesi için tanımladığımız iterator nesnesini çağırdık. i.hasNext() metoduyla koleksiyon nesnesinin bir sonraki elemanı mevcut ise, döngü çalışıyor. Daha sonraki satırda i.next() metodu ile iterator nesnesinin koleksiyon üzerinde gösterdiği elemanı ekrana yazdırıyoruz. En son satırda ise i.remove() metodu ile iterator nesnesinin koleksiyon üzerinde gösterdiği elemanı siliyoruz. Ders 129 - Set (Kümeler) Set arayüzü, collection arayüzünü miras alır. Bu sınıfı matematikteki kümelere benzetebiliriz. Matematikte elemanların kümeler içerisinde sıralı bir şekilde tutulma zorunluluğu yoktur ve bir elemandan bir küme içerisinde yalnızca bir tane bulunabilir. Bu sınıf içinde durum aynen böyledir. Elemanlar sıralı bir biçimde tutulması gerekiyorsa, SortedSet alt sınıfının öğesi TreeSet kullanılabilir. Set arayüzünün öğesi HashSet'dir. HASHSET HashSet koleksiyonu, Set koleksiyon tipinin bir örneğidir. Bu koleksiyon tipi yukarıda da bahsedildiği gibi tam olarak kümelere benzer. Elemanların sıralı olması şartı yoktur ve her elemandan bir küme içerisinde yalnız bir tane bulunabilir. HashSet koleksiyonunun bir diğer özelliği de erişim sırasının belirsiz olmasıdır.HashSet koleksiyonunun kullanımına bir örnek vererek bu koleksiyonu daha iyi anlamaya çalışalım. 1 //SetOrnek.java - 23.04.2014 2 3 import java.util.*; 4 5 public class SetOrnek 6 { 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public static void main(String[] args) { // HashSet nesnesi tanımladık. HashSet hSet = new HashSet(); // öğeleri HashSet koleksiyonuna ekliyoruz hSet.add("Okan"); hSet.add("Onur"); hSet.add("Göksu"); hSet.add("Bilke"); // HashSet nesnesini iterator öğesine bağladık Iterator i = hSet.iterator(); while(i.hasNext()) { System.out.println("Küme elemanı : " + i.next()); } } } Ekran çıktısı: 1 Küme elemanı : Onur 2 Küme elemanı : Göksu 3 Küme elemanı : Bilke 4 Küme elemanı : Okan Örnekte de görüldüğü gibi öğeler HashSet üzerinde sırasız bir şekilde saklanıyor. Öğelere erişim kısmında ise belirsiz bir erişim sırası var. Set koleksiyonlarının bir diğer özelliğinden yukarıda bahsetmiştik. Set koleksiyonları tekrarlı eleman içermezler. Bu özelliğe de bir örnek vererek açıklayalım. 1 //SetOrnek2.java - 23.04.2014 2 3 import java.util.*; 4 5 public class SetOrnek2 6 { 7 public static void main(String[] args) 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { // HashSet nesnesi tanımladık. HashSet hSet = new HashSet(); // öğeleri HashSet koleksiyonuna ekliyoruz hSet.add("Okan"); hSet.add("Onur"); hSet.add("Göksu"); hSet.add("Bilke"); hSet.add("Okan"); hSet.remove("Göksu"); // HashSet nesnesini iterator öğesine bağladık Iterator i = hSet.iterator(); while(i.hasNext()) { System.out.println("Küme elemanı : " + i.next()); } } } Ekran çıktısı: Küme elemanı : Onur 1 Küme elemanı : 2 Bilke 3 Küme elemanı : Okan Öncelikle remove() metodunun kullanımına göz atalım. remove() metoduyla belirttiğimiz elemanHashSet koleksiyon öğesi içerisinde bulunuyorsa silinir. Eleman HashSet koleksiyon öğesinde bulunmuyorsa,remove() metodu geri false değeri döndürür. HashSet koleksiyonumuza verileri eklerken "Okan" öğesini iki kere ekledik ama program bize örnekte de olduğu gibi sonuçta "Okan" öğesini bir kere verdi. "Okan" öğesini iki kere eklememiz HashSet koleksiyon öğelerine erişim sırasını değiştirmedi. Ayrıca program derleme anında hata vermez. Peki, iki kere eklenilen elemanı bulmamız mümkün değil midir? Bu soruya şöyle cevap verelim. Koleksiyon sınıflarının ortak kullanıldığı add() metodu eklenilen elemanın koleksiyon içerisinde var olup olmadığını kontrol eder. Eğer eklemek istenilen eleman koleksiyon içerisinde yoksa geriye true; zaten var isefalse değer döndürür. Bu durumu daha iyi kavrayabilmek için yine kısa bir örnekle açıklayalım. //SetOrnek3.java - 23.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import java.util.*; public class SetOrnek3 { public static void main(String[] args) { // kopya eleman bulunduran dizi oluşturuldu String[] a = {"Okan", "Onur", "Göksu", "Bilke", "Okan"}; // kopya eleman kontrol değerini tutacak değer boolean b; // HashSet nesnesi oluşturduk HashSet hSet = new HashSet(); // a dizisinin her elemanı için for döngüsü çalışır for(String s : a) { // hSet öğesine s alanının içindeki değeri kopyaladık b = hSet.add(s); if(!b) System.out.println("Kopya eleman bulundu : " + s); } Iterator i = hSet.iterator(); while(i.hasNext()) { System.out.println("Küme elemanı : " + i.next()); } } } Ekran çıktısı: 1 2 3 4 5 Kopya eleman bulundu : Okan Küme elemanı : Onur Küme elemanı : Göksu Küme elemanı : Bilke Küme elemanı : Okan Örnekte kopya eleman bulunduran bir dizi tanımladık. Daha sonra bu dizinin elemanlarını sıra ile HashSetkoleksiyon öğesine kopyaladık. Burada dikkat edilmesi gereken nokta add() metodu, yukarıda da bahsettiğim gibi eleman zaten mevcut ise, false değeri döndürecektir. Örnekte if kontrolü ile bu kopya değeri bulduktan sonra ekrana yazdırıyoruz. Kısacası; HashSet koleksiyon öğesini, sıranın önemsiz olduğu ve toplu veri depolamak istediğiniz uygulamalarınızda kullanabilirsiniz. LINKEDHASHSET LinkedHashSet, HashSet koleksiyon öğesine genel olarak benzemesine karşın bir özelliğiyle HashSetöğesinden ayrılır. HashSet koleksiyon öğesinde verilere erişim sırası belirsizdi. Bu koleksiyon öğesinde ise öğeler birbirine çift yönlü bağlıdır. LinkedHashSet öğelerinin erişim sırasını, aşağıdaki örnek üzerinden daha iyi görebiliriz. 1 //LinkedHashSetOrnek.java - 23.04.2014 2 3 import java.util.*; 4 5 public class LinkedHashSetOrnek 6 { 7 public static void main(String[] args) 8 { 9 // LinkedHashSet koleksiyon öğesini oluşturduk 10 LinkedHashSet linkedHashSet = new 11 LinkedHashSet(); 12 13 // elemanları koleksiyonumuza ekledik 14 linkedHashSet.add("Okan"); 15 linkedHashSet.add("Onur"); 16 linkedHashSet.add("Göksu"); 17 linkedHashSet.add("Bilke"); 18 linkedHashSet.add("Okan"); 19 20 // koleksiyonumuza iterator öğemize bağladık 21 22 23 24 25 26 27 28 29 Iterator i = linkedHashSet.iterator(); while(i.hasNext()) { System.out.println("Koleksiyon öğeleri : " + i.next()); } } } Ekran çıktısı: Koleksiyon öğeleri : Okan 1 Koleksiyon öğeleri : 2 Onur 3 Koleksiyon öğeleri : 4 Göksu Koleksiyon öğeleri : Bilke Örnekte de görüldüğü gibi, LinkedHashSet koleksiyon öğesi elemanları giriş sırasına göre birbirine çift yönlü bağlar. Elemanlar bağlı olmasına karşın yine de birbirleri arasında düzgün şekilde bir sıra bulunmuyor. Yani, elemanlar artan sırada sıralı değil, giriş sırasına göre sıralıdır. LinkedHastSet koleksiyon öğesi HashSetöğesinde de olduğu gibi kopya eleman bulundurmaz. SORTED SET SortedSet koleksiyon arayüzü, set koleksiyon arayüzünün alt arayüzüdür. Set koleksiyon arayüzü ile genel olarak aynı özelliklere sahip olmasına karşın elemanları sıralı tutmasıyla HashSet koleksiyon öğesinden ayrılır. Bu arayüzün kullanılan öğesi TreeSet'dir. TREESET TreeSet öğesi yukarıda da bahsedildiği gibi SortedSet arayüzünün alt sınıfıdır. Genel olarak HashSetsınıfı ile aynı metotları kullanılır. Bu koleksiyon tipinde tip kontrolü yapılır. Dolayısıyla kümeye içerisindeki elemanlardan farklı tipte bir eleman eklemeye çalışırsak derleme anında hata verecektir. TreeSet koleksiyon öğesinin genel kullanımını basit bir örnek üzerinde açıklayalım. //TreeSetOrnek.java - 23.04.2014 1 2 import java.util.*; 3 4 public class TreeSetOrnek 5 { 6 public static void main(String[] args) 7 { 8 // TreeSet koleksiyon öğesi oluşturduk. 9 TreeSet treeSet = new TreeSet(); 10 11 // koleksiyonumuza öğeleri ekledik 12 treeSet.add("İstanbul"); 13 treeSet.add("kırklareli"); 14 treeSet.add("edirne"); 15 treeSet.add("tekirdağ"); 16 // tip uyuşmazlığı nedeniyle böyle bir eleman 17 ekleyemeyiz. 18 // treeSet.add(1); 19 20 // treeSet koleksiyon öğesini i iterator nesnesine 21 bağladık. 22 Iterator i = treeSet.iterator(); 23 24 while(i.hasNext()) 25 { 26 System.out.println(i.next()); 27 } 28 } 29 } 30 Ekran çıktısı: 1 edirne 2 kırklareli 3 tekirdağ 4 İstanbul Yukarıdaki örnekte önce bir TreeSet oluşturduk. Daha sonra verilerimizi koleksiyon öğemize ekleyip öğeleri tek tek ekranda gösterdik. Örnekte dikkat edilmesi gereken nokta elemanların sırasıdır. Elemanları karışık sırada eklememize karşın ekran çıktısında sıralı bir şekilde alıyoruz. TreeSet koleksiyon öğesi verileriartan sırada sıralar. TreeSet öğesi HashSet koleksiyon öğesinden farklı bir takım metotlar içerir. Bunlardan bazıları ve bu metotların açıklamaları şöyledir: Koleksiyon öğesinin en küçük elemanını verir. first() : Object Koleksiyon öğesinin en büyük elemanını verir. last() : Object Koleksiyon öğesindeki toElement'den küçük olan headSet(Object öğeleri verir. toElement) : SortedSet Koleksiyon öğesinde fromElement öğesinden subSet (Object başlayıp toElement öğesine kadar olan elemanları fromElement, Object verir. Sonuca ilk eleman dahil, son eleman dahil toElement) : SortedSet değildir. Koleksiyon tailSet (Object öğesindeki fromElement ve fromElement'den fromElement) : sonraki elemanları verir. SortedSet Bu metotları daha iyi anlayabilmek için örnek üzerinde açıklayalım. 1 //TreeSetOrnek2.java - 23.04.2014 2 3 import java.util.*; 4 5 public class TreeSetOrnek2 6 { 7 public static void main(String[] args) 8 { 9 // TreeSet koleksiyon öğesini oluşturduk 10 TreeSet treeSet = new TreeSet(); 11 12 // Koleksiyonumuza öğeleri ekledik 13 treeSet.add(1); 14 treeSet.add(7); 15 treeSet.add(13); 16 treeSet.add(6); 17 treeSet.add(10); 18 19 System.out.println("TreeSet koleksiyonunun öğeleri : "); 20 System.out.println(treeSet); 21 System.out.println("Koleksiyonun ilk öğesi : " + 22 treeSet.first()); 23 System.out.println("Koleksiyonun son öğesi : " + 24 treeSet.last()); 25 System.out.print("Koleksiyondaki 7 den küçük elemanlar : 26 "); 27 System.out.println(treeSet.headSet(7)); 28 System.out.print("Koleksiyondaki 6 ile 13 arasındaki 29 elemanlar : "); 30 System.out.println(treeSet.subSet(6, 13)); 31 System.out.print("Koleksiyondaki 7 ve 7 den büyük 32 elemanlar : "); System.out.println(treeSet.tailSet(7)); } } Ekran çıktısı: TreeSet koleksiyonunun öğeleri : 1 [1, 6, 7, 10, 13] 2 Koleksiyonun ilk öğesi : 1 3 Koleksiyonun son öğesi : 13 4 Koleksiyondaki 7 den küçük elemanlar : [1, 6] 5 Koleksiyondaki 6 ile 13 arasındaki elemanlar : [6, 6 7, 10] 7 Koleksiyondaki 7 ve 7 den büyük elemanlar : [7, 10, 13] Yukarıdaki örnekte de görüldüğü gibi headSet() metoduna referans olarak verilen değer sıralamaya dahil olmazken, tailSet() metoduna referans olarak verilen değer sıralamaya dahil oluyor. Benzer durumsubSet() metodunda da mevcuttur. subSet() metoduna referans olarak verilen ilk eleman sıralamaya dahil olur, son eleman sıralamaya dahil olmaz. Ders İçinde Yazılmış Tüm Programlar ve Kodları Ektedir: Ders 130 - Liste Yapıları (List) List koleksiyon arayüzü, verileri bir dizi halinde depolar. Dizilerde olduğu gibi burada da elemanlarınindis değerleri vardır. Yazılımcı elemanların indis değerleri ile elemanlara erişebilir ve indis değerleri ile arama yapabilir. Liste yapılarını dizilerden (Array) ayıran en önemli özellik, liste yapılarının boyutlarının önceden ayarlanmış olmamasıdır. Dolayısıyla bu özellikleriyle dizilerden daha kullanışlıdırlar. Küme yapılarında her elemandan sadece bir tane bulunabiliyordu. Liste koleksiyon öğeleri kopya eleman bulundurmaya izin verirler. LISTITERATOR Liste yapılarına geçmeden önce ListIterator yapısını öğrenmek bize fayda sağlayacaktır. Daha önceki konularda küme yapıları için öğeleri yinelemek için iterator() metodunu kullanmıştık. Liste yapılarında bu metodun yaptığı görevi ListIterator() metodundan bir takım farklılıkları bulunmaktadır. Liste yapılarında öğe işlemlerimizi genel olarak indis değerleri üzerinden yaptığımız için ListIterator() metodu, indis işlemleri için özelleşmiştir. Bazı özel metotları ve bu metotların açıklamaları şöyledir: add: Referans olarak verilen elemanı listeye ekler. hasPrevious: ListIterator() metodu, ters yönde bir elemanı işaret ediyorsa geriye true değer döndürür. Eleman yoksa geriye false değer döndürür. nextIndex: next() metodu tarafından geri döndürülmesi gereken elemanının indis değerini döndürür. İterasyon yapmaz. previous: Listeyi sondan başlayarak bir önceki elemana ulaşması için iterasyon yapar ve iterasyon nesnesinin gösterdiği elemanı geri döndürür. previousIndex: previous() metodu tarafından geri döndürülmesi gereken elemanının indis değerini döndürür. İterasyon yapmaz. set: next() veya previous() metodu tarafından döndürülen elemanı referans verilen eleman ile değiştirir. ARRAYLIST ArrayList sınıfı, elemanları bir dizi biçimde saklar ve boyutu içine eleman eklendikçe büyür. ArrayListsınıfının elemanlarına indis değerleriyle erişmek veya silmek mümkündür. ArrayList sınıfı dizilerden daha avantajlı olmalarına karşın, bazı durumlarda dizilerin tercih edilmesi daha uygun olur. Depolanacak veri sayısı belli ve bu sayı büyük oranlarda değişmiyor ise dizilerin kullanılmasıdaha avantajlıdır. Veri sayısının belli olmadığı durumlarda ArrayList sınıfı kullanılabilir. ArrayList sınıfını dizilerden ayıran bir diğer özellik de, ArrayList sınıfının nesneleri depolayabilir olmasıdır. ArrayList sınıfını bir örnek üzerinden açıklamaya çalışalım. 1 //ListYapilariOrnek.java - 24.04.2014 2 3 import java.util.ArrayList; 4 import java.util.ListIterator; 5 6 public class ListYapilariOrnek 7 { 8 public static void main(String[] args) 9 { 10 ArrayList arrayList = new ArrayList(); 11 12 arrayList.add(1); 13 arrayList.add(2); 14 arrayList.add(3); 15 16 ListIterator i = arrayList.listIterator(); 17 18 System.out.println("ArrayList'i baştan sona doğru 19 tarıyoruz..."); 20 21 while(i.hasNext()) 22 { 23 System.out.print(i.nextIndex() + ". eleman : "); 24 System.out.println(i.next()); 25 } 26 System.out.println("ArrayList'i sondan başa doğru 27 tarıyoruz..."); 28 29 while(i.hasPrevious()) 30 { 31 System.out.print(i.previousIndex() + ". eleman : "); 32 System.out.println(i.previous()); 33 } 34 } 35 } Ekran çıktısı: ArrayList'i baştan sona doğru 1 tarıyoruz... 2 0. eleman : 1 3 1. eleman : 2 4 2. eleman : 3 5 ArrayList'i sondan başa doğru 6 tarıyoruz... 7 2. eleman : 3 8 1. eleman : 2 0. eleman : 1 Örnekte önce bir ArrayList tanımlayıp elemanlarımızı ArrayList'e ekledik. Daha sonra ArrayListnesnemizi ListIterator öğesine bağladık. İlk while döngüsünde ListIterator öğesinin hasNext() metodu ileArrayList'i baştan sona tarayıp elemanların indis değerlerini ve elemanları nextIndex() ve next() metotları yardımıyla ekrana yazdırdık. İkinci while döngüsünde aynı işlemleri ArrayList'i sondan başa doğru tarayarak yaptık. Liste yapılarına giriş yaparken, küme yapılarından farklı olarak liste yapılarının kopya eleman bulundurabileceğini söylemiştik. Peki, ArrayList öğemize farklı tipte bir eleman eklemeye çalışırsak, hata alır mıyız? Bunu da bir örnek üzerinden açıklayalım. 1 //ListYapilariOrnek2.java - 24.04.2014 2 3 import java.util.ArrayList; 4 import java.util.ListIterator; 5 6 public class ListYapilariOrnek2 7 { 8 public static void main(String[] args) 9 { 10 ArrayList arrayList = new ArrayList(); 11 12 arrayList.add(1); 13 arrayList.add(2); 14 15 16 17 18 19 20 21 22 23 : "); 24 25 26 } 27 } 28 arrayList.add(3); arrayList.add(1); arrayList.add("String tipte eleman"); ListIterator i = arrayList.listIterator(); while(i.hasNext()) { System.out.print(i.nextIndex() + ". eleman System.out.println(i.next()); } Ekran çıktısı: 0. eleman : 1 1 1. eleman : 2 2 2. eleman : 3 3 3. eleman : 1 4 4. eleman : String tipte 5 eleman Örnekte de görüldüğü gibi liste yapıları kopya eleman bulundurmaya izin veriyor. Farklı tipte bir eleman eklemeye çalıştığımızda ise hata vermedi. Bunun sebebi; koleksiyon öğelerini tanımlarken tip belirtmediğimiz zaman elemanlar koleksiyon öğeleri içerisine nesne olarak depolanırlar. Koleksiyon öğelerini tanımlarken tip belirtmeniz durumunda, farklı tip eleman eklenirken uygulama hata verecektir. Son olarak Liste yapılarında kullanılacak genel metotların ArrayList öğesi üzerinde kullanıldığı bir örnek yaparak, bu sınıfı sonlandıralım. 1 //ListYapilariOrnek3.java - 24.04.2014 2 3 import java.util.ArrayList; 4 import java.util.ListIterator; 5 6 public class ListYapilariOrnek3 7 { 8 public static void main(String[] args) 9 { 10 ArrayList arrayList = new ArrayList(); 11 12 arrayList.add(1); 13 arrayList.add(2); 14 arrayList.add(6); 15 arrayList.add(5); 16 arrayList.add(2, 3); 17 arrayList.set(3, 4); 18 19 System.out.print("Dizinin tüm elemanları : "); 20 System.out.println(arrayList); 21 System.out.print("Listenin indis numarası 3 olan 22 elemanı : "); 23 System.out.println(arrayList.get(3)); 24 } 25 } 26 Ekran çıktısı: Dizinin tüm elemanları : [1, 2, 3, 4, 5] 1 Listenin indis numarası 3 olan elemanı 2 :4 Örnekte arrayList.add(2, 3) satırına kadar elemanları sırayla listemize ekledik. Bu satırda 2 numaralı indis değerine 3 kaydedilir ve daha sonraki elemanların indis değerleri bir ötelenir. Daha sonraki satırda iseset() metodu ile 3 indis değerli elemanı 4 ile değiştirdik. En son satırda get() metodu ile 3 indis değerli elemanı ekrana yazdırdık. Ders 131 - LinkedList (Bağlı Liste) Bağlı liste yapısında adından da anlaşılabileceği gibi elemanlar eklenilirken aralarına bir bağ konulur. Bu bağ hem tek yönlü hem de çift yönlü olabilir. Bağlı liste yapısı List arayüzünün alt sınıfıdır. Dolayısıyla Listarayüzünün sınıflarının kullandığı ortak metotların hepsini uygulayabilir. Fakat bu koleksiyon yapısı listenin sonuna veri ekleme, listenin başından veri çekme gibi bazı özelleşmiş metotlara sahiptir. Bu özelliği sayesinde bağlı liste yapısı özelleştirilip kuyruk (Queue) veya yığıt (Stack) yapısına dönüştürülebilir. Kuyruk ve yığıt yapıları özel öneme sahip koleksiyon tipleridir. Ancak, bu yapıları kullanan uygulamaların çok olması nedeniyle kuyruk ve yığıt yapıları için özelleşmiş metotlar oluşturulmuştur. Bu bölümde kuyruk ve yığıt yapılarının nasıl oluşturulduğunu örneklerle göreceğiz. Şimdi bağlı liste yapısını daha iyi anlayabilmek için genel bir örnek yapalım: //ListYapilariOrnek.java - 24.04.2014 1 2 import java.util.LinkedList; 3 4 public class ListYapilariOrnek 5 { 6 public static void main(String[] args) 7 { 8 LinkedList linkedList = new LinkedList(); 9 10 linkedList.add(1); 11 linkedList.add(2); 12 linkedList.add(3); 13 linkedList.addFirst(4); 14 linkedList.addLast(0); 15 16 System.out.println("Listenin tüm elemanları : " + linkedList); 17 System.out.println("Listenin ilk elemanı : " + 18 linkedList.getFirst()); 19 System.out.println("Listenin son elemanı : " + 20 linkedList.getLast()); 21 } 22 } 23 Ekran çıktısı: Listenin tüm elemanları : [4, 1, 2, 1 3, 0] 2 Listenin ilk elemanı : 4 3 Listenin son elemanı : 0 Örnekte önce oluşturduğumuz bağlı listeye üç eleman ekledik. Daha sonra addFirst() ve addLast()metodlarıyla listenin önce başına sonra da sonuna bir eleman ekledik. Son olarak getFirst() ve getLast()metotlarıyla da ilk ve son elemanları ekrana yazdırdık. Kuyruk ve yığıt örneğine geçmeden önce bunları kısaca açıklayalım. Kuyruk, ilk giren ilk çıkar mantığını benimseyen yapıdır. Yani elemanlar koleksiyona sondan eklenir, ancak silme işlemi listenin başından yapılır.Yığıt yapısında ise kuyruk yapısının tam tersi mantık vardır. Elemanlar yığıt yapısında daima listenin sonunaeklenir ve silme işlemi listenin sonundan yapılır. Şimdi bağlı liste yapısıyla nasıl kuyruk ve yığıt yapıldığını görelim. Kuyruk Sınıfı: //kuyruk.java - 24.04.2014 1 2 import java.util.LinkedList; 3 4 public class kuyruk 5 { 6 private LinkedList list = new 7 LinkedList(); 8 9 public void elemanKaydet(Object 10 eleman) 11 { 12 list.addLast(eleman); 13 } 14 public Object elemanCek() 15 { 16 return list.removeFirst(); 17 } 18 public Object elemanGetir() 19 { 20 return list.getFirst(); 21 } 22 public boolean isEmpty() 23 { 24 return list.isEmpty(); 25 } 26 } 27 Yığıt Sınıfı: //yigit.java - 24.04.2014 1 2 import java.util.LinkedList; 3 4 public class yigit 5 { 6 private LinkedList list = new 7 LinkedList(); 8 9 public void yigitaEkle(Object eleman) 10 { 11 list.addFirst(eleman); 12 } 13 public Object tepeEleman() 14 { 15 return list.getFirst(); 16 } 17 public Object yigittanCek() 18 { 19 return list.removeFirst(); 20 } 21 public boolean isEmpty() 22 { 23 return list.isEmpty(); 24 } 25 } 26 27 Main Sınıfı: 1 //yigit.java - 24.04.2014 2 3 public class main 4 { 5 public static void main(String[] args) 6 { 7 kuyruk queue = new kuyruk(); 8 yigit stack = new yigit(); 9 10 for(int i = 1 ; i <= 3 ; i++) 11 { 12 queue.elemanKaydet(i); 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 stack.yigitaEkle(i); } System.out.println("Kuyruk(Queue) Elemanları :"); // kuyruk boş olmadığı sürece döngü çalışır. while(!queue.isEmpty()) { System.out.println("Kuyruktan getir :" + queue.elemanGetir()); System.out.println("Kuyruktan getir ve sil :" + queue.elemanCek()); } System.out.println("Yığıt(Stack) Elemanları :"); // yığıt boş olmadığı sürece döngü çalışır. while(!stack.isEmpty()) { System.out.println("En tepedeki eleman: " + stack.tepeEleman()); System.out.println("Yığıttan çekilen eleman: " + stack.yigittanCek()); } } } Ekran çıktısı: Kuyruk(Queue) 1 Elemanları : 2 Kuyruktan getir :1 3 Kuyruktan getir ve sil :1 4 Kuyruktan getir :2 5 Kuyruktan getir ve sil :2 6 Kuyruktan getir :3 7 Kuyruktan getir ve sil :3 8 Yığıt(Stack) Elemanları : 9 En tepedeki eleman: 3 10 Yığıttan çekilen eleman: 3 11 En tepedeki eleman: 2 12 Yığıttan çekilen eleman: 2 13 En tepedeki eleman: 1 14 Yığıttan çekilen eleman: 1 Önce kullandığımız metotları kısaca açıklayalım. Kuyruk Sınıfı: elemanKaydet (Object eleman): Elemanı kuyruğun sonuna ekler. elemanCek(): Kuyruğun başındaki elemanı getirir ve elemanı kuyruktan siler. elemanGetir(): Kuyruğun başındaki elemanı getirir. isEmpty(): Kuyruk boş ise geriye true; dolu ise false değer döndürür. Yığıt Sınıfı: yigitaEkle(Object eleman): Elemanı yığıta iter. tepeEleman(): Yığıtın en tepesindeki elemanı getirir. yigittanCek(): Yığıtın en tepesindeki elemanı çeker ve elemanı yığıttan siler. isEmpty() Yığıt boş ise geriye true; dolu ise false değer döndürür. Örnekte önce bir kuyruk (queue) ve bir yığıt (stack) yapısı oluşturduk. Daha sonra oluşturduğumuz bu yapıların ekleme metotlarını kullanarak kuyruk ve yığıta sırasıyla 1, 2 ve 3 elemanlarını ekledik. Sonuç olarak ekran çıktısında kuyruk yapısından ilk elde ettiğimiz elemanın kuyruğa ilk olarak eklediğimiz eleman olduğunu; yığıt yapısında ilk elde ettiğimiz elemanın yığıt yapısına, en son eklediğimiz eleman olduğunu gördük. VECTOR Vector'ler içine eleman yüklendikçe büyüyen dizilerdir. Temelde ArrayList koleksiyon yapısına benzemesine rağmen aralarında bir takım performans farklılıkları vardır. Vector sınıfı senkronizedir. Bu nedenle ArrayList sınıfı Vector sınıfından daha hızlıdır. Ayrıca Vector'lerin kapasitesinin ne değerde artacağını uygulamalar belirleyebilir. Vector sınıfını bir örnek üzerinden açıklayalım. 1 //VectorOrnek.java - 24.04.2014 2 3 import java.util.Vector; 4 5 public class VectorOrnek 6 { 7 public static void main(String[] args) 8 { 9 final int kapasite = 3; 10 final int artis = 4; 11 // Vector kapasitesini ve kapasite artışını verilen değerlerle 12 belirledik. 13 Vector v = new Vector(kapasite, artis); 14 15 v.add(1); 16 v.add(15); 17 v.add(19); 18 System.out.println("Vector'un kapasitesi : " + v.capacity()); 19 System.out.println("İlk eleman : " + v.firstElement()); 20 System.out.println("Son eleman : " + v.lastElement()); 21 v.add(5); 22 System.out.println("Vector'un kapasitesi : " + v.capacity()); 23 System.out.println("3. eleman : " + v.elementAt(2)); 24 } 25 } 26 Ekran çıktısı: Vector'un kapasitesi : 1 3 2 İlk eleman : 1 3 Son eleman : 19 4 Vector'un kapasitesi : 5 7 3. eleman : 19 Yukarıdaki örnekte Vector oluştururken, Vector'un kapasitesini 3 ve bu kapasite aşıldığı anda artırılacak kapasite artış miktarını 4 olarak belirledik. Bundan sonra vector başlangıç olarak kapasitesini 3 birim olarak belirler. Daha sonra bu kapasite aşıldığı anda kapasitesini 4 birim artırır. İlk olarak üç eleman ekledikten sonra Vector'un kapasitesini kontrol ettiğimizde kapasitesinin 3 olduğunu görüyoruz. Daha sonra Vector'un ilk elemanlarını ekrana yazdırıp, bir eleman daha ekliyoruz. Bu durumda Vector'un ilk elemanlarını ekrana yazdırıp, bir eleman daha ekliyoruz. Bu durumda Vector'un ilk kapasitesi aşılmış oluyor ve Vector kapasitesini artış miktarı kadar artırır. Tekrar Vector'un kapasitesini kontrol ettiğimizde kapasitesinin 7 olduğunu görüyoruz. QUEUE (KUYRUK) Kuyruk yapısına bağlı liste yapısında kısaca değinmiştik. Kuyruk, ilk giren ilk çıkar (First In First Out) mantığıyla çalışır. Yani kuyruğa ilk eklenen eleman kuyruktan ilk çıkacak elemandır. Temelde LinkedList(Bağlı Liste) yapısında olmalarına rağmen özel önemleri olduğu için bir takım özelleşmiş metotları kullanırlar. Kuyruk yapısı liste sınıfının en belirgin özelliği olan indis değerleriyle işlem yapmazlar. Yani kuyruk içindeki bir elemana indis değeriyle erişemezsiniz. Kuyruk sınıfını bir örnekle açıklayalım. //KuyrukOrnek.java - 24.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.LinkedList; import java.util.Queue; public class KuyrukOrnek { public static void main(String[] args) { Queue kuyruk = new LinkedList(); // add metotuyla eleman eklerken hata alırsak uygulama exception fırlatır. kuyruk.add(10); kuyruk.add(55); kuyruk.add(7); // offer metotuyla eleman eklerken hata alırsak geriye false değer döner. kuyruk.offer(66); while(!kuyruk.isEmpty()) { System.out.println("Sırada bekleyen eleman : " + kuyruk.peek()); System.out.println("Sırada bekleyen elemanı getir : " + kuyruk.poll()); } } } Ekran çıktısı: 1 Sırada bekleyen eleman : 10 2 3 4 5 6 7 8 Sırada bekleyen elemanı getir : 10 Sırada bekleyen eleman : 55 Sırada bekleyen elemanı getir : 55 Sırada bekleyen eleman : 7 Sırada bekleyen elemanı getir : 7 Sırada bekleyen eleman : 66 Sırada bekleyen elemanı getir : 66 Örnekte önce bir kuyruk yapısı oluşturduk. Daha sonra bu kuyruğa elemanlarımızı ekledik. Elemanları eklerken hangi metotla eklediğimize dikkat etmeliyiz. Eğer uygulamanın eleman eklerken hata almamız durumunda hata(Exception) fırlatmasını istiyorsak add() metodunu; hata almamız durumunda geriye trueveya false değer döndürmesini istiyorsak offer() metodunu kullanmalıyız. Elemanları ekledikten sonra kuyruğun başında bekleyen elemanı peek() metoduyla belirledik ve ekrana yazdırdık. Sonraki satırda ise bekleyen elemanı kuyruktan almak için poll() metodunu kullandık. Bu metot kuyrukta sıra bekleyen elemanı bize verir ve kuyruktan bu elemanı siler. Ders 132 - Map Arayüzü Map arayüzü, Collection arayüzünün bir parçası değildir. Bu arayüz, elemanlarını anahtar değerlerle eşleştirerek saklar. Anahtar değerler arasında kopya eleman bulundurmaya izin vermez; elemanlar arasında kopya değer bulunabilir. Map sınıflarını anlatmadan önce, bu sınıfların kullandığı bazı metotları açıklayalım. containsKey(Object key): Map içerisinde referans olarak verilen anahtar değer varsa true, yoksa falsedeğer döndürür. containsValue(Object Value): Map içerisinde referans olarak verilen değer varsa true, yoksa falsedeğer döndürür. entrySet(): Map içerisindeki elemanları Set (Küme) koleksiyon öğesi olarak verir. get(Object key): Map içerisinden, referans olarak verilen anahtar değere karşılık gelen elemanı verir. keySet(): Map içerisindeki anahtarları Set(Küme) koleksiyon öğesi olarak verir. put(Object key, Object value): Map içerisine referans olarak verilen elemanı anahtar değere eşleyerek kaydeder. remove(Object key): Map içerisinden anahtar değere karşılık gelen eleman silinir. values(): Map içerisindeki değerleri Collection öğesi olarak verir. HASHMAP HashMap, Map arayüzünün bir örneğidir. Bu sınıf her elemana karşılık bir anahtar değeri saklar. Anahtar değerler veya veriler sıralı olmak zorunda değildir. HashMap'den çekilen verilerin sırası belirsizdir. HashMap sınıfının performansını etkileyen bazı faktörler vardır. Başlangıç sığası ve bu başlangıç sığasınınnasıl artacağı gibi faktörler bu gibi veri yapılarının performansını direk etkiler. HasMap sınıfında da Başlangıç Sığası (Initial Capacity) ve Yükleme Katsayısı (Load Factor) faktörleri performansı etkiler. Başlangıç sığası,HashMap öğesinin ilk tanımlanırken belirlenen sığasıdır. Yükleme katsayısı ise, sığanın belirlenen oranda doolduğunda otomatik olarak değişeceğini gösteren orandır. Bu konu hakkında bir örnek yaparak konuya açıklık getirelim. 1 //HashMapOrnek.java - 24.04.2014 2 3 import java.util.HashMap; 4 import java.util.Iterator; 5 import java.util.Set; 6 7 public class HashMapOrnek 8 { 9 public static void main(String[] args) 10 { 11 HashMap hash = new HashMap (10, 0.75f); 12 // başlangıç sığası 10, yükleme katsayısı 0.75 olan HashMap öğesi 13 oluşturduk. 14 15 hash.put("Bir", 1); 16 hash.put("İki", 2); 17 hash.put("Üç", 3); 18 hash.put("Dört", 4); 19 hash.put("Beş", 5); 20 hash.put("Altı", 6); 21 22 Set veri = hash.entrySet(); 23 Set anahtar = hash.keySet(); 24 25 System.out.println("HashMap Öğesinin verileri"); 26 Iterator i = veri.iterator(); 27 while(i.hasNext()) 28 System.out.println(i.next()); 29 30 System.out.println("HashMap Öğesinin anahtarları"); 31 Iterator it = anahtar.iterator(); 32 while(it.hasNext()) 33 System.out.println(it.next()); 34 } 35 } 36 Örnekte önce başlangıç sığası 10 olan, yükleme katsayısı 0.75 olan bir HashMap öğesi oluşturduk. Bu rakamların yüksek olması HashMap öğesinin performansını etkileyecek; bellek kullanımını artıracaktır. Eğer öğeyi oluştururken başlangıç sığası ve yükleme katsayısı tanımlamak istiyorsanız, bunu kullanacağınız verilere göre iyi ayarlamanız gerekmektedir. Başlangıç sığası ve yükleme katsayısı tanımlamadığınız durumda derleyici sizin için ön tanımlı değerler olan başlangıç sığası 16 ve yükleme katsayısı 0.75 olan bir öğe oluşturacaktır. Öğemizi oluşturduktan sonra öğemize verileri anahtar değerler ile eşleyerek kaydettik. Buradan sonra ekran çıktısında verilerin kayıt sırası ile elde ettiğimiz çıktının sırasının farklı olduğuna dikkatinizi çekmek istiyorum.HashMap öğesini anlatırken söylediğimiz gibi HashMap öğesinde verilere erişim sırası belirsizdir. Daha sonrasında HashMap öğesinin verilerini entrySet() metodu ile oluşturduğumuz Set koleksiyon öğesine aktardık. Aynı işlemi sonraki satırda, bu sefer HashMap öğesinin anahtarları için yaptık. Verileri ve anahtarlarıiterator yardımıyla ekrana yazdırdık. HashMap öğesinin anahtarları için tekrarlı öğe içermez ifadesini kullanmıştık. Peki, tekrarlı anahtar öğesi girmeye çalıştığımızda hata verecek mi? Bunu kısa bir örnek üzerinden anlatalım. 1 //HashMapOrnek2.java - 24.04.2014 2 3 import java.util.HashMap; 4 import java.util.Iterator; 5 import java.util.Set; 6 7 public class HashMapOrnek2 8 { 9 public static void main(String[] args) 10 { 11 HashMap hash = new HashMap(); 12 13 hash.put("Bir", 3); 14 15 16 17 18 19 20 21 22 23 hash.put("İki", 4); hash.put("Bir", 1); hash.put("İki", 2); hash.put("Üç", 3); System.out.println("HashMap öğeleri : " + hash); } } Ekran çıktısı: 1 HashMap öğeleri : {Üç=3, Bir=1, İki=2} Örnekte HashMap öğesi oluşturduk ve bu öğeye iki kere tekrarlı anahtar içeren veri ekledik. Uygulama, tekrarlı anahtar değerleri için derleme anında hata vermedi. Fakat sonradan eklenen ve tekrarlı anahtar içeren öğenin verisini daha önceden var olan öğenin verisiyle değiştirdi. put() metodu, tekrarlı anahtar içeren bir öğe eklenmek istediğinde öğenin verisini önceden var olan öğenin verisi ile değiştirir ve önceki veriyi geriye döndürür. Eğer tekrarlı anahtar değer yoksa geriye null değer döndürür. Tekrarlı anahtar değerlerini kontrol etmek için uygulamanızda put() metodu için null değerini kontrol edebilirsiniz. LINKEDHASHMAP LinkedHashMap, Map arayüzünün bir öğesidir. Genel olarak HashMap ve LinkedList yapılarının özelliklerini içerir. LinkedList koleksiyon yapısında veriler birbirine bağlanıyordu. Bu sayede verilerin dönüş sırasını tahmin edebiliyorduk. LinkedHashMap öğelerinde de öğelerin dönüş sırasını tahmin edebiliriz.LinkedHashMap ile Map arayüzün öğelerinin yapabildiği işlemleri yapabiliriz. LinkedHashMap öğesini daha iyi anlayabilmek için bir örnekle bu öğeyi açıklayalım. 1 //LinkedHashMapOrnek.java - 24.04.2014 2 3 import java.util.LinkedHashMap; 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.Set; public class LinkedHashMapOrnek { public static void main(String[] args) { LinkedHashMap lhm = new LinkedHashMap(); // ASCII tablosundaki 65-90 arasındaki değerleri ve anahtarlarını öğemize kaydediyoruz for(int i = 65 ; i <= 90 ; i++) lhm.put((char) i, i); Set anahtarlar = lhm.keySet(); System.out.println("LinkedHashMap öğeleri"); System.out.println(lhm); System.out.println("LinkedHashMap öğesinin anahtarları"); System.out.println(anahtarlar); } } Ekran çıktısı: LinkedHashMap öğeleri {A=65, B=66, C=67, D=68, E=69, F=70, G=71, H=72, I=73, J=74, 1 K=75, L=76, M=77, N=78, O=79, P=80, Q=81, R=82, S=83, T=84, 2 U=85, V=86, W=87, X=88, Y=89, Z=90} 3 LinkedHashMap öğesinin anahtarları 4 [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z] Örnekte önce bir LinkedHashMap öğesi oluşturduk. Daha sonrasında for döngüsü yardımıyla, ASCIItablosundan 65 - 90 arasındaki değerleri öğemize ekledik. Ekran çıktısında da görüldüğü gibi öğeler kayıt sırasında olduğu gibi geri dönmüş oldu. LinkedHashMap bu özelliğiyle HashMap öğesindeki öğelerin geri dönüş belirsizliğini ortadan kaldırıyor. SORTEDMAP SortedMap, Map arayüzünün alt arayüzüdür. SortedMap, SortedSet arayüzünde olduğu gibi verileriartan sırada sıralı olarak saklar. Bu arayüzün SortedSet arayüzünden farkı, verileri anahtarlarla eşleyereksaklamasıdır. Bu arayüz, Map arayüzüne ekleme olarak iki metot daha sunar. Bu metotlar ve bunların görevleri ise şöyledir: firstKey(): Öğe içerisinde ilk anahtar değerini döndürür. lastKey(): Öğe içerisindeki son anahtar değerini döndürür. TREEMAP TreeMap, içerisine girilen verileri sıralı bir biçimde tutar. Yani anahtarların sıralı bir biçimde tutulması istediğiniz uygulamalarınızda TreeMap kullanabilirsiniz. Diğer Map arayüzü öğelerinden farklı bir takım metotlara sahiptir. Bunlardan bazıları ve bunların görevleri şöyledir. ceilingEntry(K Key): Verilen anahtar değere eşit veya ondan büyük olan anahtar değerle eşlenmiş anahtar-veri çiftini verir. Böyle bir anahtar yoksa null değer döndürür. ceilingKey(K Key): Verilen anahtar değere eşit veya ondan büyük olan anahtar değeri döndürür. Böyle bir anahtar değer yoksa null değer verir. descendingKeySet(): Map içerisindeki anahtar değerleri azalan sırada verir. descendingMap(): Map içerisindeki anahtar-veri çiftlerini azalan sırada verir. firstEntry(): Map içerisindeki ilk anahtar ile eşleşen anahtar veri çiftini verir. floorEntry(K Key): Verilen anahtar değere eşit veya ondan küçük olan anahtar değerle eşleşmiş anahtar-veri çiftini verir. Böyle bir anahtar değer yoksa null değer döndürür. floorKey(K Key): Verilen anahtar değere eşit veya küçük olan anahtar değeri döndürür. Böyle bir anahtar değer yoksa null değer döndürür. headMap(K Key): Verilen anahtardan küçük olan anahtar değerlerle eşleşen anahtar-veri çiftlerini verir. Böyle bir anahtar değer yoksa null değer döndürür. higherEntry(K Key): Verilen anahtar değerden büyük olan anahtar değerle eşleşmiş anahtar-veri çiftini verir. Böyle bir anahtar değer yoksa null değer döndürür. higherKey(K Key): Verilen anahtar değerden büyük olan anahtar değeri verir. Böyle bir anahtar değer yoksa null değer döndürür. lastEntry(): Map içerisindeki en büyük anahtarla eşleşen anahtar-veri çiftini verir. lowerEntry(K Key): Verilen anahtardan küçük olan anahtarla eşleşen anahtar-veri çiftini verir. Böyle bir anahtar değer yoksa null değer döndürür. lowerKey(K Key): Verilen anahtardan küçük olan anahtar değeri verir. Böyle bir anahtar değer yoksanull değer döndürür. pollFirstEntry(): Map içerisindeki ilk anahtarla eşleşen anahtar-veri çiftini verir ve bu öğeyi Mapiçerisinden siler. pollLastEntry(): Map içerisindeki son anahtarla eşleşen anahtar-veri çiftini verir ve bu öğeyi Mapiçerisinden siler. subMap(K fromKey, L toKey): Verilen anahtar arasında kalan anahtar-veri çiftlerini verir. Alt uç sıralamaya dahil, üst uç hariçtir. tailMap(K Key): Verilen anahtara eşit veya büyük olan anahtarlarla eşleşmiş anahtar veri çiftlerini verir. Anahtar değer yoksa null değer döndürür. Bu metotların bazılarını içeren bir örnekle konuyu açıklayalım. 1 //TreeMapOrnek.java - 24.04.2014 2 3 import java.util.TreeMap; 4 5 public class TreeMapOrnek 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 { public static void main(String[] args) { TreeMap tree = new TreeMap(); tree.put(1, "Bir"); tree.put(3, "Üç"); tree.put(6, "Altı"); tree.put(4, "Dört"); tree.put(5, "Beş"); tree.put(2, "İki"); System.out.println("TreeSet öğeleri : " + tree); System.out.print("3 veya 3 den sonraki en büyük anahtar-veri çifti : "); System.out.println(tree.ceilingEntry(3)); System.out.print("Azalan şekilde anahtarlar : "); System.out.println(tree.descendingKeySet()); System.out.print("7 veya 7 den sonraki en küçük anahtar-veri çifti : "); System.out.println(tree.floorEntry(7)); System.out.print("4 den küçük olan anahtar veri çiftleri : "); System.out.println(tree.headMap(4)); System.out.print("3 den büyük olan anahtar-veri çifti : "); System.out.println(tree.higherEntry(3)); System.out.print("2 den küçük olan anahtar değeri : "); System.out.println(tree.lowerKey(2)); System.out.print("Map içerisindeki son veri(Veri silinecek) : "); System.out.println(tree.pollLastEntry()); System.out.print("2 ile 4 değerleri arasındaki anahtar-veri çiftleri : "); System.out.println(tree.subMap(2, 5)); System.out.print("4 ve 4 den büyük olan anahtar veri çiftleri : "); System.out.println(tree.tailMap(4)); } } Ekran çıktısı: 1 TreeSet öğeleri : {1=Bir, 2=İki, 3=Üç, 4=Dört, 5=Beş, 6=Altı} 2 3 veya 3 den sonraki en büyük anahtar-veri çifti : 3=Üç 3 Azalan şekilde anahtarlar : [6, 5, 4, 3, 2, 1] 4 5 6 7 8 9 10 7 veya 7 den sonraki en küçük anahtar-veri çifti : 6=Altı 4 den küçük olan anahtar veri çiftleri : {1=Bir, 2=İki, 3=Üç} 3 den büyük olan anahtar-veri çifti : 4=Dört 2 den küçük olan anahtar değeri : 1 Map içerisindeki son veri(Veri silinecek) : 6=Altı 2 ile 4 değerleri arasındaki anahtar-veri çiftleri : {2=İki, 3=Üç, 4=Dört} 4 ve 4 den büyük olan anahtar veri çiftleri : {4=Dört, 5=Beş} Örnekte ilk önce bir TreeMap oluşturduk ve verilerimizi TreeMap öğesine rastgele ekledik. Ekran çıktısında ilk sırada TreeMap öğelerinin erişim sırasına baktığımızda verileri rastgele ve düzensiz eklememize rağmen verilerin sıralı bir biçimde TreeMap içerisinde saklandığını görüyoruz. Sonraki satırda kullandığımız metotla 3 veya 3'den sonra en büyük olan anahtarla eşleşen anahtar-veri çiftini ekrana yazdırıyoruz. Daha sonraki satırda ise 5 metoduyla Map içerisindeki anahtarları azalan sırada ekrana yazdırıyoruz. Bir sonraki satırda floorEntry() metoduyla 7 veya 7'den sonraki en küçük anahtarla eşleşen anahtar-veri çiftini ekrana yazdırdık. headMap() metoduyla 4'den küçük olan anahtar-veri çiftlerini ekrana yazdırdık. Bir sonraki satırdahigherEntry() metoduyla 3'den büyük olan anahtarla eşleşen anahtar-veri çiftini ekrana yazdırdık. Sonraki satırda lowerKey() metoduyla 2'den küçük olan anahtar değeri ekrana yazdırdık. pollLastEntry() metoduylaMap içerisindeki son anahtar-veri çiftini ekrana yazdırdıktan sonra metot son veriyi Map içerisinden sildi. Sonraki satırda subMap() metoduyla 2 ile 5 arasındaki verileri ekrana yazdırdık fakat metotun tanımında da anlatıldığı üzere 2 sıralamaya dahil edilirken, 5 sıralamaya dahil edilmedi. En son satırda tailMap() metoduyla 4 ve 4'den büyük olan anahtar-veri çiftlerini ekrana yazdırdık ve uygulamayı sonlandırdık. Ders 133 - Olay Yönetimine Giriş Bu dersimizde Java'da önemli bir yeri olan olaylar ve olayların yönetimine ilişkin durumları açıklamaya çalışacağız. Olaylar, görsel tabanlı uygulamaların temelini oluştururlar. Olaylar hakkında hiç bilgi sahibi olmadan, görsel tabanlı uygulama yazmak neredeyse imkansızdır. Uygulamamız çalışırken kullanıcı tarafından uygulamaya yapılan her etki bir olaydır. Bu bazen bir fare tıklaması olabileceği gibi bazen ise farenin hareket etmesi durumudur. Java'da olayları tam olarak anlayabilmemiz için olayları meydana getiren dört unsuru bilmemiz gerekir. Bunlar; Olay Kaynağı (Event Source): Olayı tetikleyen nesnedir. Çoğu zaman dış bir birimin durumunun değişmesi olayı tetikleyen ana neden olmuştur. Fare ve klavye gibi nesneler, en çok olay üreten birimler olmuşlardır. Olay Nesnesi (Event Object): Olayı tetikleyen kod parçasıdır. Olay ile ilgili bilgileri tutar. Olay Dinleyicileri (Event Listener): Dinleyici bir olayın tetiklenme durumu için oluşturulmuş nesnedir. Adından da anlaşılacağı üzere sürekli özelleştiği olayı dinler ve olay gerçekleştiği zaman Event Handlingnesnesini tetikler. Olay İşleyicileri (Event Handling): Olay dinleyicisi tarafından ilgili olay yakalandığında, bu olaya aitEvent Handling nesnesi tetiklenir ve bu nesne altındaki kod parçalarının çalışması sağlanır. Ders 134 - Olay Sınıfları Bu başlık altında Java'daki olayları gerçekleştiren sınıfları anlatacağız. Olay sınıfları, olay yönetimi bölümünün büyük bir kısmını oluşturmaktadır. Bu sebeple olay yönetimine olay sınıflarıyla başlamamız daha uygun olacaktır. Java'da burada işleyeceğimizden fazla olay olduğunu bilmeliyiz. Biz bu kısımda en çok kullanılan olay sınıflarını işleyeceğiz. Olay sınıflarına geçmeden önce, şimdi bir olayın bileşenimize nasıl eklendiğini görmek için basit bir örnek verelim: JButton dugme = JButton("Yeni 1 Dugme"); Olayımızı eklemeden önce yukarıdaki gibi öncelikle bileşenimizi oluşturuyoruz. 1 dugme.addActionListener(this); Sonrasında ise olayımızın gerçekleşip gerçekleşmediğini kontrol edecek dinleyici bileşenimize ekliyoruz. Daha sonrasında ise, yine sınıfımız içerisinde olayımız gerçekleştiğinde çağrılacak ilgili metodumuzun bir kopyasını yazıyoruz. void actionPerformed(ActionEvent ae) 1 { 2 // butona tıklanıldığında çağırılacak 3 metod 4 } Yukarıda gördüğümüz metodun içerisine butona her tıklandığında, çalıştırmak istediğimiz kod parçalarını yazmamız gerekmektedir. Tabi bir olayı tanımlarken olayı yazacağımız sınıfımızın ilgili olay dinleyici sınıfınıimplement etmesi gerekmektedir. Yukarıdaki örnekte ActionListener olay dinleyici sınıfını kullanmaktadır. Dolayısıyla sınıfımızda bileşenlerimize olayımızı eklemeden önce sınıfımızın ActionListener sınıfını implementetmesini sağlamalıyız. Şimdi olay sınıflarına ve bunların bize sağladığı metotlara geçelim. ACTIONEVENT Tanımlı bir bileşenin etki oluşturduğunu bildiren bir olay sınıfıdır. Bir düğmeye basıldığı gibi durumlarda oluşurlar. Bu olay sınıfının yapılandırıcı metotları aşağıdaki gibidir. ActionEvent (Object kaynak, int id, String komut) ActionEvent (Object kaynak, int id, String komut, int belirtec) ActionEvent (Object kaynak, int id, String komut, long zaman, int belirtec) Burada kaynak olayı başlatan nesnedir. Id ise olayın tipini integer bir değer ile ifade eder. komut ise olayla ilişkilendirilen karakter komut dizisidir. belirtec olay gerçekleştiğinde hangi belirteç tuşlarına basıldığını işaret eder (Belirteç tuşları: ALT, CTRL, SHIFT ve META). Negatif değer belirteç parametresi için bir anlam ifade etmezken , 0 değeri hiçbir belirteç tuşuna basılmadığını gösterir. zaman parametresi ise olayın gerçekleştiği zamanı belirtir. Bu sınıfın bazı metotları ve kullanım amaçları şöyledir: getActionCommand(): Olayla ilişkilendirilmiş komut adını geriye döndürür. getModifiers(): Olay gerçekleşirken hangi belirteç tuşlarına basıldığını geri döndürür. getWhen(): Olayın ne zaman meydana geldiğiyle ilgili bilgiyi geriye döndürür. paramString(): Olay içerisinde tanımlanmış parametre katarlarını geri döndürür. ADJUSTMENTEVENT AdjustmentEvent, genellikle kaydırma çubuğu tarafından oluşturulan olaydır. Kaydırma çubuğu birkaç durumda bu olayı üretebilir. Bu durumları ayırt etmek için sınıf içerisinde birkaç tane değişken tanımlanmıştır. Bunlar; ADJUSTMENT_VALUE_CHANGED: Kaydırma çubuğunun durumunun değiştiğini gösterir. BLOCK_DECREMENT: Kaydırma çubuğunun değerinin düşürüldüğünü gösterir. BLOCK_INCREMENT: Kaydırma çubuğunun değerinin artırıldığını gösterir. TRACK: Kaydırma çubuğunun sürüklendiğini gösterir. UNIT_DECREMENT: Kaydırma çubuğunun ucundaki butona kaydırma çubuğunun değerinin düşürülmesi için tıklandı. UNIT_INCREMENT: Kaydırma çubuğunun ucundaki butona kaydırma çubuğunun değerinin düşürülmesi için tıklandı. Bu olayın yapılandırıcı metodu aşağıdaki gibidir: AdjustmentEvent (Adjustable kaynak, int id, int tip, int veri) AdjustmentEvent (Adjustable kaynak, int id, int tip, int veri, boolean isAdjusting) Burada kaynak olayı başlatan nesneyi belirtir. id olay tipini, tip ayarlama tipini belirtirken veri ise ayarlanan nesneyi belirtir. isAdjusting değeri ise çoklu ayarlama olayına izin verilip verilmediğini gösterir. Bu sınıfın bazı metotları ve kullanım amaçları şöyledir: getAdjustable(): Bu olay ile ilişkilendirilmiş Adjustable nesne geri döndürülür. getAdjustmentType(): Olay ile ilişkilendirilmiş ayarlama tipini gönderir. Bu değer yukarıda bahsettiğimiz sabit değerlerdir. getValue(): Ayarlama miktarı geriye döndürülür. getValueIsAdjusting(): Çoklu ayar olaylarından biri doğru ise, geriye true değer döndürür. COMPONENTEVENT Bu olay sınıfı, bileşenlerin durumları ile ilgilidir. Bir bileşenin konumu veya boyutu gibi özellikleri değiştiğinde bu olay tetiklenir. Bir önceki olay sınıfında da olduğu gibi olay tiplerini birbirinden ayırt etmek için değişkenler tanımlanmıştır. Bunlar; COMPONENT_HIDDEN: Bileşenin gizlediği durumu belirtir. COMPONENT_SHOWN: Bileşenin görünürlük özelliğinin aktif edildiği durumu bildirir. COMPONENT_RESIZED: Bileşenin boyutunun değiştiğini bildirir. COMPONENT_MOVED: Bileşenin konumunun değiştiğini bildirir. Bu olay sınıfının yapılandırıcı metodu aşağıdaki gibidir: ComponentEvent(Component kaynak, int 1 tip) Burada kaynak olayı başlatan nesnedir, tip ise olayın tipini belirtir. Bu olay sınıfının en çok kullanılan metodu ve amacı aşağıdaki gibidir: getComponent(): Olayı başlatan bileşeni geriye döndürür. CONTAINEREVENT Bu olay sınıfı, bir bileşen Container nesnesine eklenildiğinde veya çıkarıldığında oluşur. Olay sınıfımız olayları birbirinden ayırt etmek amacıyla iki sabit oluşturmuştur. Bunlar; COMPONENT_ADDED: Container nesnesine bileşen ekleme durumunu kontrol eden sabit değer. COMPONENT_REMOVED: Container nesnesinden bileşen silme durumunu kontrol eden sabit değer. Bu olay sınıfımızın yapılandırıcı metodu aşağıdaki gibidir: ContainerEvent(Component kaynak, int id, Component 1 diger) Burada kaynak olayımızı başlatan bileşen, id olayımızın tipi ve diger Container nesnesine eklenilen veya çıkarılan bileşeni ifade etmektedir. Bu sınıfın en çok kullanılan bazı metotları ve metotların amaçları aşağıdaki gibidir: getContainer(): Bu metot, bize olayı başlatan Container nesnesini döndürür. getChild: Bu metot, bize Container nesnemize eklenilen veya nesnemizden çıkarılan bileşeni döndürür. FOCUSEVENT Bu olay sınıfıi bileşen üzerinde herhangi bir odak alındığında veya kaybedildiğinde tetiklenir. Olay odak alındığını ve kaybedildiğini, sınıf içerisinde tanımladığı FOCUS_GAINED ve FOCUS_LOST değerleriyle anlar. Bu sınıfın yapılandırıcı metotları aşağıdaki gibidir: FocusEvent(Component kaynak, int tip) FocusEvent(Component kaynak, int tip, boolean gecici) FocusEvent(Component kaynak, int tip, boolean gecici, Component diger) Burada kaynak olayı üretecek nesne referansıdır. Tip olayın tipini belirtir (FOCUS_GAINED veyaFOCUS_LOST). Bir diğer parametre olan gecici ise odak yakalama olayı geçici ise true değer alır; değilsefalse değer alır. Odak alımı başka bir bileşeni daha kapsayacaksa bu bileşen diger parametresi ile belirtilir. Bu sınıfın bazı metotları ve amaçları aşağıdaki gibidir: getOppositeComponent(): diger parametresiyle belirttiğimiz component tipindeki bileşeni döndürür. isTemporary(): Bu metot, bize odak yakalama olayının geçici olup olmadığını bildirir. INPUTEVENT Bu olay sınıfı, tüm girdi durumlarını kontrol eden olay tipidir. Bu olay sınıfı içerisinde yapılandırıcı bir metot yoktur. Bu olay gerçekleşirken ActionEvent olayında da olduğu gibi herhangi bir belirteç tuşuna basılması durumunu kontrol etmek için değerler tanımlanmıştır. Bunlar; Alt kontrol tuşunu belirtir. ALT_MASK AltGr kontrol tuşunu belirtir. ALT_GRAPH_MASK Farenin Button1 tuşunu belirtir. BUTTON1_MASK Farenin Button2 tuşunu belirtir. BUTTON2_MASK BUTTON3_MASK CTRL_MASK META_MASK SHIFT_MASK Farenin Button3 tuşunu belirtir. Ctrl tuşunu belirtir. Meta tuşunu belirtir. (Sun sistemlerinde bulunur) Shift tuşunu belirtir. Bu olay sınıfının bazı kullanılan metotları ve bu metotların amaçları aşağıdaki gibidir: isAltDown(): Olay başlatıldığında Alt tuşuna basılıp basılmadığını kontrol eder. isAltGraphDown(): Olay başlatıldığında AltGr tuşuna basılıp basılmadığını kontrol eder. isControlDown(): Olay başlatıldığında Ctrl tuşuna basılıp basılmadığını kontrol eder. isMetaDown(): Olay başlatıldığında Meta tuşuna basılıp basılmadığını kontrol eder. isShiftDown(): Olay başlatıldığında Shift tuşuna basılıp basılmadığını kontrol eder. Yukarıdaki metotlar, boolean tipinde değer döndürür. getModifiers(): Olay başlatıldığında hangi kontrol tuşlarına basıldığını verir. Int tipinde değer döndürür. ITEMEVENT ItemEvent olayı, genelde seçim olaylarıyla ilgilenir. Bir liste öğesi seçildiğinde, onay kutusu seçildiğinde veya onay kutusu kaldırıldığında bu olay üretilir. Bu olay sınıfı içerisinde olay tiplerinin tanımlanması için üç adet tam sayı tipte veri belirtilmiştir. Bunlar: DESELECT: Kullanıcı seçilmiş olan bir öğenin seçimini kaldırdı. SELECTED: Kullanıcı seçilmemiş olan bir öğeyi seçti. ITEM_STATE_CHANGED: Öğenin seçim durumunun değiştiğini gösterir. Seçili veya seçimin kaldırılmış olmasıyla ilgili bilgi vermez. Bu sınıfın yapılandırıcı metodu aşağıdaki gibidir: ItemEvent (ItemSelectable kaynak, int id, Object eleman, int 1 stateChange) Burada kaynak olayı üreten nesnedir. id ise olayın tipini belirtir. eleman ise olay tarafından etkilenen elemanı belirtir. stateChange parametresi ise bu öğenin geçerli durumunu belirtmek için kullanılır. Bu olay sınıfının bazı kullanılan metotları ve bu metotların amaçları aşağıdaki gibidir: getItem(): Olay tarafından etkilenen elemanı geriye döndürür. Object tipinde değer döndürür. getItemSelectable(): Olayı başlatan nesneyi geri döndürür. getStateChange(): Olay başlatıldıktan sonra değişen durumu döndürür (Sınıf içerisindeki değerlerden birini döndürür. SELECTED veya DESELECTED gibi). KEYEVENT Bu olay sınıfı genel olarak klavye girdileriyle ilgilidir. Sınıf içerisinde olayların tipini belirlemek için üç tip sabit değişken kullanılmıştır. Bunlar ve anlamları şöyledir. KEY_PRESSED: Klavyeden bir tuşa basılma durumunu belirtir. KEY_RELEASED: Klavyeden basılan bir tuşun bırakıldığını belirtir. KEY_TYPED: Klavyeden bir karakter girildiğini belirtir. Bu olay tiplerinden başka kullanılan tiplerde vardır. Bunlar ise genellikle klavyeden hangi tuşa basıldığının belirtilmesi için kullanılır. Bunlardan bazıları ve anlamları şöyledir: VK_CANCEL Cancel tuşunu kontrol eder. Aşağı yön tuşunu kontrol VK_DOWN eder. Yukarı yön tuşunu kontrol eder. Sol yön tuşunu kontrol eder. VK_LEFT Sağ yön tuşunu kontrol VK_RIGHT eder. Enter tuşunu kontrol eder. VK_ENTER Caps Lock tuşunu kontrol VK_CAPS_LOCK eder. VK_DELETE Delete tuşunu kontrol eder. ESC tuşunu kontrol eder. VK_ESCAPE VK_UP Tuş kontrolleri yukarıda belirttiğimizden çok fazladır. 0'dan 9'a kadar bütün tuşların kontrol değişkeni mevcuttur. Burada sadece örnek olması açısından bir kaçının açıklamasını verdik. Bu olay sınıfının en çok kullanılan yapılandırıcısı aşağıdaki gibidir: KeyEvent (Component kaynak, int id, long zaman, int belirtec, int kod, char 1 character) Burada kaynak olayı başlatan birleşen, id olayımızın tipi, zaman olayının gerçekleştiği zaman, belirtecolayın başlangıcında belirteç tuşlarına basılıp basılmadığını kontrol eden parametre, kod hangi tuşun kontrolünün yapılacağı integer tipte belirtir (VK_ENTER gibi), character ise tuş kontrolünde tuşun bilgisinichar tipte bildirir. Bu olay sınıfında en çok kullanılan bazı metotlar ve bu metotların amaçları şu şekildedir: getKeyCode(): Bu olay sırasında basılan tuşun kodunu integer tipte geri döndürür. getKeyChar(): Olay sırasında basılan tuşu char tipte geri döndürür. getKeyText(int keyCode): Kodu referans olarak gönderilen tuşu tanımlayan string tipte açıklama gönderir. isActionKey(): Basılan tuş bir fonksiyonel tuş ise true; değilse false değer döndürür. MOUSEEVENT Bu olay sınıfı farenin olaylarını kontrol eder. Farenin tıklanması, fareyi sürükleme, fare tekerleğinin hareket ettirilmesi gibi olaylar bu sınıf altındadır. Bu olayları birbirinden ayırmak için sınıf içerisinde bir takım değişkenler tanımlanmıştır. Bu değişkenleri iki grup altında inceleyebiliriz. Bunlar; Fare Olayları: MOUSE_CLICKED: Farenin tıklanması durumunu kontrol eder (Butona basıldı ve serbest bırakıldı). MOUSE_ENTERED: Farenin bir bileşenin etki altına girmesi durumunu kontrol eder. MOUSE_EXITED: Farenin bir bileşenin etki alanından çıkması durumunu kontrol eder. MOUSE_PRESSED: Farenin butonuna basılması durumunu kontrol eder. MOUSE_RELEASED: Farenin butonunun serbest bırakılması durumunu kontrol eder. MOUSE_WHEEL: Farenin tekerleğinin hareket ettirilmesi durumunu kontrol eder. Fare hareket olayları: MOUSE_DRAGGED: Farenin sürüklenmesi durumunu kontrol eder. MOUSE_MOVED: Farenin taşınması durumunu kontrol eder. MouseEvent olay sınıfımızın yapılandırıcı metotları aşağıdaki gibidir. MouseEvent (Component kaynak, int id, long zaman, int belirtec, int x, int y, int tikSayisi, boolean tetikleyici) MouseEvent (Component kaynak, int id, long zaman, int belirtec, int x, int y, int tikSayisi, boolean tetikleyici, int button) Burada kaynak olayı üreten bileşen, id olayın tipi, zaman olayın ne zaman gerçekleştiği, belirtec olay gerçekleşirken hangi belirteç tuşlarına basıldığı, x ve y farenin yatay ve dikey koordinatları, tikSayisi olay ile ilişkilendirilmiş fare tık sayısı, tetikleyici eğer olay bir açılır pencerenin görüntülenmesini sağlayacaksa true; değilse false, button ise hangi fare tuşunun durumunun değiştiğini gösteren değerlerdir. Button parametresinin hangi fare tuşunun durumunun değiştiğini gösteren değerler aldığını az önce ifade etmiştik. Bu değerler, yine sınıf içerisinde tanımlanan tuşları birbirinden ayırt etmek için kullanılan sayısal değerlerdir. Bunlar; NOBUTTON: Olaylardan hiçbir fare tuşunun etkilenmediğini gösterir. BUTTON1: Farenin ilk tuşunu belirtir. BUTTON2: Farenin ikinci tuşunu belirtir. BUTTON3: Farenin üçüncü tuşunu belirtir. Bu olay sınıfımızın en çok kullanılan bazı metotları ve amaçları aşağıdaki gibidir. getX(): Farenin yatay düzlemdeki X koordinatını verir. getY(): Farenin dikey düzlemdeki Y koordinatını verir. getPoint(): Farenin bulunduğu noktayı getirir. Point tipinde değer döndürür. getClickCount(): Olay için fareye tıklanma sayısını verir. getButton(): Olaya neden olan fare tuşunu belirten sayısal değer gönderir. Sayısal değerler yukarıda bahsettiğimiz tuş değerleridir. MOUSEWHEELEVENT Bu olay sınıfı farenin tekerleğini kontrol eder. MouseEvent sınıfının alt sınıfıdır. Diğer sınıflarda olduğu gibi bu olay sınıfımızda da olayları birbirinden ayırmak için bir takım değerler tanımlanmıştır. Bunlar; WHEEL_BLOCK_SCROLL: Bir sayfa (block) yukarı veya aşağı hareket ettirilmesi durumudur (Page Down veya Page Up tuşlarında olduğu gibi). WHEEL_UNIT_SCROLL Bir satır (unit) yukarı veya aşağı hareket ettirilmesi durumudur. (Yön tuşlarıyla sayfa hareketlerinde olduğu gibi). Bu olay sınıfının yapılandırıcı metodu aşağıdaki gibidir: MouseWheelEvent (Component kaynak, int id, long zaman, int belirtec, 1 int x, int y, int tikSayisi, int tetikleyici, int kaydirmaTipi, int kaydirmaAdedi, int donusSayisi) Bu olay sınıfının MouseEvent olay sınıfının alt sınıfı olduğunu belirtmiştik. Dolayısıyla yukarıdaki parametreleri çoğu MouseEvent olayında bahsedildiği gibidir. Farklı olan parametrelerden kaydirmaTipisayfanın satır satır veya sayfa sayfa kaydırılma tiplerinden birini ifade eder. kaydirmaAdedi, satır satır kaydırma için kaç satır kaydırıldığını gösterir. donusSayisi ise tekerleğin kaç tur çevrildiğini gösterir. Bu olay sınıfının en çok kullanılan metotlarından bazıları ve bu metotların amaçları aşağıdaki gibidir: getScrollAmount(): Olay içerisinde kaç satır çevrildiğini döndürür. getScrollType(): Yukarıda bahsettiğimiz kaydırma tiplerinden birini verir(Satır kaydırma veya sayfa kaydırma). getWheelRotation(): Olay içerisinde fare tuşunun kaç tur çevrildiğini verir. TEXTEVENT Metin nesnelerinin içeriğinin değişimini belirten olay sınıfıdır. Olay tipini belirlemek için tek bir değişken sınıf içerisinde tanımlanmıştır. Bu değişken şöyledir. TEXT_VALUE_CHANGED: Metin nesnesinin içeriğinin değiştiğini belirten durumdur. Bu olay sınıfının yapılandırıcı metodu aşağıdaki gibidir: 1 TextEvent(Component kaynak, int id) Burada kaynak olayı başlatan bileşendir. id ise olayımızın tipidir. WINDOWEVENT Bu olay sınıfı adından da anlaşılacağı üzere pencere olaylarını kontrol eder. Bu olayları birbirinden ayırmak için sınıf içerisinde bir takım değerler tanımlanmıştır. Bunlar şöyledir: WINDOW_ACTIVATED WINDOW_CLOSED WINDOW_OPENED Pencerenin etkinleştirilmesi durumu Pencerenin kapatılması durumu Pencerenin açılması durumu Pencerenin kapatılması için etkileşimde WINDOW_CLOSING bulunuldu Pencerenin etkin özelliğini yitirmesi WINDOW_DEACTIVATED durumu Pencerenin simge durumuna getirilmesi WINDOW_ICONFIED durumu Pencerenin simge durumunun iptal edilmesi WINDOW_DEICONFIED durumu Pencerenin odak özelliğini kaybetmesi WINDOW_LOST_FOCUS durumu Pencerenin durumunun değişmesi durumu WINDOW_STATE_CHANGED (Boyutu veya konumu gibi) Pencerenin odak özelliğini geri kazanması WINDOW_GAINED_FOCUS durumu Bu olay sınıfının en çok yapılandırıcı metotları aşağıdaki gibidir: WindowEvent (Component kaynak, int id) WindowEvent (Component kaynak, int id, int eskiDurum, int yeniDurum) WindowEvent (Component kaynak, int id, Window diger) WindowEvent (Component kaynak, int id, Window diger, int eskiDurum, int yeniDurum) Burada kaynak olayı başlatan pencere nesnesi, id olayımızın tipi, diger etkinleştirme veya odak olayı oluştuğunda gösterilecek pencere, eskiDurum pencerenin eski durumunu ve yeniDurum ise pencerenin yeni oluşacak durumunu ifade eder. Bu sınıfın en çok kullanılan bazı metotları ve bu metotların amaçları aşağıdaki gibidir: getWindow(): Olayı başlatan pencere nesnesini döndürür. getOldState(): Pencerenin WINDOW_STATE_CHANGED değeri değişmeden önceki durumunu döndürür. getNewState(): Pencerenin WINDOW_STATE_CHANGED değeri değiştikten sonraki durumunu döndürür. Ders 135 - Olay Dinleyicileri (Event Listeners) Daha önceden bir olayın yapısının 4 unsurdan oluştuğundan bahsetmiştik. Bir olayın gerçekleşebilmesi için en önemli olan iki unsurdan biridir dinleyiciler. Olay dinleyicileri olay kaynaklarından aldığı etkileşimleri uygun olay metoduna aktarır. Etkileşimden sonra metot altındaki kod parçası çalışır. Bu bölümde olay dinleyicilerini ve bunların sağladıkları metotları yüzeysel olarak anlatmaya çalışacağız. ACTIONLISTENER Bu dinleyici, herhangi bir eylem olayı gerçekleşme durumunu kontrol eder. Bu dinleyici genel olarak bir tane metot sunar. Bu metot ve metodun yapısı aşağıdaki gibidir: actionPerformed (ActionEvent ae): Eylem olayı gerçekleştiğinde çağrılır. ADJUSTMENTLISTENER Bu dinleyici, ayarlama olaylarını kontrol eder. Bu dinleyici birimi genel olarak bir tane metot sunar. Bu metot ve yapısı aşağıdaki gibidir: adjustmentValueChanged (AdjustmentEvent ae): Olayı çağıran bileşenin ayarlama değeri değiştiğinde çağrılır. COMPONENTLISTENER Bu dinleyici, bir bileşenin üzerine yapılan etki olaylarını kontrol eder. Dinleyici bize genel olarak dört adet metot sunar. Bu metotlar ve yapıları aşağıdaki gibidir. componentResized (ComponentEvent ce): Bileşen yeniden boyutlandırıldığında çağrılır. componentMoved (ComponentEvent ce): Bileşenin konumu değiştiğinde çağrılır. componentShown (ComponentEvent ce): Bir bileşen aktifleştirildiğinde çağrılır. componentHidden (ComponentEvent ce): Bir bileşen gizlendiğinde çağrılır. CONTAINERLISTENER Container nesnemize bileşen eklenildiğini veya çıkarıldığını kontrol eden dinleyici birimidir. Bu dinleyici sınıfı bize iki metot sunar. Bunlar ve amaçları şöyledir: componentAdded (ContainerEvent ce): Container nesnemize bir bileşen eklenildiğinde çağrılır. componentRemoved (ContainerEvent ce): Container nesnemizden bir bileşen çıkarıldığında çağrılır. FOCUSLISTENER Bu dinleyici birimi, olayı çağıran nesne odak kazandığında veya odak kaybettiğinde çalışır. Bize iki adet metot sunar. Bunlar ve bu metotların yapıları aşağıdaki gibidir: focusGained (FocusEvent fe): Olayı başlatan nesne odak aldığında çağrılır. focusLost (FocusEvent fe): Olayı başlatan nesne odak kaybettiğinde çağrılır. ITEMLISTENER Bu dinleyici birimi, bir öğenin durumunun değişip değişmediğini kontrol eden birimdir. ItemListener bize tek bir metot sunar. Bu metot ve yapısı aşağıdaki gibidir: ItemStateChanged (ItemEvent ie): Öğe durumu değiştiğinde çağrılır. KEYLISTENER Bu dinleyici birimi klavye tuşlarına basılıp basılmadığını kontrol eder. Bu dinleyici sınıfı üç metot sunar. Bu metotlar ve metotların amaçları aşağıdaki gibidir. keyPressed (KeyEvent ke): Klavyeden bir tuşa basıldığında çağrılır. keyReleased (KeyEvent ke): Klavyeden basılan tuş serbest bırakıldığında çağrılır. keyTyped (KeyEvent ke): Klavyeden bir karakter girildiğinde çağrılır. MOUSELISTENER Bu dinleyici arabirimleri farenin tuşlarına basılma olayını kontrol eder. Bu dinleyici sınıfı beş metot sunar. Bu metotlar ve görevleri aşağıdaki gibidir: mouseClicked (MouseEvent me): Farenin tuşuna basılıp serbest bırakılma (tıklanma) durumu gerçekleştiğinde çağrılır. mouseEntered (MouseEvent me): Fare bir bileşenin üzerine geldiğinde çağrılır. mouseExited (MouseEvent me): Fare üzerinde olduğu bir bileşenden ayrıldığında, bu metot çağrılır. mousePressed (MouseEvent me): Farenin tuşuna basıldığında çağrılır. mouseReleased (MouseEvent me): Farenin bir tuşu basılı durumdan serbest bırakılma durumuna geçtiğinde çağrılır. MOUSEMOTIONLISTENER Bu dinleyici birimi, fenerin hareketlerini kontrol eden birimdir. Bu dinleyici sınıfı iki metot sunar. Bu metotlar ve metoların görevleri aşağıdaki gibidir: mouseDragged (MouseEvent me): Fare tuşuna basılı durumda sürüklendiği zaman çağrılır. mouseMoved (MouseEvent me): Fare tuşu basılı olmadan sürüklendiği durumlarda çağrılır. MOUSEWHEELLISTENER Bu dinleyici birimi, fare tekerleğinin hareket ettirilmesini kontrol eden birimdir. Bu sınıf bize bir metot sunmaktadır. Bu metot ve yapısı aşağıdaki gibidir: mouseWheelMoved (MouseWheelEvent mwe): Fare tekerleği hareket ettiği durumda çağrılır. TEXTLISTENER Bu dinleyici birimi, metin nesnelerinde veya metin tabanlı bileşenlerdeki metin değişimlerini kontrol eden birimdir. Bu dinleyici sınıfı bize bir metot sunar. Bu metot ve metodumuzun görevi aşağıdaki gibidir: textChanged(TextEvent te): Metin değişimi durumlarında çağrılır. WINDOWFOCUSEDLISTENER Bu dinleyici birimi, pencerenin odak kazandığı veya odak kaybettiği durumlarda tetiklenir. Bu birim bize iki metot sunar. Bu metotlar ve metotların görevleri aşağıdaki gibidir: windowGainedFocus (WindowEvent we): Pencere odak kazandığı durumda çağrılır. windowLostFocus (WindowEvent we): Pencere odak kaybettiği durumda çağrılır. WINDOWLISTENER Bu dinleyici birimi, pencere ile ilgili olayları kontrol eden birimdir. Bu birim içerisinde bize yedi tane metot sunulur. Bu metotlar ve metotların görevleri aşağıdaki gibidir. windowActivated (WindowEvent we): Pencere etkinleştirildiğinde çağırılır. windowDeactivated (WindowsEvent we): Pencere aktifliğini kaybettiğinde çağırılır. windowClosed (WindowEvent we): Pencere kapandığında çağırılır. windowClosing (WindowEvent we): Pencere kapatılmak için etkileşimde bulunduğunda çağrılır. windowOpened (WindowEvent we): Pencere açıldığında çağırılır. windowIconfied (WindowEvent we): Pencere simge durumuna getirildiğinde çağırılır. windowDeiconfied (WindowEvent we): Pencere simge durumundan geri getirildiğinde çağırılır. Ders 136 - Fare ve Klavye Olay Metodlarının Kullanımı Bu dersimizde en çok kullanılan olaylar olan fare ve klavye olaylarına örnek vereceğiz. Daha önceki derslerimizde de anlattığımız gibi fare MouseListener, MouseMotionListener ve MouseWheelListenerdinleyic i sınıflarını kullanmaktaydı. Klavye olaylarında ise sadece KeyListener olayı, klavye durumlarını karşılıyordu. Şimdi öncelikle klavye daha sonra farenin en çok kullanılan olaylarına örnek verelim. 1 //klavyeOlayOrnekleri.java - 24.04.2014 2 3 import java.awt.EventQueue; 4 import java.awt.event.KeyEvent; 5 import java.awt.event.KeyListener; 6 7 import javax.swing.JFrame; 8 import javax.swing.JLabel; 9 10 public class klavyeOlayOrnekleri extends JFrame implements 11 KeyListener 12 { 13 // implement edildi 14 JLabel etiket = new JLabel("etiket"); 15 String metin = ""; 16 17 public static void main(String[] args) 18 { 19 EventQueue.invokeLater( 20 new Runnable() 21 { 22 public void run() 23 { 24 try 25 { 26 klavyeOlayOrnekleri init = new 27 klavyeOlayOrnekleri(); 28 init.setVisible(true); 29 } 30 catch (Exception e) 31 { 32 e.printStackTrace(); 33 } 34 } 35 }); 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 } } // bileşenlerimizi yapılandıran metod public klavyeOlayOrnekleri() { super("Klavye Olayları"); add(etiket); // bileşenimiz çerçevemize eklendi addKeyListener(this); // olay dinleyicimiz eklendi. setSize(550, 100); } @Override public void keyPressed (KeyEvent ke) { metin += "Klavyeden bir tuşa basıldı -"; etiket.setText(metin); } @Override public void keyReleased (KeyEvent ke) { metin += "Klavyeden basılan tuş serbest bırakıldı."; etiket.setText(metin); } @Override public void keyTyped (KeyEvent ke) { char tus = ke.getKeyChar(); metin += "Klavyeden basılan tuş : " + tus + " - "; etiket.setText(metin); } Yukarıdaki örnekte GUI bileşenlerini kullandık. Bir sonraki konuda GUI bileşenleri ve bunların nasıl yapılandırılacağını anlatılcaktır. Metotların anlatımına geçmeden önce sınıfımızın KeyListener dinleyici sınıfını implement aldığına dikkat edelim. Bileşenlerimizi yapılandıran yapıcı metodumuz içerisinde bileşenlerimizi ekledikten sonra, KeyListenerdinleyici sınıfımızı çerçevemize ekledik. KeyListener sınıfı bundan sonra çerçevemiz içerisinde gerçekleşecek klavye olaylarını dinleyecek. Daha sonra bu dinleyici sınıfının bize sunduğu metotları kullandık. Daha öncede anlattığımız gibi keyPressed() metodu, klavyeden bir tuşa basıldığı anda çalışıyor, keyReleased() metodu klavyeden basılan tuş serbest bırakıldığında çrğrılıyor ve keyTyped() ise klavyeden bir karakter girildiğinde çalışıyordu. Yukarıdaki olay klavyeden h tuşuna basıldığında gerçekleşmiştir. Örnek sayesinde olay metotlarımızın sırasının nasıl olduğunu görmüş oluyoruz. Şimdi fare olay metotlarını kullanacağımız bir örnek yapalım. 1 //fareOlayOrnekleri.java - 24.04.2014 2 3 import java.awt.Container; // java.awt.*; 4 import java.awt.EventQueue; 5 import java.awt.GridLayout; 6 import java.awt.event.MouseEvent; 7 import java.awt.event.MouseListener; 8 import java.awt.event.MouseMotionListener; 9 10 import javax.swing.JFrame; 11 import javax.swing.JLabel; 12 13 public class fareOlayOrnekleri extends JFrame implements 14 MouseListener, MouseMotionListener 15 { 16 JLabel etiket1 = new JLabel("etiket1"); 17 JLabel etiket2 = new JLabel("etiket2"); 18 19 public static void main(String[] args) 20 { 21 EventQueue.invokeLater( 22 new Runnable() 23 { 24 public void run() 25 { 26 try 27 { 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 fareOlayOrnekleri init = new fareOlayOrnekleri(); init.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } // bileşenlerimizi yapılandıran metod public fareOlayOrnekleri() { super("Fare Olayları"); Container con = getContentPane(); setLayout(new GridLayout()); con.add(etiket1); con.add(etiket2); // bileşenlerimiz çerçevemize eklendi addMouseListener(this); addMouseMotionListener(this); // olay dinleyicilerimiz eklendi setSize(550, 100); } @Override public void mouseDragged(MouseEvent me) { etiket1.setText("Fare sürüklendi."); } @Override public void mouseMoved(MouseEvent me) { etiket1.setText("Farenin yeri değişti."); int x = me.getX(); int y = me.getY(); etiket2.setText("Fare koordinatları X:" + x + " Y:" + y); } @Override public void mouseClicked(MouseEvent me) { etiket1.setText("Fare tıklandı."); } @Override 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 } 94 public void mouseEntered(MouseEvent me) { etiket1.setText("Fare etki altına girdi."); } @Override public void mouseExited(MouseEvent me) { etiket1.setText("Fare etki alanından çıktı."); } @Override public void mousePressed(MouseEvent me) { etiket1.setText("Fare butonuna basıldı."); } @Override public void mouseReleased(MouseEvent me) { etiket1.setText("Fare butonu serbest bırakıldı."); } Uygulamamızda yine daha önceki uygulamamızda kullandığımız gibi GUI bileşenlerini kullandık. Yapıcı metodumuz içerisinde fare dinleyicilerimizi ekledik. Bundan sonraki kısımda olay gerçekleştiğinde çağrılacak metotları yazdık. Ders 137 - GUI (Graphical User Interface) Nedir? GUI'yi Türkçeye Grafiksel Kullanıcı Arayüzü olarak çevirebiliriz. GUI, Java'da form kontrollerini kullandığımız görsel kısımdır. GUI ile kullanıcılar fare ve form kontrolleri sayesinde uygulamayı daha kolay kullanabilirler. Şimdiye kadar önceki derslerimizde yaptığımız uygulamaları konsol üzerinden yaptık. Profesyonel uygulamalarda konsol ortamı tercih edilmez. Bu yüzden grafiksel arayüzü öğrenmeyi bizim için bir zorunluluk olarak sayabiliriz. GUI bileşenlerini Eclipse üzerinden anlatacağımızı daha önceden belirtmiştik. Standart Eclipse kurulumunda GUI bileşenleri bulunmamaktadır. Bu yüzden bir sonraki bölümde Eclipse üzerinde GUI kurulumunu anlatacağız. Ders 138 - GUI Kurulumu Eclipse üzerinde GUI ile uygulama geliştirebilmek için birden fazla Plugin bulunmaktadır. Biz bu bölümdeSwing Plug-in'lerini kullanacağız. Bu bileşenleri kurabilmek için internet bağlantısı gerekecetir. Kuruluma geçmeden önce internet bağlantınızı kontrol ediniz. Eclipse'e Swing Plug-in'lerini kurabilmek için Eclipse üzerinden Help menüsünden Install New Softwareseçeneğini seçiyoruz. Daha sonra karşımıza aşağıdaki şekildeki gibi bir pencere açılacak. Bu pencerede Work with bölümünde açılır seçenek menüsünden --All Available Sites-- seçeneğini seçtikten sonra, alt pencereye seçeneklerin gelmesi için bir süre beklememiz gerekecektir. Bir süre bekledikten sonra menümüze aşağıdaki şekildeki gibi seçenekler gelecektir. Listedeki seçenekler arasından General Purpose Tools seçeneğini bulup, seçeneğimizi genişletmek için yanındaki üçgen işaretine tıklayalım. Seçeneklerimizi genişlettikten sonra alt seçenekler arasından aşağıdaki şekildeki seçenekleri bulup işaretleyelim. Alt seçeneklerimizi seçtikten sonra bir sonraki aşamaya geçmek için menümüzden Next butonuna tıklayalım. Bir sonraki adımda karşımıza kuracağımız bileşenleri gösteren özet sayfası çıkacaktır. Next butonuna tıklayıp bir sonraki aşamaya geçelim. Bu bölümde karşımıza kurulum sözleşmesi çıkacaktır. Kurulum sözleşmesini onaylayıp Finish butonuna tıklayalım. Bu bölümden sonra Eclipse bizim için bileşenleri internetten indirip kuracaktır. Bileşenlerin indirilip kurulması tamamlandıktan sonra Eclipse'yi yeniden başlatın. Eclipse'yi yeniden başlattıktan sonra GUI bileşenleri kullanıma hazır olacaktır. Ders 139 - GUI Projesi Oluşturma Java'da GUI projesi iki yöntemle oluşturulabilir. Birincisi ve en çok kullanacağımız yöntem; Eclipse IDEüzerinden oluşturmaktır. İkincisi ise GUI projesini oluşturduğumuz sınıfın Java form bileşenlerini kod yardımıyla miras alma yöntemidir. Bu dersimizde ikisine de örnek vererek açıklamaya çalışacağız. Şimdi derleyicinin bizim için otomatik kod oluşturmasına örnek verelim. İlk olarak yukarıdaki resimdeki gibi bir Java projesi oluşturmak için proje oluşturma penceresini açıyoruz. Daha sonrasında açılan pencerede projemize isim verip, Finish butonuyla projemizi oluşturuyoruz. Projemiz yukarıdaki resimde görüldüğü gibi oluşturuldu. Projemiz içerisinde başlangıç olarak projemizin kodlarının bulunacağı src (source) klasörünü ve varsayılan olarak gelen Java sistem kütüphanelerinigörüyoruz. Daha sonrasında src klasörümüz seçili iken resimdeki gibi projemize Swing menüsü altından JFramebileşenini ekliyoruz. Açılan pencerede ilk bölümde JFrame nesnemizin ekleneceği kaynak klasör, ikinci bölümde paket ismimiz, üçüncü bölümde JFrame nesnemize vereceğimiz isim ve üst sınıf bilgisi bulunuyor. Biz bu kısımda sadece ikinci ve üçüncü bölüme isim vereceğiz. Paket ismimizi ve JFrame nesnemizin ismini belirledikten sonra, Finish butonuna basarak JFrame nesnemizi oluşturuyoruz. JFrame nesnemiz oluşturulduktan sonra şekildeki gibi projemize eklenecektir. JFrameFormu.javasınıfına çift tıkladığımızda aşağıdaki gibi bir kod yapısıyla karşılaşacağız. 1 package javaGuiProjemiz; 2 3 import java.awt.BorderLayout; 4 import java.awt.EventQueue; 5 6 import javax.swing.JFrame; 7 import javax.swing.JPanel; 8 import javax.swing.border.EmptyBorder; 9 10public class JFrameFormu extends JFrame { 11 12 private JPanel contentPane; 13 14 /** 15 * Launch the application. 16 */ 17 public static void main(String[] args) { 18 EventQueue.invokeLater(new Runnable() { 19 public void run() { 20 try { 21 JFrameFormu frame = new JFrameFormu(); 22 frame.setVisible(true); 23 } catch (Exception e) { 24 e.printStackTrace(); 25 } 26 } 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42} }); } /** * Create the frame. */ public JFrameFormu() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setLayout(new BorderLayout(0, 0)); setContentPane(contentPane); } Bu derleyicinin bizim için otomatik oluşturduğu bir kod parçasıdır. Biz bileşenleri menüden form üzerine bıraktıkça, derleyici bizim için bileşenleri form üzerinde otomatik yapılandıracak kod parçaları oluşturacaktır. Konu başlangıcında GUI projelerinin iki şekilde oluşturulabileceğini söylemiştik. İlk yöntem derleyicinin bizim için otomatik oluşturmasıydı. İkinci yöntem ise, yukarıdaki kodda görüldüğü gibi bileşenleri sınıf üzerinde miras alarak el ile oluşturma yöntemidir. Sınıfımızın başlangıcında JFrame bileşenini miras (extends) aldığına dikkatimizi verelim. Derslerimizde örneklerimizi daha çok kod üzerinden oluşturacağız dolayısıyla ikinci yöntemi daha sık kullanacağız. Sınıfımıza çift tıkladığımızda açılan pencerede, sol alt kısımdaki Source | Design sekmelerinden Designsekmesine tıklayarak, JFrame bileşeninin tasarımını görebiliriz. Ders 140 - Swing Swing bileşenleri Java'da GUI uygulamaları oluştururken kullanacağımız görsel bileşenlerdir. JavadaSwing bileşenlerinden önce AWT bileşenleri kullanılmaktaydı. AWT bileşenleri asıl amacına ulaşamayınca Java 2.0 ile Swing bileşenleri ortaya çıktı. Swing bileşenleri AWT üzerine kurulmuştur. Dolayısıyla Swing bileşenleri AWT metodlarını kullanmaktadır. Bu bölümde Swing bileşenlerine değineceğiz. Swing paketlerindeki sınıf ve bileşenlerin sayısı çok fazladır. Biz bu bölümde sadece bir kısmını inceleyeceğiz. SWING BİLEŞENLERİ Sonraki derslerimizde sırasıyla en fazla kullanılan Swing bileşenlerinin yapısını inceleyeceğiz ve bunlar hakkında örnekler yapacağız. Sırasıyla işleyeceğimiz bileşenler şunlardır. JFrame Container JLabel JButton JTextField JComboBox JRadioButton JCheckBox JToggleButton JTable JList JScrollPane JTabbbedPane Ders 141 - JFrame Java bileşenlerine geçmeden önce JFrame nesnesini ve bu nesnesinin metodlarını öğrenmeliyiz. JFramenesnesi, üzerinde GUI bileşenlerini tutar ve temel pencere metodları ile pencere olaylarınıngerçekleştirilmesini sağlar. Bundan sonra işleyeceğimiz bütün görsel nesneler bu bileşen üzerinde konumlandırılacaktır. Bir örnek üzerinden JFrame bileşenimizi anlatmaya devam edelim. 1 //JFrameOrnegi.java - 25.04.2014 2 3 import javax.swing.*; 4 5 public class jFrameOrnegi extends JFrame 6 { 7 public jFrameOrnegi() 8 { 9 super("Pencere bileşinimiz"); 10 // üst sınıfımızın yapılandırıcısını çağırdık 11 12 this.setSize(300, 400); 13 // penceremizin boyutunu ayarladık 14 this.setAlwaysOnTop(true); 15 // bu metod ile pencerenin her zaman en üstte olması durumu 16 ayarlanır 17 this.setVisible(true); 18 // penceremizi görünür yaptık. 19 this.setResizable(false); 20 // penceremizin boyutlandırılabilir özelliğini false yaptık 21 this.setDefaultCloseOperation(EXIT_ON_CLOSE); 22 // kapama butonuna basıldığında pencerenin durumunu 23 belirtiyoruz 24 25 26 27 28 29 30 } } public static void main(String[] args) { jFrameOrnegi j = new jFrameOrnegi(); } Örneğimizde görüldüğü gibi bir pencere oluşturduk ve bu pencerenin özelliklerini JFrame sınıfının bize sağladığı metodlar yardımıyla değiştirdik. JFrame sınıfının metodları, bazı durumlarda bu bileşeni oluşturmaktan daha büyük öneme sahip olabilir. Bu bileşenin bazı önemli metodları ve bu metotların görevleri şöyledir. add(): Bu metot ile JFrame üzerinde bileşenler ekleyebiliriz. getContentPane(): Oluşturulan formun modelini getirir. getDefaultCloseOperation(): Formun kapama butonuna basıldığında nasıl davranacağı bilgisini verir. getLayout(): Bileşenin kullandığı Layout (yerleşim düzeni) bilgisini getirir. getMaximumSize(): Bileşenin alabileceği maksimum boyutu en boy cinsinden gönderir. getMinimumSize(): Bileşenin alabileceği minimum boyutu en boy cinsinden gönderir. getSize(): Bileşenin anlık boyutunu en boy cinsinden gönderir. getTitle(): Bileşenin başlık bilgisini gönderir. isAlwaysOnTop(): Pencerenin her zaman üstte olma durumunu boolean değer tipinde geri döndürür. isResizable(): Pencerenin boyutlandırılabilir olup olmadığı bilgisini boolean değer tipinde geri döndürür. isVisible(): Pencerenin görünürlük durumunu boolean değer tipinde geri döndürür. setAlwaysOnTop (boolean deger): Pencerenin her zaman üstte olma durumunu ayarlar. setBounds (int x, int y, int en, int boy): Bu metot, bileşenlerin ekleneceği koordinatları ve bileşenin boyutlarını ayarlar. Metot parametrelerinde x eklenilecek bileşenin x eksenindeki noktası, y ise y eksenindeki noktasıdır. Diğer parametrelerden en ve boy ise bileşenin en ve boy özelliklerini ayarlar. setDefaultCloseOperation (int operation): Bu metot, kapama butonuna basıldığında formun nasıl davranacağını belirtir. Metodun parametresi sınıf içerisinde tanımlı sabitlerdir. Bu sabitlerden bazıları ve görevleri şöyledir: o EXIT_ON_CLOSE: Formun kapanmasını sağlar. o DISPOSE_ON_CLOSE: Formun kapanmasın sağlar. EXIT_ON_CLOSE'dan farkı ise, bu sabit ile tanımlanan form kapanırsa tüm program kapanmaz. EXIT_ON_CLOSE ile tanımlanan form kapandığında bütün pencereler kapanacaktır. o DO_NOTHING_ON_CLOSE: Kapama butonuna basıldığında hiç bir olay gerçekleştirilmez. o HIDE_ON_CLOSE: Pencereyi gizler. RAM üzerindeki bilgileri tutar ve kullanıcının pencereyi tekrar çağırmasını bekler. Kullanıcı tekrar çağırana kadar pencere bilgileri hazır olarak bekletilir. setResizable (boolean deger): Pencerenin boyutlandırılabilir özelliğini ayarlar. setSize (int en, int boy): Pencerenin boyutlarını en boy cinsinden belirler. setVisible (boolean deger): Pencerenin görünürlük özelliğini ayarlar. Ders 142 - Container Container nesneleri, bileşenleri üzerinde tutmaya yararlar. Ders 141 JFrame dersinde JFrame'i anlatırken nesneleri üzerinde tutabileceğinden bahsetmiştik. JFrame bileşeni, tüm bileşenleri aynı özellikte tutar. Yani aynı yerleşim düzeninde veya aynı arkaplan resmiyle birlikte tutar. Container bileşenini ise bu noktata bileşenlerin durumunu özelleştirmek için kullanabiliriz. Container bileşenlerini aşağıdaki örnekteki gibi oluşturabiliriz. 1 //containerOrnegi.java - 25.04.2014 2 3 import java.awt.BorderLayout; 4 import java.awt.Container; 5 import java.awt.GridLayout; 6 7 import javax.swing.*; 8 9 public class containerOrnegi extends JFrame 10 { 11 public containerOrnegi() 12 { 13 super("Formumuz"); 14 Container con = getContentPane(); 15 // container bileşenini oluşturduk ve formumuzun modelini bu bileşen 16 içerisine aldık 17 con.setLayout(new BorderLayout()); 18 // bileşenimizin yerleşim tipini belirledik 19 con.add(new JLabel("etiket bileşeni1")); 20 // bileşen içerisine etiket bileşenini ekledik 21 Container con2 = getContentPane(); 22 // yine bir container bileşeni oluşturduk ve formumuzun modelini 23 aldık 24 con2.setLayout(new GridLayout()); 25 // bileşenimizin yerleşim tipini belirledik 26 con2.add(new JLabel("etiket bileşeni2")); 27 // bileşen içerisine etiket ekledik. 28 setVisible(true); 29 setSize(300, 300); 30 // formumuzun özelliklerini ayarladık 31 } 32 33 public static void main(String[] args) 34 { 35 containerOrnegi c = new containerOrnegi(); 36 } 37 } Ders 143 - JLabel JLabel, Swing bileşenlerinin en temel bileşenlerindendir. Gayet basit bir yapısı vardır. Belki de en çok kullanacağımız bileşen JLabel'dir. JLabel bileşeni en temel olarak etiket görevi görür. Çoğu zaman JLabel bileşeninin Text özelliğinden yararlanarak, diğer Swing bileşenlerinin görevini belirtmek için kullanırız. Yazacağımız bazı uygulamalardaJLabel bileşeninin Text özelliğinin değiştirmemiz gerekecektir. Şimdi JLabel bileşeninin kullanımını ve bazı özelliklerini işleyeceğimiz bir örnek yapalım. 1 //JLabelOrnegi.java - 25.04.2014 2 3 import java.awt.Container; 4 import java.awt.EventQueue; 5 import java.awt.GridLayout; 6 7 import javax.swing.JFrame; 8 import javax.swing.JLabel; 9 10 public class JLabelOrnegi extends JFrame 11 { 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 // uygulamalar başlatılıyor public static void main(String[] args) { EventQueue.invokeLater (new Runnable() { public void run() { try { JLabelOrnegi frame = new JLabelOrnegi(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } // bileşenleri yapılandıran metod public JLabelOrnegi() { super("JLabel Örneği"); Container con = getContentPane(); con.setLayout(new GridLayout()); /* Başlığı "JLabel Örneği" olan bir pencere oluşturduk ve üzerine bir yerleşim ekledik. */ JLabel lblNewLabel = new JLabel("JLabel kullanımı örneği"); con.add(lblNewLabel); JLabel lblNewLabel1 = new JLabel("İlk Swing bileşeni örneğimiz"); con.add(lblNewLabel1); setSize(400, 200); setVisible(true); /* yeni bir JLabel bileşeni oluşturduk ve bu bileşeni daha önceden oluşturduğumuz pencere üzerine ekledik, pencerenin boyutunu belirledik */ } } İlk olarak main metodumuz içerisinde bileşenlerimizi yapılandıracak metodu çağırdık. Bu metod içerisinde önce super() metodu ile penceremizin başlığını belirledik. Daha sonrasında bir Container nesnesi oluşturup bu nesnenin yerleşimini GridLayout olarak ayarladık. Bundan sonraki kısımda iki adet JLabel bileşeni oluşturduk ve JLabel bileşenlerimizin Text özelliğini yapılandırıcı metod yardımıyla belirledik. Oluşturduğumuz bu bileşenlerin Text özelliğini belirledikten sonra Container nesnemize ekledik. Son olarak çerçevemizinboyutunu ve görünürlük özelliğini de belirledikten sonra işlemi sonlandırdık. JLabel bileşenlerimizin Text özelliklerini yapılandırıcı metot ile belirlediğimizi bir önceki paragrafta söylemiştik. Bu bileşenimizin Text özelliğini farklı bir metot ile değiştirmek mümkündür. setText() metodu yardımıyla JLabel bileşenimizin Text özelliğini değiştirebilir. getText() metodu yardımıyla JLabel bileşenimizin mevcut Text özelliğini String olarak getirebiliriz. Metotların nasıl kullanıldığını görmek adına yapılandırıcı metodumuzu değiştirerek bir örnek yapalım. 1 //JLabelOrnegi2.java - 25.04.2014 2 3 import java.awt.Container; 4 import java.awt.EventQueue; 5 import java.awt.GridLayout; 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 import javax.swing.JFrame; import javax.swing.JLabel; public class JLabelOrnegi2 extends JFrame { // uygulamalar başlatılıyor public static void main(String[] args) { EventQueue.invokeLater (new Runnable() { public void run() { try { JLabelOrnegi2 frame = new JLabelOrnegi2(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } // bileşenleri yapılandıran metod public JLabelOrnegi2() { super("JLabel Örneği"); Container con = getContentPane(); con.setLayout(new GridLayout()); /* Başlığı "JLabel Örneği" olan bir pencere oluşturduk ve üzerine bir yerleşim ekledik. */ JLabel lblNewLabel = new JLabel("JLabel kullanımı örneği"); con.add(lblNewLabel); JLabel lblNewLabel1 = new JLabel("İlk Swing bileşeni örneğimiz"); con.add(lblNewLabel1); JLabel lblNewLabel2 = new JLabel(); lblNewLabel2.setText(lblNewLabel.getText()); con.add(lblNewLabel2); setSize(600, 200); setVisible(true); 53 /* yeni bir JLabel bileşeni oluşturduk ve bu bileşeni daha 54 önceden 55 oluşturduğumuz pencere üzerine ekledik, pencerenin boyutunu belirledik */ } } Metotların anlaşılması için daha önceden yazdığımız kodda ufak değişiklikler yaptık. Daha önceden yapılandırıcı metot sayesinde belirlediğimiz JLabel bileşenimizin Text özelliğini burada setText() metodu ile belirledik. Daha sonrasında üçüncü bir JLabel bileşeni oluşturduk ve bu bileşenin Text özelliğini ilk oluşturduğumuz JLabel bileşenimizin Text özelliğini getText() metodu ile getirerek bu bileşenimize aktardık. Ders 144 - JButton Bu bileşenimiz tetikleyici bir bileşendir. .NET platformundaki Button bileşeninin Java platformundaki karşılığıdır. JButton bileşeni üzerinde metin veya resim gibi nesneleri tutabilir. JButton bileşenine tıklandığında ActionListener()'ın actionPerformed olayı tetiklenir. Bu olay tetiklendiği anda, altında bulunan kod satırlarını işleme koyar. Buton bileşeni üzerine komut eklemek istediğimizdesetActionCommand() metodunu kullanırız. Bu komutu daha sonradan elde etmek istediğimizde olay nesnesi içerisinde getActionCommand() metodu yardımıyla, üzerine tıklanılan butonun komutunu elde edebiliriz. Şimdi buton bileşenini daha iyi anlayabilmek için bir örnek yapalım. 1 //JButtonOrnegi.java - 25.04.2014 2 3 import java.awt.Container; 4 import java.awt.EventQueue; 5 import java.awt.GridLayout; 6 import java.awt.event.ActionEvent; 7 import java.awt.event.ActionListener; 8 9 import javax.swing.JButton; 10 import javax.swing.JFrame; 11 import javax.swing.JLabel; 12 13 public class JButtonOrnegi extends JFrame implements 14 ActionListener 15 { 16 JLabel etiket = new JLabel("Sonuç burada olacak."); 17 // uygulama başlatılıyor 18 public static void main(String[] args) 19 { 20 EventQueue.invokeLater( 21 new Runnable() 22 { 23 public void run() 24 { 25 try 26 { 27 JButtonOrnegi cerceve = new JButtonOrnegi(); 28 cerceve.setVisible(true); 29 } 30 catch (Exception e) 31 { 32 e.printStackTrace(); 33 } 34 } 35 }); 36 } 37 // bileşenler yapılandırılıyor. 38 39 public JButtonOrnegi() 40 { 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 super("JButton Örneği"); Container con = getContentPane(); setLayout(new GridLayout()); // container nesnesi oluşturup yerleşim tipimizi belirledik JButton dugme = new JButton("6 + 2"); dugme.setActionCommand("+"); dugme.addActionListener(this); con.add(dugme); /* ilk butonumuzu oluşturduk sonrasında butonumuza komut verip container nesnesine ekledik */ dugme = new JButton("6 * 2"); dugme.setActionCommand("*"); dugme.addActionListener(this); con.add(dugme); /* ikinci butonumuzu oluşturduk sonrasında butonumuza komut verip container nesnesine ekledik */ dugme = new JButton("6 / 2"); dugme.setActionCommand("/"); dugme.addActionListener(this); con.add(dugme); /* üçüncü butonumuzu oluşturduk sonrasında butonumuza komut verip container nesnesine ekledik */ con.add(etiket); setSize(600, 100); setVisible(true); // JLabel bileşenimizi ekledik ve çerçeve boyutunu belirledik } // düğme tıklandığında gerçekleşecek olay @Override public void actionPerformed(ActionEvent e) { String text = e.getActionCommand(); int sayi1 = 6; int sayi2 = 2; if (text.equals("+")) { 87 etiket.setText("Sonuç: " + String.valueOf(sayi1 + 88 sayi2)); 89 } 90 else if (text.equals("*")) 91 { 92 etiket.setText("Sonuç: " + String.valueOf(sayi1 * 93 sayi2)); 94 } else if (text.equals("/")) { etiket.setText("Sonuç: " + String.valueOf(sayi1 / sayi2)); } } } Bu örneğimizde diğerlerinden farklı olarak örneğimize ActionEvent kullanacağımız için örneğimizin bu sınıfıimplement etmesini sağladık. Kodumuzda ilk önce ana sınıfımızı oluşturduk ve bu ana sınıfımız içerisinde bileşenlerimizi yapılandıracak sınıfımız içerisinde yine ilk olarak bir Container nesnesi oluşturduk ve yerleşim tipimizi belirledik. Daha sonrasında butonlar oluşturarak bunların komutlarını belirledik ve butonlarımızıçerçevemize ekledik. Butonlarımızı oluşturup komutlarını belirledikten sonra, hepsine ActionListenereklediğimize dikkat edelim. Bundan sonraki kısımda butona tıklanıldığında gerçekleşecek olayın ayrıntılarını belirledik. Butona tıklandığında ActionListener'in actionPerformed olayının tetiklendiğinden bahsetmiştik.actionPeformed olayımızın içerisine çalışacak kodları yazdık. Buna göre eğer buton bileşenimizin komutu + ise uygulama iki sayıyı toplayıp JLabel bileşeni üzerinde gösterecek. Diğer durumlarda da komuta göre işlem değişecek. Yukarıdaki örneği geliştirerek bir hesap makinası yapmamız mümkündür. Butonların komut özelliğine sayılar için sayı değerlerini ve işlemler için işlem tiplerini vererek basit bir hesap makinası geliştirebiliriz. Ders 145 - JTextField JTextField, Java'da belki de en çok kullanacağımız swing bileşeni olacaktır. En genel kullanımı, kullanıcıdan veri girilmesi istenildiği durumdur. JTextField bileşeninin içeriğini getText() metodu yardımıyla almamız mümkündür. JTextField, .NET platformundaki TextBox bileşeninin Java platformundaki karşılığıdır. Şimdi JTextFieldbileşeninin kullanımını daha iyi anlayabilmek için bir örnek yapalım. Aşağıdaki örnek iki JTextField'e girilen sayıları sınır olarak alır ve bu sınırlar arasındaki asal sayıların adedini bulup, JLabel bileşenine aktarır. 1 //JTextFieldOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 import java.awt.event.*; 5 // bu örneğimizde awt nin içindeki tüm sınıfları * ile aldık. 6 import javax.swing.*; 7 8 public class JTextFieldOrnegi extends JFrame implements 9 ActionListener 10 { 11 JLabel etiket; 12 JTextField metinKutusu1; 13 JTextField metinKutusu2; 14 JButton dugme; 15 16 // uygulama başlatılıyor 17 public static void main(String[] args) 18 { 19 EventQueue.invokeLater( 20 new Runnable() 21 { 22 public void run() 23 { 24 try 25 { 26 JTextFieldOrnegi cerceve = new 27 JTextFieldOrnegi(); 28 cerceve.setVisible(true); 29 } catch (Exception e) 30 { 31 e.printStackTrace(); 32 } 33 } 34 }); 35 } 36 // bileşenler yapılandırılıyor 37 public JTextFieldOrnegi() 38 { 39 super("JTextField Örneği"); 40 Container con = getContentPane(); 41 setLayout(new GridLayout()); 42 // container nesnesi oluşturup yerleşim tipimizi belirledik 43 etiket = new JLabel("Sonuç burada olacak"); 44 con.add(etiket); 45 // etiketi oluşturduk ve ekledik 46 metinKutusu1 = new JTextField(); 47 con.add(metinKutusu1); 48 metinKutusu2 = new JTextField(); 49 con.add(metinKutusu2); 50 // JTextField bileşenlerini oluşturup ekledik 51 52 dugme = new JButton("Asal sayıları bul"); 53 dugme.addActionListener(this); 54 con.add(dugme); 55 setSize(800, 100); 56 setVisible(true); 57 // JButton bileşenimizi oluşturup ActionListener ekledik 58 } 59 60 // butona tıklanıldığında bu olay çalışacak 61 @Override 62 public void actionPerformed(ActionEvent ae) 63 { 64 int ilk = Integer.parseInt(metinKutusu1.getText()); 65 int son = Integer.parseInt(metinKutusu2.getText()); 66 int asalSayisi = 0; 67 68 for (int i = ilk ; i <= son ; i++) 69 { 70 int bolenSayisi = 0; 71 for (int bolen = 2 ; bolen < i ; bolen++) 72 { 73 if(i % bolen == 0) 74 bolenSayisi++; 75 } 76 if (bolenSayisi == 0) 77 asalSayisi++; 78 } 79 etiket.setText("Bulunan asal sayı adedi: " + 80 String.valueOf(asalSayisi)); } } Kodumuzda yine her zaman yaptığımız gibi bir ana sınıf oluşturduk. Bu ana sınıf, bileşenlerimizi yapılandıracak metodu çağırdı. Bu metot içerisinde önce bir Container nesnesi oluşturup daha sonra yerleşim tipimizi belirledik. Daha sonra sırasıyla JLabel ve JTextField bileşenlerimizi oluşturup çerçevemize ekledik. Bundan sonraki kısımda JButton oluşturduk ve JButton'umuza ActionListener ekledik. ActionListenerolayımızın altına girilen sayılar arasındaki asal sayı adedini bulabilmek için kodlarımızı yazdık. JTextFieldbileşenimizin text özelliğini JLabel bileşenimizde olduğu gibi getText() metodu yardımıyla elde ettik. JLabelbileşenimize bulduğumuz sayıyı setText() metodu yardımıyla yazdırdık. Ders 146 - JComboBox JComboBox, yani açılır liste kutuları; adından da anlaşılacağı gibi bize açılır bir liste sunar. Aynı anda sadece bir eleman seçmemize izin verir. Seçili elemanın özelliklerini belirli metotlar yardımıyla almamız mümkündür. JComboBox seçili elemanın değişmesi durumunda diğer bileşenlerden farklı olarak bir olay tetiklenir. Bu olay itemStateChanged() olayıdır. Seçili eleman her değiştiğinde bu olay tetiklenir ve her seferinde olay altında yazılan kod parçaları çalışır. Şimdi JComboBox bileşenini ve bahsettiğimiz bu olayı anlayabilmek için bir örnek yapalım. 1 //JComboBoxOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 7 public class JComboBoxOrnegi extends JFrame implements 8 ItemListener 9 { 10 JLabel etiket; 11 JLabel etiket1; 12 JComboBox combo; 13 14 // uygulama başlatılıyor 15 public static void main(String[] args) 16 { 17 EventQueue.invokeLater( 18 new Runnable() 19 { 20 public void run() 21 { 22 try 23 { 24 JComboBoxOrnegi cerceve = new 25 JComboBoxOrnegi(); 26 cerceve.setVisible(true); 27 } 28 catch (Exception e) 29 { 30 e.printStackTrace(); 31 } 32 } 33 }); 34 } 35 // bileşenler yapılandırılıyor 36 public JComboBoxOrnegi() 37 { 38 super("JComboBox Örneği"); 39 Container con = getContentPane(); 40 setLayout(new GridLayout()); // container nesnesi oluşturup yerleşim tipimizi belirledik 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 combo = new JComboBox(); combo.addItem("Edirne"); combo.addItem("Kırklareli"); combo.addItem("Tekirdağ"); combo.addItem("İstanbul"); combo.addItem("Çanakkale"); con.add(combo); combo.addItemListener(this); /* JComboBox bileşenimizi oluşturduk, * içine verileri ekledik ve Item Listener olayını ekledik */ etiket = new JLabel("Seçilen eleman"); con.add(etiket); etiket1 = new JLabel("Elemanın indis değeri"); con.add(etiket1); setSize(600, 100); setVisible(true); // JLabel bileşenimizi tanımladık ve form boyutunu ayarladık } @Override public void itemStateChanged(ItemEvent isc) { String komboIcerik; int indis; komboIcerik = (String) combo.getSelectedItem(); indis = combo.getSelectedIndex(); etiket.setText(komboIcerik); etiket1.setText(String.valueOf(indis)); } } Uygulamamızı kısaca açıklamamız gerekirse, uygulamamız JComboBox bileşeninin ItemStateChangeolayını kullanarak seçili elemanı ve elemanının indis değerini JLabel bileşenine yazdırıyoruz. Yazdığımız kodda diğer örneklerimizden farklı olarak JComboBox bileşenini ekledik ve bu bileşenimize elemanları addItem()metodu yardımıyla ekledik. Daha sonrasında değişen eleman durumlarında içeriği alabilmemiz için JComboBoxbileşenimize bir ItemListener ekledik. Olayımız içerisinde ise seçili eleman her değiştiğinde JLabel bileşeninintext özelliğinin buna bağlı olarak değişmesini sağladık. Ders 147 - JRadioButton JRadioButton, sadece tek bir seçeneği seçmek gibi durumlarda kullanırız. JRadioButton bileşeni sayesinde kullanıcıya birçok seçenek verip, kullanıcıdan bir tane seçenek seçmesini isteyip, daha sonra bu seçenekle ilgili olayı işleme koyabiliriz. JRadioButton bileşenlerini kullanacağımız zaman bunları bir grup içerisinde yapılandırmamız daha doğru olacaktır. Grup içerisinde yapılandırmamızın ana sebebi; sadece bir tek doğru seçeneğin olması görüşüdür. Farklı gruplardaki seçenekleri farklı gruplar altında yapılandırabiliriz. JRadioButton bileşenlerinin ana görevinin tek bir seçeneği seçmek olduğunu söylemiştik. Bu durumda seçenekleri kontrol etmek veya seçenek değişiminde farklı işlemlere yönlendirmek için bir takım olaylar kullanabiliriz. JRadioButton seçim değişimlerini kontrol eden olay ActionListener arabirimininactionPerformed() olayıdır. Bu olay altında belirlediğiniz grup için hangi düğmenin seçili olduğunu bulabilirsiniz. Şimdi JRadioButton bileşenini ve olaylarını daha iyi anlamak için bir örnek yapalım. Aşağıdaki örnek JTextField içerisindeki metinin text özelliklerini değiştiren bir örnektir. 1 //JRadioButtonOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public class JRadioButtonOrnegi extends JFrame implements ActionListener { JTextField textBox; JRadioButton rb1, rb2, rb3, rb4; ButtonGroup grup; // uygulama başlatılıyor public static void main(String[] args) { EventQueue.invokeLater( new Runnable() { public void run() { try { JRadioButtonOrnegi cerceve = new JRadioButtonOrnegi(); } catch (Exception e) { e.printStackTrace(); } } }); } // bileşenler yapılandırılıyor public JRadioButtonOrnegi() { super("JRadioButton Örneği"); Container con = getContentPane(); setLayout(new FlowLayout()); // container nesnesi oluşturup yerleşim tipimizi belirledik textBox = new JTextField("ElektroArge Elektronik Araştırma Geliştirme Platformu."); con.add(textBox); //JTextField oluşturduk ve varsayılan metnimizi girdik. grup = new ButtonGroup(); rb1 = new JRadioButton("Normal", true); con.add(rb1); grup.add(rb1); rb1.addActionListener(this); rb2 = new JRadioButton("Kalın", false); 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 con.add(rb2); grup.add(rb2); rb2.addActionListener(this); rb3 = new JRadioButton("Eğik", false); con.add(rb3); grup.add(rb3); rb3.addActionListener(this); rb4 = new JRadioButton("Kalın ve Eğik", false); con.add(rb4); grup.add(rb4); rb4.addActionListener(this); /* JRadioButton bileşenlerimizi oluşturduk ve * bu bileşenleri tek bir grup altında topladık */ setSize(350,130); setVisible(true); } @Override public void actionPerformed(ActionEvent ae) { String font = ae.getActionCommand(); if (font.equals("Normal")) textBox.setFont(new Font("sansserif", Font.PLAIN, 12)); else if (font.equals("Kalın")) textBox.setFont(new Font("sansserif", Font.BOLD, 12)); else if (font.equals("Eğik")) textBox.setFont(new Font("sansserif", Font.ITALIC, 12)); else if (font.equals("Kalın ve Eğik")) textBox.setFont(new Font("sansserif", Font.BOLD + Font.ITALIC, 12)); } } Uygulamamız basit olarak JTextField bileşeni içerisindeki metinin Font özelliğini JRadioButtonbileşenlerinin aldığı değerlere göre değiştiriyor. Yazdığımız kodda yapılandırıcı metod içerisinde diğer uygulamalarımızdan farklı olarak JRadioButton ekledik. JRadioButton eklerken, bu bileşenin yapılandırıcı metoduna boolean bir parametre ekledik. Bu uygulama başladığında varsayılan olarak seçili gelekJRadioButton bileşenini gösterecektir. JRadioButton bileşenlerimizi oluşturduktan sonra, hepsini daha önceden oluşturduğumuz bir grup altında topladık. Hepsini bir grup altında toplamasaydık bütün JRadioButton bileşenlerini aynı anda seçebilecektik. Tek grup altında toplamak bize tek bir doğru seçenek olmasını sağlıyor. Olayımız içerisinde önce hangi JRadioButton bileşeninin seçili olduğunu bulduktan sonra buna göre işlemlerimizi yaptık. Ders 148 - JCheckBox JCheckBox, JRadioButton bileşenine çok benzer fakat bir yön ile bu bileşenden ayrılır. JRadioButtonbileşenini önceki dersimizde anlatırken tek bir doğru seçeneğin seçilmesi gerektiğini anlatmıştık, burada ise durum farklıdır. JCheckBox bileşenlerinde birden fazla seçenek işaretlenebilir ve buna göre işlem yapılabilir. Şimdi bu bileşeni daha iyi anlamak ve olaylarını daha iyi görebilmek için bununla ilgili bir örnek yapalım. 1 //JCheckBoxOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 7 public class JCheckBoxOrnegi extends JFrame implements 8 ItemListener 9 { 10 JLabel etiket1; 11 JCheckBox cb, cb1, cb2, cb3, cb4; 12 13 // uygulama başlatılıyor 14 public static void main(String[] args) 15 { 16 EventQueue.invokeLater( 17 new Runnable() 18 { 19 public void run() 20 { 21 try 22 { 23 JCheckBoxOrnegi cerceve = new 24 JCheckBoxOrnegi(); 25 cerceve.setVisible(true); 26 } catch (Exception e) 27 { 28 e.printStackTrace(); 29 } 30 } 31 }); 32 } 33 // bileşenler yapılandırılıyor. 34 public JCheckBoxOrnegi() 35 { 36 super("JCheckBox Örneği"); 37 Container con = getContentPane(); 38 setLayout(new FlowLayout()); 39 // container nesnesi oluşturup yerleşim tipimizi belirledik 40 JLabel etiket = new JLabel("Bildiğiniz programlama dillerini 41 seçin"); 42 con.add(etiket); 43 44 cb = new JCheckBox("Java"); 45 con.add(cb); 46 cb.addItemListener(this); 47 cb1 = new JCheckBox("C"); 48 con.add(cb1); 49 cb1.addItemListener(this); 50 cb2 = new JCheckBox("C++"); 51 con.add(cb2); 52 cb2.addItemListener(this); 53 cb3 = new JCheckBox("C#"); 54 con.add(cb); 55 cb3.addItemListener(this); 56 cb4 = new JCheckBox("Android"); 57 con.add(cb4); 58 cb4.addItemListener(this); 59 // JCheckBox bileşenlerimizi oluşturduk ve olaylarını ekledik 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 etiket1 = new JLabel(); con.add(etiket1); setSize(300, 150); setVisible(true); } @Override public void itemStateChanged(ItemEvent ie) { String diller = "Bildikleriniz: "; if(cb.isSelected()) diller += cb.getText(); if(cb1.isSelected()) diller += ", " + cb1.getText(); if(cb2.isSelected()) diller += ", " + cb2.getText(); if(cb3.isSelected()) diller += ", " + cb3.getText(); if(cb4.isSelected()) diller += ", " + cb4.getText(); etiket1.setText(diller); } } Uygulamamız kısaca seçili olan JCheckBox bileşenlerini bulup, bunların text özelliğini bir JLabelbileşenine aktarıyor. Yazdığımız bu uygulamada diğer uygulamalardan farklı olarak JCheckBox bileşeni oluşturduk ve bunları çerçevemize ekledik. Olayımız içerisinde ise hangi JCheckBox bileşenlerinin seçili olduğunu bulduk ve bunların text özelliğini bir JLabel bileşenine aktardık. Ders 149 - JToggleButton JToggleButton, JButton bileşeninin farklı bir durumudur. JButton bileşenine bir kez tıkladığımızda anlıkdüğmeye tıklamış ve geri çekmiş (serbest bırakmış) olursunuz. JToggleButton bileşeninde ise durum biraz farklıdır. Bu bileşene bir kez tıkladığınızda bir daha tıklayana kadar düğme basılı kalır. Bir daha tıkladığınızda düğmeyi serbest bırakmış olursunuz. JToggleButton bileşeni her ne kadar JButton bileşenine benzese de yapısal olarak JCheckBox bileşenine benzer. Bu yüzden JToggleButton bileşeni aynı JCheckBox bileşeni gibi ItemListener arabirimininitemStateChanged() olayını kullanır. JToggleButton bileşeninde aynen JCheckBox bileşeninde olduğu gibiisSelected() metodunu kullanmamız mümkündür. Şimdi bu bileşen hakkında bir örnek yaparak konuyu daha iyi anlamaya çalışalım. 1 //JToggleButtonOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 7 public class JToggleButtonOrnegi extends JFrame implements 8 ItemListener 9 { 10 JLabel etiket, etiket1, etiket2; 11 JToggleButton gecisliDugme; 12 13 // uygulama başlatılıyor 14 public static void main(String[] args) 15 { 16 EventQueue.invokeLater( 17 new Runnable() 18 { 19 public void run() 20 { 21 try 22 { 23 JToggleButtonOrnegi cerceve = new 24 JToggleButtonOrnegi(); 25 cerceve.setVisible(true); 26 } catch (Exception e) 27 { 28 e.printStackTrace(); 29 } 30 } 31 }); 32 } 33 // bileşenler yapılandırılıyor. 34 public JToggleButtonOrnegi() 35 { 36 super("JToggleButton Örneği"); 37 Container con = getContentPane(); 38 setLayout(new FlowLayout()); 39 // container nesnesi oluşturup yerleşim tipimizi belirledik 40 etiket1 = new JLabel("Basılma sayısı: "); 41 con.add(etiket1); 42 etiket = new JLabel("0"); 43 con.add(etiket); 44 45 gecisliDugme = new JToggleButton("Bas\\Serbest bırak"); 46 con.add(gecisliDugme); 47 gecisliDugme.addItemListener(this); 48 // JToggleButton bileşenimizi oluşturduk ve olayını ekledik 49 50 etiket2 = new JLabel("JToggleButton serbest bırakıldı"); 51 con.add(etiket2); 52 setSize(300, 100); 53 setVisible(true); 54 } 55 56 @Override 57 public void itemStateChanged(ItemEvent ie) 58 { 59 int sayac = Integer.parseInt(etiket.getText()); 60 61 if(gecisliDugme.isSelected()) 62 { 63 sayac++; 64 etiket.setText(String.valueOf(sayac)); 65 etiket2.setText("JToggleButton'a basıldı"); 66 } else { etiket2.setText("JToggleButton serbest bırakıldı"); 67 68 69 } } } Uygulamamızda ilk önce yerleşim düzenimizi seçip bir Container bileşeni oluşturduk. Daha sonrasında önceden oluşturduğumuz etiketlerimizi yapılandırarak Container nesnemize ekledik. Daha sonrasındaJToggleButton bileşenimizi oluşturup buna bir ItemListener olayı atadık. Olayımız içerisinde JToggleButtonbileşenine her basıldığında artacak bir sayaç tanımladık. Eğer bileşenimizin isSelected() özelliği true ise sayacımızı etiketimize yazdırıyor ve JToggleButton bileşenimize basıldığını gösteren bir başka bildirimi diğer etikete yazdırıyor. Eğer bileşenimizin bu özelliği false ise bileşenimizin serbest bırakıldığını gösteren bildirim etiketimize yazdırılıyor. Ders 150 - JTable JTable, verileri satırlar ve sütunlar olarak görüntülemeye yarayan bir bileşendir. Bu bileşeni çok boyutlu bir dizinin görsel hali olarak düşünebiliriz. Swing bileşenleri arasında en karmaşık bileşen olduğunu söylersek herhalde yanılmış olmayız. JTable bileşenini birçok yapılandırıcı metod sunar. En fazla kullanılan yapıcı metod aşağıdaki gibidir. JTable (Object icerik[][], Object 1 sutunlar[]) Yukarıdaki yapılandırıcı metod iki parametre alır ve bunlardan ilki içerisinde barındıracağı verileri tutan bir dizidir. Dizinin iki boyutlu olduğuna dikkatimizi verelim. Bu boyutlar, satır ve sütunlar içindir. İkinci parametre ise sütun isimlerini tutan bir dizidir. Bir JTable bileşeni birden fazla olayla ilişkilidir. Kullanıcı tablodan bir eleman seçtiğindeListSelectionEvent olayı tetiklenir. Tablo içerisinde verilerden biri değiştirildiğinde TableModelEvent olayı tetiklenir. Bu olayların hepsini kullanmak zorunda değiliz. Eğer tablomuzu sadece veri tutmak veya verileri ekrana çıktı gibi göstermek istiyorsak, bu olayları kullanmayabiliriz. Şimdi JTable bileşeni ve bu bileşenin seçim olayı hakkında bir örnek yaparak konuyu daha iyi anlamaya çalışalım. 1 //JTableOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 import javax.swing.*; 5 import javax.swing.event.*; 6 7 public class JTableOrnegi extends JFrame implements 8 ListSelectionListener 9 { 10 JTable tablo; 11 JLabel etiket, etiket1; 12 13 // uygulama başlatılıyor 14 public static void main(String[] args) 15 { 16 EventQueue.invokeLater( 17 new Runnable() 18 { 19 public void run() 20 { 21 try 22 { 23 JTableOrnegi cerceve = new JTableOrnegi(); 24 cerceve.setVisible(true); 25 } catch (Exception e) 26 { 27 e.printStackTrace(); 28 } 29 } 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 }); } // bileşenler yapılandırılıyor. public JTableOrnegi() { super("JTable Örneği"); Container con = getContentPane(); setLayout(new FlowLayout()); // container nesnesi oluşturup yerleşim tipimizi belirledik Object[] sutun = {"İl", "Plaka Kodu", "Bölge"}; // sütun isimlerini tanımladık Object[][] veriler = { {"Edirne", 22, "Marmara"}, {"İstanbul", 34, "Marmara"}, {"Kırıkkale", 71, "İç Anadolu"}, {"İzmir", 35, "Ege"}, {"Trabzon", 61, "Karadeniz"}, {"Hatay", 31, "Akdeniz"}, {"Gazi Antep", 27, "Güney Doğu Anadolu"}, {"Malatya", 44, "Doğu Anadolu"}, {"Giresun", 28, "Karadeniz"} }; // tablo içerisinde gösterilecek verileri tanımladık tablo = new JTable(veriler, sutun); con.add(new JScrollPane(tablo)); tablo.setCellSelectionEnabled(true); /* tablomuzu oluşturduk, * çerçevemize ekledik ve seçilebilir özelliğini aktif yaptık */ ListSelectionModel model = tablo.getSelectionModel(); model.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); model.addListSelectionListener(this); /* tablomuza ListSelectionListener olayını ekleyebilmek * için model ekledik ve seçeneklerini ayarladık */ etiket = new JLabel("Seçili Veri: "); con.add(etiket); etiket1 = new JLabel(); con.add(etiket1); setSize(500, 200); setVisible(true); } @Override public void valueChanged(ListSelectionEvent ie) 76 { 77 int sutunIndisi = tablo.getSelectedColumn(); 78 int satirIndisi = tablo.getSelectedRow(); 79 Object seciliEleman; 80 81 seciliEleman = tablo.getValueAt(satirIndisi, sutunIndisi); 82 etiket1.setText(String.valueOf(seciliEleman)); 83 } 84} Bu uygulamamızda diğerlerinden farklı olarak tablo oluşturduk. Tablo oluştururken önce sütun isimlerini, daha sonra ise tablo içerisinde gösterilecek verileri tanımladık. Daha sonra tablomuzun yapılandırıcı metodu ile bu verileri tablomuza aktardık. Tablo bileşenimize ListSelectionListener ekleyebilmek için önce modeloluşturduk. Daha sonra modelimiz üzerinden tablomuzda sadece bir hücrenin seçili olabilmesi içinselectionMode() metodu ile seçim modunu değiştirdik. Olayımız ise her hücre değişimde tetiklenecektir. Olayımız içerisinde önce tablomuzda ki seçili olan satır ve sütun indis değerlerini bulduk ve bu indis değerlerine göre seçili olan elemanı bulduk ve JLabel bileşenimize aktardık. Ders 151 - JList JList, adından da anlaşılacağı gibi bir liste elemanıdır. İçerisindeki elemanlardan bir veya daha fazlasınıseçmeye izin verir. En çok kullanılan swing bileşenlerindendir. JTable bileşenini anlatırken çok boyutlu dizilere benzetebileceğimizi söylemiştik. Bu bileşeni ise tek boyutlu bir diziye benzetmemiz mümkündür. Elemenalarıindis değerleriyle eşleyerek saklar. JList bileşeni üzerinde işlemler genelde eleman seçimleriyle ilgilidir. JTable bileşeninin iki olay tetiklediğini söylemiştik bunlar; eleman değiştirme olayı ve eleman seçim olayı idi. Bu bileşenimizde işlemler eleman seçimleriyle ilgili olduğu için bileşenimiz sadece ListSelectionListener olayını tetikler. JList bileşeni üzerinde, varsayılan olarak birden fazla seçim yapmanız mümkündür. Bu durumu değiştirmek için daha önceki dersimizde kullandığımız gibi setSelectionModel() metodunu kullanabiliriz. Metodumuzun genel yapısı şu şekildedir: void setSelectionModel(int 1 secimTipi) Metodumuzda belirttiğimiz secimTipi parametresi ListSelectionModel altındaki üç değerden biri olabilir. Bunlar; SINGLE_SELECTION SINGLE_INTERVAL_SELECTION MULTIPLE_INTERVAL_SELECTION JList oluşturulduktan itibaren varsayılan olarak MULTIPLE_INTERVAL_SELECTION değeri gelir. Bu seçim tipi kullanıcının birden fazla aralıkta öğe seçebilmesini sağlar (çoklu seçim).SINGLE_INTERVAL_SELECTION ise; kullanıcının bir öğeler aralığı seçebilmesini sağlar. SINGLE_SELECTIONile sadece tek bir eleman seçilebilir. JList bileşenini ve olaylarını daha iyi anlayabilmek için bir örnek yapalım. 1 //JListOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 import javax.swing.*; 5 import javax.swing.event.*; 6 7 public class JListOrnegi extends JFrame implements 8 ListSelectionListener 9 { 10 JList liste; 11 JLabel etiket1; 12 13 // uygulama başlatılıyor 14 public static void main(String[] args) 15 { 16 EventQueue.invokeLater( 17 new Runnable() 18 { 19 public void run() 20 { 21 try 22 { 23 JListOrnegi cerceve = new JListOrnegi(); 24 cerceve.setVisible(true); 25 } catch (Exception e) 26 { 27 e.printStackTrace(); 28 } 29 } 30 }); 31 } 32 // bileşenler yapılandırılıyor. 33 public JListOrnegi() 34 { 35 super("JList Örneği"); 36 Container con = getContentPane(); 37 setLayout(new FlowLayout()); 38 // container nesnesi oluşturup yerleşim tipimizi belirledik 39 40 String[] veriler = {"Edirne", "İstanbul", "Kırıkkale", "İzmir", 41 "Trabzon", "Hatay", "Gaziantep", "Malatya", "Giresun"}; 42 // listemiz içerisinde gösterilecek verileri ekledik 43 44 liste = new JList<String>(veriler); 45 con.add(liste); 46 liste.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 47 liste.addListSelectionListener(this); 48 /* listemizi oluşturduk, seçim tipini belirledik ve 49 * dinleyici ekledik. */ 50 51 etiket1 = new JLabel(); 52 53 54 55 56 57 58 59 60 61 62 63 64 65} con.add(etiket1); setSize(350, 210); setVisible(true); } @Override public void valueChanged(ListSelectionEvent ie) { int indis = liste.getSelectedIndex(); String veri = (String) liste.getSelectedValue(); etiket1.setText(indis + ". indisdeki veri: " + veri); } Yapılandırıcı metodumuz içerisinde yerleşim tipimizi belirledikten sonra JList bileşenimiz içerisinde gösterilecek verileri oluşturduk. Daha sonrasında listemizi yaratıp bu elemanları referans listemize ekledik.JList yapımızı oluştururken diğer bileşenlerden farklı olarak bu bileşenimizde içerisine eklenecek veri tipini de belirttik. Seçim tipimizi SINGLE_SELECTION olarak belirledikten sonra listemize bir ListSelectionListenerdinleyicisi ekledik. Olayımız her eleman değiştiğinde tetiklenecektir. Olayımız içerisinde önce seçili indisdeğerini daha sonra elemanı bulduk ve JLabel bileşenimizin yardımıyla bunları ekranda gösterdik. Ders 152 - JScrollPane JScrollPane, diğer bileşenleri kaydırmak için oluşturulmuş bir swing bileşenidir. Çerçevemize sığmayanbileşenleri JScrollPane bileşenimize eklediğimizde ekranda çubuklar belirir ve biz bu çubuklar sayesinde bileşenimizin ekrana sığmayan diğer kısmını da görebiliriz.Bu bileşen swing bileşenleri arasındaki anlaşılması en basit olanıdır. Yapılandırıcı metodu aşağıdaki gibidir. 1 JScrollPane (Component bilesen) JScrollPane bileşenini kullanmak için bu bileşenimizi oluştururken parametre olarak ekrana sığmayan bileşeni veririz. JScrollPane ekrana sığmayan bileşen için otomatik olarak kaydırma çubukları oluşturacaktır. Bu konuyu daha iyi anlamak için bir örnek yapalım: 1 //JScrollPaneOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 import javax.swing.*; 5 import javax.swing.event.*; 6 7 public class JScrollPaneOrnegi extends JFrame implements 8 ListSelectionListener 9 { 10 JList liste; 11 JLabel etiket1; 12 13 // uygulama başlatılıyor 14 public static void main(String[] args) 15 { 16 EventQueue.invokeLater( 17 new Runnable() 18 { 19 public void run() 20 { 21 try 22 { 23 JScrollPaneOrnegi cerceve = new JScrollPaneOrnegi(); 24 cerceve.setVisible(true); 25 } catch (Exception e) 26 { 27 e.printStackTrace(); 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 } } } }); } // bileşenler yapılandırılıyor. public JScrollPaneOrnegi() { super("JScrollPane Örneği"); Container con = getContentPane(); setLayout(new FlowLayout()); // container nesnesi oluşturup yerleşim tipimizi belirledik String[] veriler = {"Edirne", "İstanbul", "Kırıkkale", "İzmir", "Trabzon", "Hatay", "Gaziantep", "Malatya", "Giresun"}; // listemiz içerisinde gösterilecek verileri ekledik liste = new JList<String>(veriler); con.add(liste); liste.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); liste.addListSelectionListener(this); /* listemizi oluşturduk, seçim tipini belirledik ve * dinleyici ekledik. */ JScrollPane cubuk = new JScrollPane(liste); con.add(cubuk); etiket1 = new JLabel(); con.add(etiket1); setSize(350, 210); setVisible(true); } @Override public void valueChanged(ListSelectionEvent ie) { int indis = liste.getSelectedIndex(); String veri = (String) liste.getSelectedValue(); etiket1.setText(indis + ". indisdeki veri: " + veri); } Ekran çıktısı: Bir önceki bileşen için yaptığımız örneğe bu sefer JScrollPane bileşenini uyguladık. JScrollPanebileşenimize parametre olarak JList bileşenimizi verdik ve sonuç olarak JScrollPane bize kendi oluşturduğu kaydırma çubuklarını verdi. Ders 153 - JTabbedPane JTabbedPane, genel olarak bir sekmeli pano bileşenidir. Birden fazla sekmeler arasında değişik panolar arasında tutabilir. Bu bileşen üzerinde sekmelere tıklamamız durumunda tıklanılan sekmenin pano içeriği görünür duruma gelecek, diğer bölümler gizlenecektir. Bu bileşene sekme ekleyebilmek için addTab()metodunu kullanırız. addTab() metodunun genel yapısı aşağıdaki gibidir: void addTab (String sekmeAdi, Component 1 eklenecekBilesen) İlk parametre sekmenin adını belirler, ikinci parametre ise sekmeye eklenecek bileşeni belirler. Sekmeye ekleyeceğimiz bileşen çoğunlukla JPanel olacaktır. JPanel birçok bileşeni bir arada tutabilmemizi sağlayan bir bileşendir. Şimdi konuyu daha iyi anlayabilmek için bir örnek yapalım. Aşağıdaki örnek daha önce JTable bileşeninde yaptığımız örneğin JTabbedPane bileşenine uyarlanmış hali olacaktır. 1 //JScrollPaneOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 import javax.swing.*; 5 6 public class JTabbedPaneOrnegi extends JFrame 7 { 8 // uygulama başlatılıyor 9 public static void main(String[] args) 10 { 11 EventQueue.invokeLater( 12 new Runnable() 13 { 14 public void run() 15 { 16 try 17 { 18 JTabbedPaneOrnegi cerceve = new 19 JTabbedPaneOrnegi(); 20 cerceve.setVisible(true); 21 } catch (Exception e) 22 { 23 e.printStackTrace(); 24 } 25 } 26 }); 27 } 28 // bileşenler yapılandırılıyor. 29 public JTabbedPaneOrnegi() 30 { 31 super("JTabbedPane Örneği"); 32 Container con = getContentPane(); 33 34 JTabbedPane sekmeliPano = new JTabbedPane(); 35 sekmeliPano.addTab("İl", new ilPanel()); 36 sekmeliPano.addTab("Plaka Kodu", new plakaPanel()); 37 sekmeliPano.addTab("Bölge", new bolgePanel()); 38 con.add(sekmeliPano); 39 // panomuzu oluşturduk ve sekmelerini ekledik 40 41 setSize(350, 250); 42 setVisible(true); 43 } 44 45 // illeri görüntüleyeceğimiz panel 46 public class ilPanel extends JPanel 47 { 48 public ilPanel() 49 { 50 String[] veriler = {"Edirne", "İstanbul", "Kırıkkale", "İzmir", 51 "Trabzon", "Hatay", "Gaziantep", "Malatya", "Giresun"}; 52 JList liste = new JList<String>(veriler); 53 add(liste); 54 // listemize verileri ekledik ve panelimize listeyi ekledik 55 56 JScrollPane cubuk = new JScrollPane(liste); 57 add(cubuk); 58 } 59 } 60 61 // plakaları görüntüleyeceğimiz panel 62 public class plakaPanel extends JPanel 63 { 64 public plakaPanel() 65 { 66 String[] plaka = {"22", "34", "71", "35", "61", "31", "37", "44", 67 "28"}; 68 JList liste = new JList<String>(plaka); 69 add(liste); 70 // listemize verileri ekledik ve panelimize listeyi ekledik. 71 72 JScrollPane cubuk = new JScrollPane(liste); 73 add(cubuk); 74 } 75 } 76 77 // bilgileri görüntüleyeceğimiz panel 78 public class bolgePanel extends JPanel 79 { 80 public bolgePanel() 81 { 82 JComboBox combo = new JComboBox(); 83 combo.addItem("Marmara"); 84 combo.addItem("Ege"); 85 combo.addItem("Karadeniz"); 86 combo.addItem("Güney Doğu Anadolu"); 87 combo.addItem("Doğu Anadolu"); 88 combo.addItem("Akdeniz"); 89 combo.addItem("İç Anadolu"); 90 91 92 add(combo); } } } Örneğimiz genel JTabbedPane kullanımını görmek içindir. Örneğimizde yapılandırıcı metodumuz içerisindeaddTab() metodu ile sekmelerimizi ve bunlar içerisine panolarımızı ekledik. İlk parametremiz sekme ismi için ikinci paremetremiz ise, sekmeye ekleyeceğimiz bileşendir. Bileşenlerimizi ekledikten sonra bileşenlerimizi yapılandıracağımız sınıfları yazdık ve işlemi sonlandırdık. Tüm bu işlemleri yaptıktan sonra uygulamamızın ekran çıktısı, yukarıdaki şekildeki gibi olacaktır. Ders 154 - JTree JTree bileşeni, verilerin hiyerarşik bir biçimde gözükmesini sağlayan bir görsel bileşendir. Bu bileşen sayesinde kullanıcı verileri hiyerarşik bir biçimde görüntüleyebilir. JTree bileşeninin en çok kullanılan yapılandırıcı metodları aşağıdaki gibidir: 1 JTree (Object veri[]) 2 JTree (Vector v) 3 4 JTree (TreeModel newModel) JTree (TreeNode dugum) İlk yapılandırıcı ile JTree bileşenimizin hiyerarşisi veri dizisinin elemanları alınarak oluşturulur. İkinci yapılandırıcı ile v vektörü, ağacımızın yapısını oluşturur. Üçüncü yapılandırıcı da daha önceden tanımlanan bir ağaç modeli referans verilerek ağacımızın dalları oluşturulur. Dördüncü yapılandırıcı da ise kök düğümüdugum olan ağaç JTree bileşenimizin verilerini oluşturur. JTree bileşeninin kendine has bazı olayları vardır. Bu olaylar ve olayların tetiklendiği durumlar aşağıdaki gibidir. TreeExpansionEvent: Ağaç genişlediğinde veya daraltığında tetiklenir. TreeModelEvent: Ağacın verileri veya yapısı değiştiğinde tetiklenir. TreeSelectionEvent: Ağacın bir elemanı veya düğümü seçildiğinde tetiklenir. Şimdi bu konuyla ilgili bir örnek yapalım. 1 //JTreeOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 5 import javax.swing.*; 6 import javax.swing.event.*; 7 import javax.swing.tree.*; 8 9 public class JTreeOrnegi extends JFrame 10 { 11 JLabel etiket; 12 13 // uygulama başlatılıyor 14 public static void main(String[] args) 15 { 16 EventQueue.invokeLater( 17 new Runnable() 18 { 19 public void run() 20 { 21 try 22 { 23 JTreeOrnegi cerceve = new JTreeOrnegi(); 24 cerceve.setVisible(true); 25 } catch (Exception e) 26 { 27 e.printStackTrace(); 28 } 29 } 30 }); 31 } 32 // bileşenler yapılandırılıyor. 33 public JTreeOrnegi() 34 { 35 super("JTree Örneği"); 36 Container con = getContentPane(); 37 setLayout(new FlowLayout()); 38 // container nesnesi oluşturup yerleşim tipimizi belirledik 39 DefaultMutableTreeNode 40 agacKoku, altKok1, altKok2, eleman1, eleman2, eleman3, eleman4, 41 eleman5; 42 agacKoku = new DefaultMutableTreeNode("Ana Kök"); 43 // örneğimiz için bir ağaç kökü oluşturduk 44 45 altKok1 = new DefaultMutableTreeNode("1. Alt Kök"); 46 agacKoku.add(altKok1); 47 altKok2 = new DefaultMutableTreeNode("2. Alt Kök"); 48 agacKoku.add(altKok2); 49 // ağacımız için alt kökler oluşturduk ve bu kökleri ağacımıza ekledik 50 51 eleman1 = new DefaultMutableTreeNode("1. Kök 1. Eleman"); 52 eleman2 = new DefaultMutableTreeNode("1. Kök 2. Eleman"); 53 altKok1.add(eleman1); 54 altKok2.add(eleman2); 55 eleman3 = new DefaultMutableTreeNode("2. Kök 1. Eleman"); 56 eleman4 = new DefaultMutableTreeNode("2. Kök 2. eleman"); 57 eleman5 = new DefaultMutableTreeNode("3. Kök 3. Eleman"); 58 altKok2.add(eleman3); 59 altKok2.add(eleman4); 60 altKok2.add(eleman5); 61 // oluşturduğumuz elemanlarımızı ağacımıza yerleştirdik 62 JTree ornekAgac = new JTree(agacKoku); 63 etiket = new JLabel("Lütfen apacın bir alanını genişletin veya " + 64 "daraltın"); 65 66 // ağacımıza genişleme olayını ekledik 67 ornekAgac.addTreeExpansionListener(new TreeExpansionListener() 68 { 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 } 90 } @Override public void treeExpanded(TreeExpansionEvent arg0) { // ağaç genişlediğinde çalışır etiket.setText(arg0.getPath().toString() + " alanı genişledi."); } @Override public void treeCollapsed(TreeExpansionEvent arg0) { // ağaç daraltıldığında çalışır etiket.setText(arg0.getPath().toString() + " alanı daraltıldı."); } }); con.add(ornekAgac); con.add(etiket); setSize(350, 250); setVisible(true); // bileşenlerimizi formumuza ekledik. Örneğimizde JTree bileşenimizi oluşturmadan önce bileşenimizin sahip olacağı kökü ve alt dalları belirledik. Daha sonra oluşturduğumuz bu ağacı JTree bileşenimize parametre olarak gönderdik. Bu kısımdaJTree bileşenimizin içeriğini belirlemiş olduk. Daha sonraki kısımda ise bileşenimize genişleme veyadaraltmayı kontrol eden TreeExpansionListener ekledik. Listener sınıfımızın bize sağladığı metodları kullanarak, ağacımızın genişleyen veya daralan kollarınıJLabel nesnemize aktardık. Ders 155 - Layout (Yerleşim Düzenleri) Layout'lar Java'da görsel uygulamalarda bileşenlerin yerini belirlemek için kullandığımız bileşenlerdir. Çoğu zaman layout'ları bileşenlerin form üzerinde daha düzenli durması için kullanırız. Layout üzerindeki bileşen form büyüyüp küçülse bile, layout'a göre şekillenir. Yani pencere büyüyüp küçülmesinden dolaylı olarak etkilenir. Görsel bileşenler form üzerine ekleneceği zaman layout olmadığı durumda, ekleneceği yerin x ve ynoktası girilerek eklenir. Layout bizi bu dertten kurtarır. Layout bileşenleri form üzerine layout tipine göre düzenle yerleştirir. GRIDLAYOUT Bileşenleri küçük dikdörtgenler içerisinde düzenli bir biçimde tutmaya yarar. İçerisine eklenen her bileşenfarklı bir dikdörtgen içerisinde tutulur. Eklenen bileşenlerin hepsinin aynı boyutta olmasını sağlar ve bileşenleri düzenler. GridLayout üzerindeki bileşenler aşağıdaki örnekteki gibi gözükür: 1 //GridLayoutOrnegi.java - 25.04.2014 2 3 import java.awt.*; 4 5 public class GridLayoutOrnegi 6 { 7 public static void main(String[] args) 8 { 9 Frame cerceve = new Frame(); 10 // çerçeve oluşturduk. 11 cerceve.setLayout(new GridLayout(3, 3)); 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 // çerçevenin layoutunu belirledik cerceve.add(new Button("1")); cerceve.add(new Button("2")); cerceve.add(new Button("3")); cerceve.add(new Button("4")); cerceve.add(new Button("5")); cerceve.add(new Button("6")); cerceve.add(new Button("7")); cerceve.add(new Button("8")); cerceve.add(new Button("9")); // çerçevemize bileşenleri ekledik cerceve.setBounds(100, 100, 400, 300); cerceve.setVisible(true); // çerçevemizin boyutunu belirledik ve çerçevimizi görünür yaptık } } BORDERLAYOUT Bu yerleşim tipi en çok kullanılan yerleşim tiplerindendir. Bileşenleri çerçeveyi bölgelere ayırır ve bu belirlenen bölgelere bileşenleri düzenli bir biçimde ekler. Genelde çerçeveyi kuzey, güney, doğu, batı vemerkez olmak üzere beşe ayırır ve bileşenleri bu bölgelerden istenilen birine ekler. BorderLayout üzerinde bileşenler aşağıdaki örnekteki gibi gözükür. 1 //BorderLayoutOrnegi.java - 25.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.awt.*; public class BorderLayoutOrnegi { public static void main(String[] args) { Frame cerceve = new Frame(); // çerçeve belirledik cerceve.setLayout(new BorderLayout()); // yerleşim tipi belirlendi cerceve.add(new Button("Kuzey"), BorderLayout.NORTH); cerceve.add(new Button("Güney"), BorderLayout.SOUTH); cerceve.add(new Button("Doğu"), BorderLayout.EAST); cerceve.add(new Button("Batı"), BorderLayout.WEST); cerceve.add(new Button("Merkez"), BorderLayout.CENTER); // butonlar eklendi cerceve.setBounds(100, 100, 400, 300); cerceve.setVisible(true); // çerçevemizin boyutunu belirledik ve çerçevimizi görünür yaptık } } FLOWLAYOUT Bu yerleşim tipi bileşenleri soldan sağa doğru sırayla ekler. Soldan devam edecek yer kalmayınca bir alt satırdan tekrar bileşenleri soldan sağa doğru eklemeye başlar. Bu layout türünün yapılandırıcısına vereceğimiz parametre ile bileşenlerin sağa, sola veya ortaya yaslı olmasını sağlayabiliriz. Bu parametreler sınıf içerisinde tanımlı sabitlerdir. Bu sabitler şöyledir: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 LEFT: Bileşenlerin sola yaslı olmasını sağlar. RIGHT: Bileşenlerin sağa yaslı olmasını sağlar. CENTER: Bileşenlerin merkeze yaslı olmasını sağlar. LEADING: Bileşenlerin soldan sağa eklenilmesini sağlar. TRAILING: Bişelenlerin sağdan sola eklenilmesini sağlar. //FlowLayoutOrnegi.java - 25.04.2014 import java.awt.*; public class FlowLayoutOrnegi { public static void main(String[] args) { Frame cerceve = new Frame(); cerceve.setLayout(new FlowLayout(FlowLayout.CENTER)); // çerçeve tanımlandı ve tipi belirlendi cerceve.add(new Button("Button1")); cerceve.add(new TextField("Metin Alanı 1")); cerceve.add(new Button("Button2")); cerceve.add(new TextField("Metin Alanı 2")); cerceve.add(new Button("Button3")); cerceve.add(new TextField("Metin Alanı 3")); cerceve.add(new Button("Button4")); cerceve.add(new TextField("Metin Alanı 4")); cerceve.setBounds(100, 100, 600, 100); cerceve.setVisible(true); // çerçevemizin boyutunu belirledik ve çerçevimizi görünür yaptık } } GRIDBAGLAYOUT GridBagLayout, çok fazla bileşen kullandığımızda karmaşıklığı ortadan kaldırmak için kullanılır.GridBagLayout, GridBagConstrains sınıfı ile her bileşenin ayrı ayrı nasıl yerleşeceğini belirler. 1 //GridBagLayout.java - 25.04.2014 2 3 import java.awt.*; 4 5 public class GridBagLayoutOrnegi 6 { 7 public static void main(String[] args) 8 { 9 Frame cerceve = new Frame(); 10 cerceve.setLayout(new GridBagLayout()); 11 GridBagConstraints g = new GridBagConstraints(); 12 g.fill = GridBagConstraints.CENTER; 13 // bileşenleri belirli kriterlere göre çerçevemize ekleyecek nesneyi 14 oluşturduk 15 g.weightx = 1; 16 g.weighty = 0; 17 // bileşenlerin arasında kaç birim boşluk bulunacağını bu değişkenlerle 18 belirliyoruz. 19 g.gridx = 1; 20 g.gridy = 1; 21 // bileşenleri düzlemde nereye ekleyeceğimizi bu bileşenlerle 22 belirliyoruz 23 // örneğin bu bileşen X düzleminde 1 Y düzleminde 1 olan yere 24 yerleşir 25 cerceve.add(new Button("5"), g); 26 g.gridx = 0; 27 g.gridy = 0; 28 cerceve.add(new Button("1"), g); 29 g.gridx = 2; 30 g.gridy = 0; 31 cerceve.add(new Button("3"), g); 32 g.gridx = 1; 33 g.gridy = 0; 34 35 36 37 38 39 40 cerceve.add(new Button("2"), g); g.gridx = 2; g.gridy = 1; g.anchor = GridBagConstraints.LINE_START; cerceve.add(new Button("4"), g); cerceve.setBounds(100, 100, 400, 300); cerceve.setVisible(true); } } DİĞER LAYOUT ÖRNEKLERİ Yukarıda en çok kullanılan layout tiplerini açıkladık. Diğer layout tipleri ise, yukarıdaki layout tipleri kadar kullanılmazlar. Bu layout tipleri ve görevleri şöyledir: CardLayout: Bileşenleri çerçeveye birer kart olarak ekledik. Aynı anda sadece bir kart görünür durumda olabilir. Yani bu yerleşim tipiyle bazı bileşenlerin bazı anlarda görünmesini sağlarken bazı bileşenlerin gizlenmesini sağlayabiliriz. BoxLayout: GridLayout yerleşim düzenini anlatırken bileşenlerin hepsinin aynı boyutta olmasını sağladığını söylemiştik. BoxLayout, çoğu özelliğiyle GridLayout'a benzemesine rağmen bu özelliğiyleGridLayout'tan ayrılır. Ayrıca GridLayout'a oranla daha fazla özelliğe sahiptir. Ders 156 - Veritabanı Kavramına Giriş Yazılıma yeni başlayanlar genelde küçük programlar yaparak programlamaya adım atarlar. C ile program yazanlar ilk başta Structure içerisine kayıt eklerler daha sonra bilgileri dizilerde tutup, tekrar elde ederler. Farklı programlama dilleri öğrendikçe büyük projeler yapma isteği sonucunda veritabanına ihtiyaç duyulur. Veritabanı, geniş depolama kapasitesi olan, verileri hızlı bir şekilde depolayıp yine hızlı bir şekilde elde etmeye yarayan, verileri sistematik bir şekilde tutan, farklı türdeki verileri bünyesinde bulunduran, yönetilebilir, güncellenebilir bir yapıdır. Veritabanları, veri modelleri ile saklanırlar. Bu veri modelleri birkaç farklı bölümde incelenir. Bunlardan bazıları: Nesneye Yönelik Model Ağ Modeli Hiyararşik Model Varlık-İlişki Modeli Bu modellerden en çok kullanılanı ilişkisel modeldir. Bu ilişkisel modelde veriler tablolar halinde tutulur. Diyelim ki bir öğrenci not sistemi yazmak istiyoruz. Bunun için bir öğrenci üzerinden gidersek öğrenci bilgilerini tutan Öğrenci tablosu, öğrenci notlarını tutan Notlar tablosu, hoca isimlerini tutan Hocalar tablosu,dersleri tutan Dersler tablosu gibi birçok tablo oluşturmamız gerekir. Daha sonra bu tabloları birbiri ileilişkilendirmek gerekir. Bu tablolardaki bilgilere kayıt denir. Her tabloda birçok sütun bulunur. Örnek olarak bir veritabanı tablosuve bu tablo içerisindeki kayıtları gösterelim. Yukarıda bir tablomuz var. Bu tablomuzun adı Öğrenciler olsun. Bu Öğrenciler tablosunda OgrenciNo,OgrenciAd, OgrenciSoyad, OgrenciB olum alanlarımız var. Bunlara sütun denir. Tablodaki her bir satırdaki bilgilere de kayıt denir. Tablomuzda öğrenci numarası Primary Key (PK-birincil anahtar) olarak ayarlanmıştır. Nedir bu Primary Key, onu açıklayalım. Ülkemizde her kişinin T.C. numarası birbirinden farklıdır. Sistemlerde bu T.C. numarası girildiğinde tek bir kişi gelir. Fakat bir ad veya bir soyad girdiğimizde, birçok kayıt gelecektir. İşte bu T.C. numarası Primary Keyolarak tanımlanmıştır. Yani bu alanda birden fazla kayıt olamaz. Biz de aynı Öğrenci numarasına sahip bir başka kişi olmasın diye bu alanı Primary Key olarak tanımladık. Örneğimizde gözükmese de bu alan Primary Key olarak tanımlanmıştır. Tablodaki bilgileri, girilmiş şekilde gösterdiğimiz için Primary Key alanını göremedik. Aşağıdaki şekilde Primary Key alanı daha net görünmektedir. Yukarıdaki şekil, tablodaki alanları tanımladığımız yeri gösterir. Her alan için boyut, tip gibi özellikler girilir. Ders 157 - Veritabanı Yönetim Sistemleri (VTYS) Önceki dersimizde veritabanı kavramını anlatmıştık. Peki, bu verilerimizi nereye kaydediyoruz? Veritabanını ne üzerinden yönetiyoruz? Burada VTYS kavramı karşımıza çıkıyor. Veritabanlarını oluşturmak, oluşturulan veritabanları üzerinde silme, ekleme, arama gibi işlemler yapan, veritabanındaki tüm ihtiyaçları gideren yazılım sistemine veritabanı yönetim sistemi (database management system) denir. Veritabanı yönetim sistemi, veritabanımızı diğer kullanıcılara açar. Veritabanı yönetim sistemi ile veritabanımızın tüm gereksinimlerini karşılarız. Bunu şöyle açıklayalım. Kullanıcı adı ve şifre isteyen bir online uygulamaya bir giriş yapamıyorsak bunu VTYS engellediği için yapamıyoruz demektir. İznimiz olan bir uygulamaya şifremiz ile giriş yaptık diyelim. Sistemdeki her bilgiyi göremiyorsak, bu yine VTYS'de bize izin tanımlanmadığı içindir. Peki, bu VTYS'yi kim yönetiyor? Veritabanı yönetim sistemini kullanan deneyimli kişilere Veritabanı Yöneticisi denir. Bu kişiler, VTYS kullanarak veritabanına girebilecek kişileri yönetir, veritabanına tablo veya kayıt ekleyip çıkarabilir, veritabanına giren kişilerin izinlerini yönetebilir ve bunun dışında birçok işi yapabilir. O yüzden bu kişilerin deneyimli olmaları gerekir. VTYS'yi anlattık. Bu veritabanı yönetim sistemlerine örnek verecek olursak; bunlar veritabanını yönetmeyi sağlayan MySQL, Oracle, Microsoft SQL Server, Postgresql, Apache, Access gibi sistemlerdir. Bunlar en bilinenleridir. Her biri ihtiyacımıza göre farklı yerlerde kullanılır. Biz derslerimizde MySQL veritabanını kullanacağız. Ders 158 - JDBC Tanımı JDBC (Java Database Connectivity), Java geliştiricilerine Java kodu üzerinden veritabanı yönetim sistemlerine erişim imkânı sağlayan bir Java arayüzüdür. Bu arayüz sayesinde Java uygulamalarımız üzerinden herhangi bir veritabanına bağlanıp veritabanından veri elde edebiliriz. JDBC, 2 katmandan oluşur. Bu yapının en üstünde JDBC API'si bulunur. Yazdığımız SQL komutlarını JDBC API, alt katmanında bulunan sürücü yöneticisine gönderir. Bu sürücü yöneticisi, veritabanları ile iletişime geçer ve dönen sonuçları JDBC API'ye gönderir. Peki, JDBC arayüzünü kullanmak için neler gereklidir? Bu arayüzü kullanmak için aşağıdaki öğeler gerekmektedir: Veri tabanı yönetim uygulaması (MySQL, MSSQL, ORACLE vb.) Java Database Server SQL Sorgulama dil bilgisi Veritabanı uygulaması ve Java uygulamamız arasındaki bağlatıyı sağlayacak kod Biz derslerimizde MySQL veritabanı yönetim aracını kullanacağız. Yukarıda bahsettiğimiz gibi JDBC için SQL sorgulama dilini de bilmeyi gerektiriyor. Bir sonraki dersimizde bu sorgulama dilinin komutlarına değineceğiz. Daha sonraki dersimizde ise uygulamalarımızda kullanacağımız veritabanı yönetim aracı olanMySQL'in kurulumuna geçelim. Ders 159 - Temel SQL Komutları VTYS için birçok sistemden bahsettik. Bu sistemler ile veritabanındaki kayıtları her türlü kontrol edebiliyor ve veritabanı üzerindeki ayarlamaları yapıyorduk. Peki, programımızdan bu veritabanına ulaşıp veri eklemeyi, silmeyi, güncellemeyi, tablolar oluşturmayı nasıl yapacağız? Çoğu veritabanı sistemlerinde SQL dili kullanılır. Programımızdan veya MySQL arayüzümüzden SQL komutlarını kullanarak veritabanımız üzerinde işlemler yapabiliriz. Şimbi bu temel komutları görelim. SELECT - WHERE - LIKE KOMUTLARININ KULLANIMI SELECT komutu, veritabanımızdaki kayıtları getirir. Genel kullanımı aşağıdaki gibidir. 1 SELECT * FROM tablo_adi Burada * işaretini kullanırsak tüm sütunları getir anlamına gelir. FROM kelimesinden sonra ise tablo adımız yazılır. Bir örnek verirsek: 1 SELECT * FROM Urunler Bu sorgu, Urunler tablosundaki tüm kayıtları getirir. Fakat biz her kaydı değil de belirli bir koşula bağlı olarak kayıtları getirmek istiyorsak, ne yapmalıyız? Bunun için kullanmamız gereken kelime WHERE kelimesidir. Bu kelimeden sonra koşulumuz yazılır. Aşağıdaki komutu inceleyelim. 1 SELECT * FROM Urunler WHERE fiyat>5000 Bu komut, Urunler tablosundan, fiyatı 5000'den büyük olan kayıtları getirir. Buraya kadar gösterdiğimiz komutlarda, bir kaydın tüm bilgilerini getiriyordu. Eğer biz koşulu sağlayan kayıtların sadece fiyat ve miktar bilgilerinin getirilmesini istiyorsak, yazacağımız komut aşağıdaki gibidir: 1 SELECT fiyat, miktar FROM Urunler Where fiyat>5000 Yukarıdaki komut, fiyatı 5000'den büyük olanların sadece fiyat ve miktar bilgilerini döndürür. Bir başka ihtimali de düşünelim. Tablomuzda x markalı bir ürünü getirsin istiyorsak ne yapmamız gerekir? Bir önceki örnekte WHERE ifadesinden sonra bir sayı karşılaştırdık. Fakat şimdi String veya Char bir ifade ile filtreleme yapmak isteyelim. Bunun için yazmamız gereken komut: 1 SELECT * FROM Urunler WHERE marka = 'x' Yukarıdaki ifade dediğimiz gibi Urunler tablosunda markası x'e eşit olan tüm kayıtları getirir. Şimdi farklı bir tablo üzerinde işlem yapalım ve bu sefer WHERE ifadesinin başka bir özelliğini kullanalım. SELECT * FROM Ogrenci WHERE ogrCinsiyet = 'E' AND 1 ogrYas = 21 Burada WHERE ifadesinden sonra 2 şart koyduk. Hem cinsiyeti E olan hem de yaşı 21 olan öğrencilerintüm bilgilerini getirmesini istedik. WHERE ifadelerinde birden fazla koşul kullanılabilir. WHERE ifadesi ile kullanılan bir ifade daha vardır. WHERE ile kayıtları filtreleyebiliyorduk. Aynı şekildeLIKE ifadesiyle de kayıtlar filtrelenir. Şimdi bir örnek verelim: SELECT * FROM Urunler WHERE UrunAdi LIKE '%A%' AND 1 UrunFiyat>1000 Yukarıdaki sorguda Urunler tablosundan, ürün adında A harfi bulunan kayıtlar ve fiyatı 1000'den büyük kayıtlar getirilir. Hem ilk şartı hem de ikinci şartı sağlayan kayıtlar getirilir. Aşağıdaki bir başka sorguyu inceleyelim. SELECT * FROM Urunler WHERE UrunMarka LIKE 1 '%A' Yukarıda da Urunler tablosunda ürün markası A harfi ile biten kayıtlar getirilir. Eğer T% yapsaydık, T harfi ile başlayan kayıtlar getirilirdi. LIKE ifadesinin kullanım şekli böyledir. Bir harf ile başlayan, biten veya içerisinde o harf bulunan kayıtları filtrelemek için kullanılır. SELECT, WHERE, LIKE komutlarının kullanılışı temel olarak bu şekildedir. Örnekler çoğaltılabilir. Biz örneklerimizin anlaşılması açısından temel olanları inceleyeceğiz. Veritabanı, başlı başına bir konudur. INSERT KOMUTU İLE KAYIT EKLEME INSERT komutu, tablolara kayıt eklemeye yarar. Genel kullanımı şu şekildedir: INSERT INTO tablo_adi VALUES (veri_1, veri_2, 1 veri_3) Yukarıda tablo_adi kısmına tablomuzun adını yazıyoruz. VALUES'ten sonra ise ekleyeceğimiz verilerigiriyoruz. Örnek verirsek; INSERT INTO Urunler VALUES (500, 'Bilgisayar', 1 1500) Yukarıda Urunler adlı tablomuzun 3 sütunu olduğunu farz ediyoruz. Bu 3 sütunun da miktar, ad ve fiyatolduğunu düşünelim. VALUES'ten sonra bu alanımıza sırayla verileri gönderiyoruz ve kaydımız ekleniyor. INSERT ile kayıt eklemenin başka bir yolu da şudur: INSERT INTO Kisiler (KisiAd, KisiSoyad, KisiMeslek) VALUES ('Okan', 'Bilke', 1 'Ogrenci') Bu şekilde de ekleme yapabiliriz. Böyle ekleme yapmanın faydası, eklediğimiz verilerin hangi sütuna eklendiğini bilmemizdir. DELETE KOMUTU İLE KAYIT SİLME DELETE komutu ile tablomuzdan verileri silebiliriz. Genel kullanımı aşağıdaki gibidir. 1 DELETE FROM tablo_adi FROM kelimesinden sonra tablomuzun adı yazılır. Yukarıdaki gibi sorgu yazarsak, bir şartımız olmadığı için o tablodaki tüm kayıtlar silinir. Eğer WHERE ile şart ekleyeceksek aşağıdaki gibi bir kullanım da olabilir. DELETE FROM Urunler WHERE UrunAdi LIKE 1 '%R%' Urunler tablosundan ürün adında R harfi olan tüm kayıtlar silinir. UPDATE KOMUTU İLE KAYIT GÜNCELLEME UPDATE komutu ile tablomuzdaki kayıtları güncelleyebiliriz. Genel kullanım şeklini bir örnekle açıklayalım. UPDATE Urunler SET UrunFiyat = '300' WHERE UrunAdi = 1 'Oyuncak' Burada Urunler tablomuzda Urun adı Oyuncak olan kaydın fiyatını 300 yapıyor. Sadece bir sütunu değil birden fazla sütunu da güncelleyebiliriz. Bunun için şöyle bir sorgu örneği gösterelim. UPDATE Urunler SET UrunFiyat='100' AND UrunStok='50' WHERE 1 UrunAdi='Bilgisayar' Urun adı Bilgisayar olan kaydın, Stok sayısını 50 ve fiyatını 100 yapıyor. Burada UrunFiyat, UrunStok, UrunAdi gibi ifadeler, bizim tablomuzdaki sütunların isimleridir. Tabloda üstün isimlerini nasıl kaydettiysek, sorgumuzda da o şekilde kullanmalıyız. Ders 160 - MySQL Kurulumu MySQL'i kurarak bilgisayarımızda bir MySQL sunucusu kurmuş oluruz ve verilerimizi bu sunucu üzerinden saklarız. Veritabanı yönetim aracımızın kurulumuna yönetim aracımızı internette indirerek başlayalım. MySQL sunucumuzu yükledik. Fakat burada bilmemiz gereken bir şey daha var. Programımızda veritabanı ile işlem yapmak istediğimizde bu sunucunun açık olması gerekir. İster bilgisayarın her açılışta bunu açmasını, istersek de gerektiğinde açık olmasını ayarlayabiliriz. Bunun için Bilgisayarım'a sağ tıklayıp Yönet diyoruz. Karşımıza gelen ekrandan Bilgisayar Yönetimi - Hizmetler ve Uygulamalar Hizmetler kısmına tıklıyoruz ve aşağıdaki gibi bir ekran elde edeceğiz. Buradan MySQL'in olduğu alana geliyoruz. MySQL hizmetini çalıştırmak ya da durdurmak için 2 kere tıklıyoruz. Başlat veya Durdur butonlarıyla hizmeti durdurup başlatabilirsiniz. Eğer bilgisayarın her açılışında başlamasını istiyorsak, Başlangıç Türü kısmından otomatik şıkkını seçiyoruz. Artık MySQL sunucumuz kurulmuş oldu. Veritabanları oluşturulabilir, kayıt ekleyebilir ve daha birçok işlemleri yapabiliriz. Bu işlemleri komut istemcisinden yapabiliriz, fakat bir uygulama indirip onun üzerinden yapmak daha hızlı olacaktır. Istisnalar: ! MySQL kurulumunda belirlediğiniz kullanıcı adı ve şifrenizi unutmayın. Veritabanına bağlanırken bu bilgileri kullanacağız. Ders 161 - MySQL İçin JDBC Connector Java üzerinden bir veritabanına bağlanmak için gerekli olan bir şey JDBC Connector, yani bağlantı nesneleridir. Bunlar, JDBC Driver ile sunucumuz arasında bağlantıyı kuran bir kütüphanedir. Bu bölümdeMySQL veritabanı yönetim uygulamasını kullanacağımızı daha önceden belirtmiştik. Şimdi bir JDBC Connectornesnesini Eclipse ortamına nasıl ekleyebileceğimizden bahsedelim. Bu linke tıklayarak MySQL sitesi üzerinden JDBC Driver for MySQL (Connector/J) nesnesini indiriyoruz. Eclipse üzerinden anlattığımız için bu mysql connector jar dosyasını Eclipse'de projemize eklemeyi gösterelim. mysql-connector-java-5.1.30.zip dosyası indikten sonra içerisinde bulunan mysql-connector-java-5.1.30-bin.jar dosyasını kullanacağız. 1. İlk yol JRE dizinine atmaktır. Program Files içerisinde Java klasörünün altında kullandığımız JREversiyonuna girelim. Bu klasör altında da sırasıyla lib ve ext klasörlerine girelim ve indirdiğimiz bu mysql connector nesnemizi buraya atalım. 2. Diğer yol olarak da projemize ekleyebiliriz. Bunun için Eclipse üzerinde Project - Properties - Java Build Path - Add External JARs diyerek bu connector nesnemizi ekleyelim. Connector nesnemizi bilgisayarımıza kurduktan sonra kod aşamamıza geçebiliriz. Şimdi Java üzerinden veritabanına bağlantının nasıl olduğunu görmek için bir örnek yapalım. 1 //databaseOrnek.java - 26.04.2014 2 3 import java.sql.*; 4 5 public class databaseOrnek 6 { 7 public static void main(String[] args) 8 { 9 baglanti(); 10 } 11 12 public static void baglanti() 13 { 14 try 15 { 16 Class.forName("com.mysql.jdbc.Driver"); 17 // veritabanı tipi 18 Connection connection = DriverManager.getConnection( 19 "jdbc:mysql://localhost:3306/test", "root", "12345"); 20 // bağlantı nesnesi 21 Statement state = connection.createStatement(); 22 ResultSet sonuc = state.executeQuery("Çalıştırılacak SQL 23 komutu"); 24 connection.close(); 25 } catch (Exception e) 26 { 27 e.printStackTrace(); 28 } 29 } 30 } Kodumuzda önce hangi tip veritabanına bağlanacağımızı belirttik. Daha sonra ise bağlantı nesnemizeveritabanı yolu, kullanıcı adı ve kullanıcı şifremizi vererek oluşturuyoruz. ResultSet nesnesi, veritabanından çektiğimiz bilgileri tutacak nesnemizdir. executeQuery() metoduna parametre olarak SQL sorgu komutunu gönderiyoruz ve sorgumuzu çalıştırıyoruz. Dönen sonucum ResultSet nesnemiz içerisinde oluyor. Ders 162 - JDBC Bileşenleri Java da veritabanı uygulamaları yazabilmemiz için bilmemiz gereken bir takım yazılımsal öğeler vardır. Bunlar veritabanına bağlantı, veritabanına sorgu gönderme ve veritabanından dönen verileri tutma gibi görevleri üstlenirler. Bu bileşenler aşağıdaki gibidir: Connection Statement ResultSet Bu bileşenlerden Statement bileşeni icra ettiği görev bakımından 3'e ayrılır. Şimdi bileşenlerimizi inceleyemeye başlayalım: CONNECTION Veritabanına bağlantı yapmamızı sağlayan bileşendir. Veritabanı ile Java uygulamamız arasında bir köprükurar. SQL sorguları bu bileşen sayesinde çalıştırılır ve dönen sonuçlar yine bu bileşen sayesinde bize döner.Connection bileşeni bağlantıyı oluşturduğu an Statement bileşeni oluşturulabilir hale gelir. Veritabanına bağlanabilmek için iki sınıftan yararlanabiliriz. Bunlar; DriverManager ve DataSource. Biz en çok kullanılan sınıf olan DriverManager sınıfını kullanacağız. Veritabanına bir Connection nesnesi oluşturabilmek için DriverManager sınıfının getConnection() metodunu kullanırız. Bu metodu kullanabilmemiz için üç parametreye ihtiyacımız vardır. Bunlar; bağlantı metni, veritabanı kullanıcı adı ve veritabanı kullanıcı şifresi. Genel bir bağlantı nesnesi aşağıdaki gibidir. 1 //ConnectionOrnek.java - 26.04.2014 2 3 import java.sql.DriverManager; 4 import java.sql.Connection; 5 6 public class ConnectionOrnek 7 { 8 public static void main(String[] args) 9 { 10 try 11 { 12 String baglanti = "jdbc:mysql://localhost:3306/test"; 13 // veritabanı adresidir. 14 String kulAdi = "root"; 15 String kulSifre = "12345"; 16 Connection connection = DriverManager.getConnection(baglanti, 17 kulAdi, kulSifre); 18 // connection nesnesi oluşturuldu, parametreler verildi 19 connection.close(); 20 } catch (Exception e) 21 { 22 e.printStackTrace(); 23 } 24 } 25 } Veritabanına bağlantıyı yukarıdaki örnekte olduğu gibi kurabiliriz. Veritabanı bağlantısıyla işimiz bittiğinde yukarıdaki örnekte olduğu bir bağlantımızı close() metoduyla kapatmalıyız. Aksi halde veritabanına ikinci kez ulaşmak istediğimizde hata almamız muhtemel olacaktır Veritabanına bağlantı için gerekli parametreleri vererek, Connection adında bir nesne oluşturduk. Bu nesne üzerinden veritabanımıza sorgular göndereceğiz. STATEMENT BİLEŞENLERİ Veri tabanı ile bağlantımızı oluşturduktan sonra SQL sorgularını çalıştırabilmek için Statementbileşenlerine ihtiyacımız vardır. Üç farklı Statement bileşeni vardır. Bunlar Statement, PreparedStatement veCallableStatement. Şimdi bu bileşenleri kısaca açıklamaya çalışalım. STATEMENT Static olarak oluşturulan bir Statement nesnesidir. Derleme olmaksızın çalıştırılan en hızlı bileşendir.executeQuery() metoduyla çalıştırılmak istenen SQL komutu çalıştırılabilir. Bu bileşenin yapısını ve kullanımını görmek için bir örnek yapalım. 1 //statementOrnek.java - 26.04.2014 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import java.sql.ResultSet; import java.sql.Statement; public class StatementOrnek { public static void main(String[] args) { try { Class.forName("com.mysql.jdbc.Driver"); //JDBC sürücüsünü yükledik String bagMetni = "jdbc:mysql://localhost:3306/test"; Connection bag = DriverManager.getConnection(bagMetni, "root", "12345"); // bağlantımızı oluşturduk. Statement st = bag.createStatement(); /* statement nesnemizi oluşturduk. bag nesnesi üzerinden * createStatement() metodunu çağırdık. */ String sql = "SELECT * FROM ogrenci"; // sorgu cümlesi oluşturduk ResultSet sonuc = st.executeQuery(sql); // SQL sorgumuzu çalıştırdık ve sonuç ResultSet nesnesi yüklendi bag.close(); } catch (Exception e) { e.printStackTrace(); } } } + 1. En üst satırda JDBC sürücüsünü yükledik. Konuyu anlatırken JDBC sürücüsünden bahsetmiştik. Veritabanı ile etkileşime geçerek dönen sonuçları JDBC API'ye gönderiyordu. 2. Bağlantı metnini verdik ve Connection nesnesi oluşturduk. 3. Bu nesne üzerinden createStatement() metodunu çağırdık ve bunu Statement tipinde bir nesneye atadık. Bu nesne üzerinden sorguları çalıştıracağız. 4. Daha sonra sorgu cümlemizi oluşturduk. Statement tipindeki st nesnesi üzerinden executeQuery()metodu ile sorgumuzu çalıştırdık ve dönen değeri ResultSet'e atadık. 5. Son olarak bağlantımızı kapattık. PREPAREDSTATEMENT PreparedStatement bileşeni, ön derlemeden geçirilen Statement bileşenidir. Çalıştırılacak SQL sorgunuzbirçok kez kullanılacağı zaman Statement bileşeninden daha iyi performans sunar. Bir sorgu birçok defa kullanılacaksa, yukarıdaki Statement ile yapacağımız sorgularda her seferinde bu sorgu derlenir. FakatPreparedStatement ile bir kere derleyip tekrar tekrar kullanabiliriz. Bu PreparedStatement bileşeninde, ayrıca SQL sorgusu içerisinde değer girilmesi gereken yerlerde yer tutucu olarak ? karakteri kullanılmaktadır. Bu bizi karmaşıklıktan bir nebze uzaklaştırır. Bu bileşenimizin yapısını daha iyi anlamak ve tutucuların nasıl kullanıldığını görmek için bir örnek yapalım. 1 //PreparedStatementOrnek.java - 26.04.2014 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 8 public class PreparedStatementOrnek 9 { 10 public static void main(String[] args) 11 { 12 try 13 { 14 Class.forName("com.mysql.jdbc.Driver"); 15 // JDBC sürücüsünü yükledik 16 17 String bagMetni = "jdbc:mysql://localhost:3306/test"; 18 Connection bag = DriverManager.getConnection(bagMetni, "root", 19 "12345"); 20 // bağlantımızı oluşturduk 21 22 String sql = "UPDATE ogrenci SET ogrAd =? WHERE ogrNo=?"; 23 PreparedStatement pSt = bag.prepareStatement(sql); 24 pSt.setString(1, "Sezer"); // ilk ? olan kısma atandı 25 pSt.setInt(2, 3361); // ikinci ? olan kısma atandı 26 /* PreparedStatement nesnemizi oluşturduk ve 27 * parametrelerimizi nesnemize geçirdik. */ 28 29 ResultSet sonuc = pSt.executeQuery(); 30 // SQL sorgumuzu çalıştırdık ve sonuc ResultSet nesnesi yüklendi 31 32 bag.close(); 33 } 34 catch (Exception e) 35 { 36 e.printStackTrace(); 37 } 38 } 39 } Örneğimizde gördüğünüz gibi bir PreparedStatement bileşeni oluşturduk ve bu bileşenimize daha önceden yazdığımız SQL komutunu parametre olarak atadık. Bundan sonraki kısımda ise setString() vesetInt() metotları yardımıyla SQL komutumuzdaki yer tutucuların olduğu bölgelere parametrelerimizi geçirdik. Yani sorgumuzda ? olan yerlere değerleri atadık. Bundan sonraki kısımda ise daha önceden yaptığımız gibiResultSet bileşenimize sonucumuzu aktardık. Bu sefer ResultSet bileşenine executeQuery() komutuyla sorgu aktarırken SQL sorgusunu parametre olarak vermediğimize dikkat edelim. SQL sorgumuzu daha önceden preparedStatement bileşenimize parametre olarak vermiş oluyoruz. CALLABLESTATEMENT CallableStatement bileşeni genellikle depolanmış yordamları (Stored Procedure) çağırmak için kullanılır. Bu bileşenimize daha önce anlattığımız iki bileşenin arası diyebiliriz. CallableStatement bileşenleri ön derleme yapılarak çalıştırılır, fakat yordam veritabanı üzerinde olduğu için tekrar derleme gerektirmez. Şimdi depolanmış yordamın nasıl çağrıldığını görmek için bir örnek yapalım. 1 CREATE OR REPLACE PROCEDURE ogrBilgiGetir( 2 no IN DBUSER.ogrNo%TYPE, 3 ad OUT DBUSER.ogrAd%TYPE, 4 soyad OUT DBUSER.orgSoyad%TYPE) 5 IS 6 BEGIN 7 SELECT ogrAd, ogrSoyad 8 INTO ad, soyad 9 FROM ogrenci WHERE ogrNo = no; 10 END; Yukarıdaki depolanmış yordam veritabanı üzerinde oluşturulur. Kısaca kayıtlı yordamımız INparametresiyle dışarıdan bir parametre alır. OUT parametresiyle dışarıya iki parametre gönderir. Sorgumuzda ise öğrenci no'sunu verdiğimiz kişinin adını ve soyadını verecek bir SQL kodu yazdık. Şimdi bu kayıtlı yordamın Java tarafından nasıl çağrıldığıyla ilgili örneğimize devam edelim. 1 //CallableStatementOrnek.java - 26.04.2014 2 3 import java.sql.CallableStatement; 4 import java.sql.Connection; 5 import java.sql.DriverManager; 6 import java.sql.ResultSet; 7 import java.sql.Statement; 8 9 public class CallableStatementOrnek 10 { 11 public static void main(String[] args) 12 { 13 try 14 { 15 Class.forName("com.mysql.jdbc.Driver"); 16 // JDBC sürücüsünü yükledik 17 18 String bagMetni = "jdbc:mysql://localhost:3306/ogrenci"; 19 Connection bag = DriverManager.getConnection(bagMetni, "root", 20 "12345"); 21 // bağlantımızı oluşturduk 22 23 String sqlYordam = "{call ogrBilgiGetir(?, ?, ?)}"; 24 CallableStatement callSt = bag.prepareCall(sqlYordam); 25 callSt.setInt(1, 3361); 26 // statement nesnemizi oluşturduk ve parametrelerimizi aktardık 27 callSt.registerOutParameter(2, java.sql.Types.VARCHAR); 28 callSt.registerOutParameter(3, java.sql.Types.VARCHAR); 29 callSt.executeQuery(); 30 // veritabanından dönecek değerlerin tipini belirledik ve 31 yordamımızı çağırdık. 32 33 String ogrAd = callSt.getString(2); 34 String ogrSoyad = callSt.getString(3); 35 // veritabanından dönen değerleri string nesnemize aktardık 36 bag.close(); 37 } 38 catch (Exception e) 39 { 40 e.printStackTrace(); 41 } 42 } } RESULTSET ResultSet, bileşenimiz, veritabanından dönen verileri içinde tutan bileşendir. Verileri bir kere ResultSetbileşenimize yükledikten sonra bu sınıfın next() metoduyla veri satırını elde edebiliriz. Daha sonra bu satır üzerinde doğru tip metotlarına istenilen parametreleri vererek verileri elde edebiliriz. Örneğin; elde ettiğimiz verinin ilk sütununda yer alan integer tipte veriyi çekmek istiyorsak resultSetNesnesi.getInt(1) yöntemini kullanırız. Şimdi bu bileşenin nasıl kullanıldığını görmek için bir örnek yapalım. 1 //ResultSetOrnek.java - 26.04.2014 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.ResultSet; 6 import java.sql.Statement; 7 8 public class ResultSetOrnek 9 { 10 public static void main(String[] args) 11 { 12 try 13 { 14 Class.forName("com.mysql.jdbc.Driver"); 15 // JDBC sürücüsünü yükledik 16 17 String bagMetni = "jdbc:mysql://localhost:3306/ogrenci"; 18 Connection bag = DriverManager.getConnection(bagMetni, "root", 19 "12345"); 20 // bağlantımızı oluşturduk 21 22 Statement st = bag.createStatement(); 23 // Statement nesnemizi oluşturduk 24 25 String sql = "SELECT * FROM ogrenci"; 26 ResultSet sonuc = st.executeQuery(sql); 27 // SQL sorgumuzu çalıştırdık ve sonuç ResultSet nesnesine 28 yüklendi 29 30 while(sonuc.next()) 31 { 32 System.out.println("Ogrenci ismi: " + sonuc.getString(1)); 33 // kolon indisi ile veriyi aldık 34 35 System.out.println("Öğrenci ismi: " + 36 sonuc.getString("ogrSoyad")); 37 // kolon ismi ile veriyi aldık 38 } 39 bag.close(); 40 } 41 catch (Exception e) 42 { 43 e.printStackTrace(); 44 } } } Yukarıdaki örneğimizde veritabanı bağlantımızı oluşturduk. SQL sorgumuzu çalıştırdıktan sonra verilerimizResultSet bileşenimiz içerisine yüklendi. Bundan sonraki kısımda elde ettiğimiz verileri while döngüsü venext() metodu yardımıyla verilerin sonuna gelene kadar okuduk. Bu metot ile imleç her seferinde bir alt satıra gelir. Verileri getString() metoduyla alırken ilk bölümde verimizi kolon indisi yardımıyla elde ettik. İkinci bölümde ise yine verimizi bu kez kolon ismi ile elde ettik. Burada next() metodu ile imleci bir alt satıra kaydırdık her seferinde. Fakat belirli bir satıra gitmesini istiyorsak, absolute() metodunun içerisine parametre olarak satır sayısını veririz. Belirli bir sayı kadar alt satırlara inmesini istiyorsak da relative() metoduna parametre olarak ilerlemek istediğimiz satır sayısını veririz. İmlecimiz de bu metotlara göre hareket eder. Ders 163 - JDBC İle Veri Sorgulama JDBC ile işlem yaparken SQL sorgulama komutlarını kullanacağız. Dersimizde yeri geldiği zaman ilgili SQL komutlarının da anlatımını göreceksiniz. Veritabanında veri sorgulamayı SQL komutlarından SELECT komutu üstlenir. Bu sorgu komutu istenilen tablodan istenilen alanları belirli kritere göre çekmeye yarar. SELECTkomutunun genel kullanımı aşağıdaki gibidir. 1 SELECT ogrNo, ogrAd FROM ogrenci Yukarıdaki sorgu komutu örneğinde ogrenci tablosundan ogrNo ve ogrAd bölümlerini seçmek istedik. Örnekteki gibi veritabanından belirli alanları çekmemiz gerektiğinde SELECT sorgu komutunun yanına çekmek istediğiniz alanları, aralarına virgül koyarak belirtebilirsiniz. SELECT komutu ile verilerimi sorgularken bazen belirli şartlara göre veri çekmemiz gerekebilir. Bu gibi durumlarda sorgu komutlarına şart komutu eklememiz gerekir. Eğer şartımız belli bir değer ise WHERE; değilse LIKE sorgu komutunu kullanırız. Bu komutların genel kullanımı aşağıdaki gibidir: 1 SELECT ogrAd, ogrSoyad FROM WHERE ogrNo = 3361 2 SELECT ogrAd, ogrSoyad FROM LIKE ogrNo = '%36%' Yukarıdaki ilk sorgu komutu öğrenci numarası 3361 olan öğrencinin adını ve soyadını getirir. İkinci sorgu komutu ise, öğrenci numarası içerisinde 36 olan öğrencinin adını ve soyadını getirir. Örnekte görüldüğü gibiLIKE komutunun kullanımında % işaretleriyle öğrenci numarasının bilmediğimiz yerlerini belirtiyoruz. Örnekte başını ve sonunu bilmediğimiz içerisinde 36 geçen öğrenci numarası olan öğrencileri çektik. Tabi bu işareti sadece başına koyarak öğrenci numarası 36 ile biten öğrencileri; sonuna % işareti koyarak öğrenci numarası 36 ile başlayan öğrencileri elde edebiliriz. Şimdi bu sorgu komutlarının JDBC bileşenleri ile nasıl çalıştığını görmek için bir örnek yapalım. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 //veriSorgulama.java - 26.04.2014 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class veriSorgulama { public static void main(String[] args) { try { Class.forName("com.mysql.jdbc.Driver"); // JDBC sürücüsünü yükledik String bagMetni = "jdbc:mysql://localhost:3306/test"; Connection bag = DriverManager.getConnection(bagMetni, "root", "12345"); // bağlantımızı oluşturduk Statement st = bag.createStatement(); Statement st1 = bag.createStatement(); // statement nesnemizi oluşturduk. String sql = "SELECT ogrAd, ogrSoyad FROM Ogrenci LIKE ogrNo = '3361'"; ResultSet sonuc = st.executeQuery(sql); // ilk SQL sorgumuzu çalıştırdık ve sonuç ResultSet nesnesine yüklendi String sql1 = "SELECT ogrAd, ogrSoyad FROM Ogrenci LIKE ogrNo = '%36%'"; ResultSet sonuc1 = st1.executeQuery(sql1); // ikinci SQL sorgumuzu çalıştırdık ve sonuç ResultSet nesnesine yüklendi while(sonuc.next()) { System.out.println("Öğrenci Adı: " + sonuc.getString("ogrAd")); System.out.println("Öğrenci Soyadı: " + sonuc.getString("ogrSoyad")); } // veritabanından gelen bilgileri yazdırdık while(sonuc1.next()) 47 { 48 System.out.println("Öğrenci Adı: " + 49 sonuc1.getString("ogrAd")); 50 System.out.println("Öğrenci Soyadı: " + 51 sonuc1.getString("ogrSoyad")); 52 } 53 // veritabanından gelen bilgileri yazdırdık } catch (Exception e) { e.printStackTrace(); } } } Örneğimizde oluşturduğumuz SQL sorgularını daha öncede bahsettiğimiz gibi Statement nesnemizinexecuteQuery() metoduna parametre olarak gönderdik ve dönen sonucu ResultSet nesnemize aktardık. Veritabanından dönen verilerin hepsini ekrana yazdırabilmek için while döngüsü içerisine ResultSetnesnemizin next() metodunu yazdık. Bundan sonraki kısımda ise verilerimizi ekrana yazdırmak için ResultSetnesnemizin getString() metodunu kullandık. Bu metot içerisinde de sütun isimlerini parametre olarak kullandık. Ders 164 - JDBC İle Veritabanına Veri Ekleme Veritabanına veri ekleyebilmek için SQL sorgu komutlarından INSERT komutunu kullanacağız. Bu komuta önce veritabanında hangi tabloya veri gireceğimizi belirtiriz. Veri gireceğimiz tabloyu belirttikten sonra tablomuzun yanına tablo içerisindeki hangi alanlara veri girişinin olacağını parantez içerisinde belirtiriz. En sonunda belirtilen alanlar için verilerimizi VALUES etiketinin yanına parantez açarak bu parantez içerisinde verilerimizi gireriz. Sorgu komutumuzu bu şekilde yazdıktan sonra, Ders 162 - JDBC Bileşenleri dersinde anlattığımız uygun statement metotlarından biri ile çalıştırırız. INSERT komutunun genel yapısı aşağıdaki gibidir. INSERT INTO ogrenci (ogrNo, ogrAd, ogrSoyad) VALUES (3361, 'Okan', 1 'Bilke') Burada ogrNo, ogrAd, ogrSoyad alanlarına bilgi gireceğimizi söyledik. VALUES kısmında ise eklenecek verileri sıraya göre yazdık. INSERT sorgu komutunun JDBC ile nasıl kullanıldığıyla ilgili bir örnek yaparak bu komutu daha iyi anlamaya çalışalım. 1 //veriEklemeOrnegi.java - 26.04.2014 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.ResultSet; 6 import java.sql.PreparedStatement; 7 8 public class veriEklemeOrnegi 9 { 10 public static void main(String[] args) 11 { 12 try 13 { 14 Class.forName("com.mysql.jdbc.Driver"); 15 // JDBC sürücüsünü yükledik 16 17 String bagMetni = "jdbc:mysql://localhost:3306/test"; 18 Connection bag = DriverManager.getConnection(bagMetni, "root", 19 "12345"); 20 // bağlantımızı oluşturduk 21 22 String sql = "INSERT INTO ogrenci(ogrNo, ogrAd, ogrSoyad) 23 VALUES(?, ?, ?)"; 24 PreparedStatement pSt = bag.prepareStatement(sql); 25 pSt.setInt(1, 3361); 26 // ilk ? kısmına 3361 ekledik 27 pSt.setString(2, "Okan"); 28 pSt.setString(3, "Bilke"); 29 /* PreparedStatement nesnemizi oluşturduk ve 30 * parametrelerimizi nesnemize geçirdik */ 31 32 ResultSet sonuc = pSt.executeQuery(); 33 // SQL sorgumuzu çalıştırdık ve sonuc ResultSet nesnesine 34 yüklendi 35 36 37 38 39 40 41 42 43 bag.close(); pSt.close(); // bağlantılar kapatıldı } catch (Exception e) { e.printStackTrace(); } } } Yukarıdaki örneğimizde verileri ekleyebilmek için SQL sorgu ifademizi oluşturduk ve bu ifademizi bağlantı nesnemizin prepareStatement() metoduna parametre olarak gönderdik. PreparedStatement bileşenine bağlantı nesnemizin bir örneğini aldıktan sonra, bu nesneye SQL sorgu ifademizde kullanacağımız parametreleri göndermek için bu nesnenin setInt() ile setString() metotlarını kullandık. Daha sonrasında bu nesnemizin executeQuery() metodunu kullanarak sorgumuzu çalıştırdık ve veritabanından dönen sonuçlarıResultSet nesnemize aktardık. Ders 165 - JDBC İle Veritabanından Veri Silme Veritabanındaki verileri silmek için SQL sorgu komutlarından DELETE komutunu kullanacağız. DELETEkomutunun çok basit bir yapısı vardır. DELETE sorgu komutu belirtilen tablodan belirtilen kriterlere göre verileri siler. DELETE sorgu komutunun genel kullanımı şu şekildedir: DELETE FROM ogrenci WHERE ogrNo = 1 3361 Burada ogrenci tablosundan ogrNo verisi 3361 olan tüm kayıtları sildik. Verileri silmek isterken şart komutunu kullanmazsak, sorgu komutu tablodaki verilerin tamamını siler. Silme komutumuzun JDBC ile nasıl kullanıldığını görmek için bir örnek yapalım. //veriSilmeOrnegi.java - 26.04.2014 1 2 import java.sql.Connection; 3 import java.sql.DriverManager; 4 import java.sql.Statement; 5 6 public class veriSilmeOrnegi 7 { 8 public static void main(String[] args) 9 { 10 try 11 { 12 Class.forName("com.mysql.jdbc.Driver"); 13 // JDBC sürücüsünü yükledik 14 15 String bagMetni = "jdbc:mysql://localhost:3306/test"; 16 Connection bag = DriverManager.getConnection(bagMetni, "root", 17 "12345"); 18 // bağlantımızı oluşturduk 19 20 Statement st = bag.createStatement(); 21 // statement nesnemizi oluşturduk 22 23 String sql = "DELETE FROM ogrenci WHERE ogrNo = 3361"; 24 st.executeQuery(sql); 25 // SQL sorgumuzu çalıştırdık. 26 } 27 catch (Exception e) 28 { 29 e.printStackTrace(); 30 } 31 } 32 } 33 Yukarıdaki örneğimizde bağlantımızı oluşturduk ve Statement nesnemize bağlantımızın adresini verdik. Daha sonrasında SQL sorgu ifademizi yazdık ve Statement nesnemizin executeQuery() metoduyla yardımıyla komutumuzu işleme koyduk. Bu örneğimizde ResultSet nesnesi kullanmadığımıza dikkat edin. DELETE komutunu kullandığımızda geriye veri dönmez. Dolayısıyla ResultSet nesnesini kullanmaya gerek yoktur. Ders 166 - JDBC İle Veritabanındaki Verileri Güncelleme Veritabanındaki verileri güncellemek için UPDATE komutunu kullanırız. Veritabanında güncelleyeceğimiz tablo adını UPDATE komutu yanına, alan isimlerini ise SET komutunun yanına yazarak, alanlara yeni vereceğimiz değerleri bu alanlara eşitleriz. Kriterimiz var ise verilerimiz yazdıktan sonra kriterlerimizi WHEREveya LIKE komutu yardımıyla belirtiriz. Kriter belirtmezsek, veritabanındaki tablodaki güncellenen alanların tümü UPDATE komutuyla güncellenir. UPDATE komutunun genel kullanımı şöyledir: UPDATE ogrenci SET ogrAd = 'Okan', ogrSoyad = 'Bilke' WHERE ogrNo 1 = 3361 Burada ogrNo alanı 3361 olan kaydın, ogrAd alanına Okan, ogrSoyad alanına Bilke yazıyoruz. Kullanmamız gereken tablo ise ogrenci tablosudur. Bu tablo üzerinden işlem yaparız. Şimdi güncelleme komutumuzun Java içerisinde nasıl kullanıldığını görmek için bir örnek yapalım. 1 //veriGuncellemeOrnegi.java - 26.04.2014 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.Statement; 6 7 public class veriGuncellemeOrnegi 8 { 9 public static void main(String[] args) 10 { 11 try 12 { 13 Class.forName("com.mysql.jdbc.Driver"); 14 // JDBC sürücüsünü yükledik 15 16 String bagMetni = "jdbc:mysql://localhost:3306/test"; 17 Connection bag = 18 DriverManager.getConnection(bagMetni); 19 // bağlantımızı oluşturduk 20 21 Statement st = bag.createStatement(); 22 // statement nesnemizi oluşturduk 23 String sql = "UPDATE ogrenci SET ogrAd = 'Okan', 24 ogrSoyad = 'Bilke' WHERE ogrNo = 25 3361"; 26 // kullanacağımız sorgu cümlesi 27 28 st.executeQuery(sql); 29 // SQL sorgumuzu çalıştırdık 30 } 31 catch (Exception e) 32 { 33 e.printStackTrace(); 34 } } } Yukarıdaki örneğimizde bir önceki örnekte yaptığımız gibi SQL sorgumuzu oluşturduk ve bunu Statementnesnemizin executeQuery() metoduna parametre olarak verdik ve sorgumuzu çalıştırmış olduk. Buraya kadar yaptığımız örneklerde bir veritabanımızın, tablomuzun ve sütunlarımızın olduğunu varsaydık. Bir sonraki dersimizde veritabanımızı ve tablolarımızı nasıl oluşturacağımızı öğreneceğiz. Ders 167 - Navicat Kurulumu Şimdiye kadar ki derslerimizde, tablomuzun ve sütunlarımızın olduğunu varsaydık. Şimdi gerçekten veritabanımızı ve tablomuzu oluşturalım. Bunun için Navicat programını kullanacağız. Bu program ile veritabanındaki tabloları alanları görsel olarak oluşturacağız. Programımızda da bu veritabanına kayıtlar ekleme, silme gibi işler yapacağız. İlk olarak Navicat programının kurulumunu anlatalım. İlk olarak Bu linke tıklayarak Navicat sitesine gidiyoruz. Karşımıza şöyle bir ekran gelecektir. Navicat for MySQL seçeneğinin altındaki Download Trial yazısına tıklıyoruz, daha sonra aşağıdaki gibi bir ekran göreceğiz. Buradan işletim sistemimize göre uygun olan sürümü indiriyoruz. İndirip kurulum dosyamızı çalıştırdıktan sonra aşağıdaki adımları takip ediyoruz. Next ile ilerliyoruz. Yükleme bittikten sonra artık programımızı kullanmaya başlayabiliriz. Navicat, veritabanımızı görsel olarak yönetmemizi sağlar. Tablo oluşturabilir, kullanıcı ekleyebilir, veritabanımıza sorgu ile eklenen kayıtları görebilir ve daha birçok işlemleri yapabiliriz. Bir sonraki dersimizde Navicat programımızı kullanarak temel veritabanı işlemleri yapacağız. Ders 168 - Navicat İle Örnek Uygulama Şimdiye kadar yaptığımız ekleme, silme gibi işlemleri veritabanındaki tabloları görsel olarak göstermedik. Sadece kod kısmında neler olduğunu anlattık. Şimdi Navicat programı ile tablolar oluşturacağız. Veritabanı üzerinde yaptığımız işlemlerin sonucunda nelerin değiştiğini görsel olarak veritabanımızda göreceğiz. Bunun için örnek olarak çalışanların bilgilerinin tutultuğu bir veritabanı oluşturalım ve üzerinde temel işlemleri yapalım. İlk olarak Navicat programımızı açıyoruz ve karşımıza şöyle bir arayüz geliyor. Sol üstteki Connection butonuna tıklayıp MYSQL yeni bir bağlantı oluşturuyoruz. Karşımıza gelen ekranı aşağıdaki gibi dolduralım. Password alanına MySQL i kurarken girdiğimiz şifreyi giriyoruz. Ders 160 - MySQL Kurulumu dersinde bunu anlatmıştık. Doldurduktan sonra bağlantımız oluşturulacaktır. Daha sonra bağlantımıza sağ tıklayalım ve New Database diyelim. Daha sonra karşımıza gelen ekrandaki bilgileri aşağıdaki gibi dolduralım. UTF - 8 olarak da işaretleyebilirsiniz. Sol tarafta veritabanımızın eklendiğini göreceksiniz. Üzerine çift tıklayıp altındaki dosyaları da açalım Daha sonra aşağıdaki gibi veritabanımızın üzerine sağ tıklayalım ve New Table diyerek bir tablo ekleyelim. Karşımıza aşağıdaki gibi bir ekran gelecektir. Buradaki gireceğimiz veriler, tablomuzdaki sütunları oluşturuyor. Allow Null kısmını işaretlemedik. Çünkü boş veri girilmesini istemiyoruz. Alt alta satırları oluşturmak için Add Field butonuna basıyoruz. İlgili alanları doldurduktan sonra CTRL+S tuşlarına basıyoruz ve bizden bir tablo adı girmemizi istiyor. Tablo adını da aşağıdaki gibi gibi isci olarak giriyoruz. Bu alanları doldurup kaydettikten sonra ekranı kapatıyoruz. Artık ana ekranımızda tablomuz görünüyor. Bu tabloya sağ tıklayarak Open Table diyoruz. Burada karşımıza tablomuz gelecektir. İçi şuan boş. Biz buraya manuel olarak birkaç bilgi girelim. Bilgileri girip CTRL+S tuşlarına basalım. Verileri girdiğimiz ekran aşağıdadır. Verileri girerken yeni kayıt eklemek için ekranın altındaki + tuşuna basabiliriz. Veritabanımı, tablomuzu ve içindeki verileri oluşturduk. Şimdi Eclipse'de bir proje açalım ve projemize yeni bir sınıf ekleyelim. Artık kod üzerinden bu veritabanına ulaşacağız ve veritabanımızdaki değişiklikleri göreceğiz. İlk olarak programımızı çalıştıracağımız isci sınıfını yazalım. Bu isci sınıfının main metodu içerisinde gerekli işlemleri yapacağız. Şimdi main metodunu boş bir şekilde verelim. Ekleme, çıkarma gibi sınıfları oluşturunca bumain metodunu dolduracağız. Projemize başlamadan önce MySQL Connector'ü Ders 161 - MySQL İçin JDBC Connector dersinde anlattığımız şekilde projemize ekliyoruz. isci Sınıfı: 1 //isci.java - 27.04.2014 2 3 public class isci 4 { 5 private String ad; 6 private String soyad; 7 private String sehir; 8 private String gorev; 9 10 public isci(String ad, String soyad, String sehir, String 11 gorev) 12 { 13 // yapıcı tanımlandı 14 this.ad = ad; 15 this.soyad = soyad; 16 this.sehir = sehir; 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 this.gorev = gorev; } public String getAd() // setter ve getter metotlar yazıldı { return ad; } public String getSoyad() { return soyad; } public String getSehir() { return sehir; } public String getGorev() { return gorev; } public static void main(String[] args) { // main metodu şimdilik boş } } Programımızı çalıştıracağımız isci sınıfını, içerisindeki getter metotları, değişkenleri yazdık. Şimdi projemize Ekleme adında bir sınıf oluşturalım. Daha sonra aşağıdaki kodları yazalım. Bu sınıf, veritabanımıza kayıt ekleyecektir. Ekleme Sınıfı: 1 //Ekleme.java - 27.04.2014 2 3 import java.sql.*; 4 5 public class Ekleme 6 { 7 public void ekle(isci i) 8 { 9 try 10 { 11 Class.forName("com.mysql.jdbc.Driver"); 12 13Connection bag = 14DriverManager.getConnection("jdbc:mysql://localhost:3306/calisandb", 15"root", "12345"); 16 // root ve 12345 alanına mysql kullanıcı adı ve şifrenizi girin. 17 18 String sql = "INSERT INTO isci VALUES(?, ?, ?, ?)"; 19 PreparedStatement p1 = bag.prepareStatement(sql); 20 p1.setString(1, i.getAd()); // ? olan kısımlar dolduruluyor 21 p1.setString(2, i.getSoyad()); // ? olan kısımlar dolduruluyor 22 p1.setString(3, i.getSehir()); // ? olan kısımlar dolduruluyor 23 p1.setString(4, i.getGorev()); // ? olan kısımlar dolduruluyor 24 25 int sonuc = p1.executeUpdate(); 26 if(sonuc == 1) 27 System.out.println("Kayıt Eklendi"); 28 else 29 System.out.println("Kayıt eklenemedi"); 30 p1.close(); 31 bag.close(); 32 // bağlantılar kapatıldı. 33 } 34 catch (Exception e) 35 { 36 e.printStackTrace(); 37 } 38 } } Bu sınıftaki ekle() metodu, parametre olarak i nesnesi alıyor. Aldığı bu i nesnesi üzerinden get()metotları ile ? olan kısımlara değerler atıyor. executeUpdate() metodu, işlemden etkilenen satır sayısınıdöndürdüğü için eğer ekleme işlemi sorunsuz yapıldıysa sonuc değişkeni 1 oluyor ve "Kayıt Eklendi" yazıyor. Değilse "Kayıt Eklenemedi" yazısını konsolda gösteriyor. Ekleme sınıfını oluşturduğumuza göre artık isci sınıfındaki main metodunun içerisini doldurabiliriz. mainmetodumuzun içi aşağıdaki gibi olacaktır. 1 public static void main(String[] args) 2 { 3 isci i = new isci("elektro", "arge", "ankara", "database 4 administrator"); 5 Ekleme e = new Ekleme(); 6 e.ekle(i); } main metodumuza bu kodları yazdık. isci sınıfından bir nesne oluşturduk ve ilk değerlerini verdik. Bu değerler, yapıcı sayesinde ilgili değişkenlere atandı. Daha sonra Ekleme sınıfından nesne oluşturduk ve bu nesne üzerinden Ekleme sınıfındaki ekle() metodunu çağırdık. Değer olarak da i nesnesini gönderdik. Çünkü eklenecek kayıtların bilgileri bu i nesnesinde tutuluyor. ekle() metoduna bakarsanız, isci sınıfından inesnesini parametre olarak alıyor. Bu ekle() metodunda da getAd() gibi metotları çağırdık ve isci sınıfında adbilgisini tutan getter metodu çağırmıştık. Programımızı çalıştırdığımızda konsol ekranımızda aşağıdaki gibi bir çıktı elde edeceğiz. 1 Kayıt Eklendi Navicat programından da veritabanımızdaki eklenen kaydı görelim. Bunun için isci adlı tabloya çift tıklayalım ve aşağıdaki eklenen kaydı görelim. Programımızı çalıştırdığımızda eklenen kaydı yukarıda gördük. Şimdi de silme işlemi yapan sınıfımızı yapalım. Silme Sınıfı: 1 //Silme.java - 27.04.2014 2 3 import java.sql.*; 4 5 public class Silme 6 { 7 public void silme (String a) 8 { 9 try 10 { 11 Class.forName("com.mysql.jdbc.Driver"); 12Connection bag = 13DriverManager.getConnection("jdbc:mysql://localhost:3306/calisandb", 14 "root", "12345"); 15 // root ve password alanına kendi belirlediklerinizi girin 16 String sql = "DELETE from isci WHERE ad=?"; 17 PreparedStatement p1 = bag.prepareStatement(sql); 18 p1.setString(1, a); 19 20 int sonuc = p1.executeUpdate(); 21 if (sonuc ==1) 22 System.out.println("Kayıt Silindi"); 23 else 24 System.out.println("Kayıt Silinemedi"); 25 bag.close(); 26 p1.close(); 27 // bağlantılar kapatıldı 28 } 29 catch (Exception e) 30 { 31 e.printStackTrace(); 32 } 33 } 34} Bu sınıftaki silme() metodumuz ise bir String ifade alıyor. Yani biz isci sınıfında silinmesini istediğimiz kişinin adını parametre olarak göndereceğimiz için bunu yaptık. Sorgumuzda da ad değişkeni a'ya eşit olan veriyi siliyor. Şimdi yine isci sınıfının main metoduna ne yazacağımıza bakalım. 1 public static void main(String[] args) 2 { 3 Silme s = new Silme(); 4 s.silme("Mustafa"); 5 } Silme sınıfından nesne oluştururuz ve bu nesne üzerinden silme() metodunu çağırırız. Metoda parametre olarak da silinecek kişinin adını gireriz. İstersek ada göre değil de başka bir veriye göre silme işlemi yapabiliriz. Bunun için sorguda değişiklik yapmamız gerekir. main metodumuzu çalıştırdığımızda konsol ekranındaki çıktımız şu şekilde olacaktır: 1 Kayıt Silindi Navicat programımızdan kayıtlara baktığımızda, adı Mustafa olan veriyi sildiğini görürüz. Görüldüğü gibi kaydımız silinmiştir. Şimdi de Guncelleme adında bir sınıf oluşturalım ve daha sonra aşağıdaki kodları yazalım. Guncelleme Sınıfı: 1 //Guncelleme.java - 27.04.2014 2 3 import java.sql.*; 4 5 public class Guncelleme 6 { 7 public void Guncelleme(String soyad, String yeniGorev) 8 { 9 try 10 { 11 Class.forName("com.mysql.jdbc.Driver"); 12 13Connection bag = 14DriverManager.getConnection("jdbc:mysql://localhost:3306/calisandb", 15"root", "12345"); 16 // root ve 12345 alanına mysql kullanıcı adı ve şifrenizi girin. 17 18 String sql = "UPDATE isci SET gorev=? WHERE soyad=?"; 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 } } PreparedStatement p1 = bag.prepareStatement(sql); p1.setString(1, yeniGorev); p1.setString(2, soyad); int sonuc = p1.executeUpdate(); // sorgu çalıştırılır if (sonuc == 1) // etkilenen satır varsa System.out.println("Kayıt Güncellendi"); else System.out.println("Kayıt Güncellenemedi"); bag.close(); p1.close(); // bağlantı kapatıldı } catch (Exception e) { e.printStackTrace(); } Bu sınıftaki metodumuz soyad ve yeniGorev parametrelerini alıyor. Aldığı ilk parametreyi sorgumuzdaki2. soru işaretinin olduğu yere ekliyor. Diğer yeniGorev parametresini ise sorgudaki ilk soru işaretinin olduğu yere ekliyor. Sorgumuz bu şekilde yapılandırılıyor. Bunu ise prepareStatement ile sağlıyoruz. Şimdi ise isci sınıfının main metoduna aşağıdaki kodları girelim. 1 public static void main(String[] args) 2 { 3 Guncelleme g = new Guncelleme(); 4 g.Guncelleme("Tuna", "Patron"); 5 } isci sınıfını çalıştırdığımızda konsolda şu çıktıyı elde edeceğiz: 1 Kayıt Güncellendi Navicat programımızdan kontrol ettiğimizde ise soyadı Tuna olan kişinin görevini Patron yapıyor. Listeleme Sınıfı: 1 //KayitGetir.java - 27.04.2014 2 3 import java.sql.*; 4 5 public class KayitGetir 6 { 7 public void KayitGetir(String ad) 8 { 9 try 10 { 11 Class.forName("com.mysql.jdbc.Driver"); 12 13Connection bag = 14DriverManager.getConnection("jdbc:mysql://localhost:3306/calisandb", 15"root", "12345"); 16 // root ve 12345 alanına mysql kullanıcı adı ve şifrenizi girin. 17 18 String sql = "SELECT * from isci WHERE ad=?"; 19 PreparedStatement p1 = bag.prepareStatement(sql); 20 p1.setString(1, ad); 21 ResultSet sonuc = p1.executeQuery(); 22 // sorgudan dönen değerler ResultSet'e aktarıldı 23 while(sonuc.next()) // ResultSet'teki tüm kayıtlar okundu 24 { 25 System.out.println(sonuc.getString("ad")); 26 System.out.println(" - "); 27 System.out.println(sonuc.getString("soyad")); 28 System.out.println(" - "); 29 System.out.println(sonuc.getString("sehir")); 30 System.out.println(" - "); 31 System.out.println(sonuc.getString("gorev")); 32 } 33 34 35 36 37 38 39 40 } 41} bag.close(); p1.close(); } catch (Exception e) { e.printStackTrace(); } Yukarıdaki sınıfta metodumuz ad parametresi alıyor ve bu parametreyi sorgumuza ekliyor. Sorgumuzda * from dediğimiz için WHERE şartına uyan tüm kayıtları getirir. While döngüsünde ise şartımıza uyan tüm kayıtları satır satır okuruz. Önceki örneklerdeki gibi executeUpdate() metodunu çağırmadık çünkü etkilenen satır sayısı diye bir şey yok. Sadece kayıtları getirme işlemi yapıyoruz. O yüzden executeQuery() metodunu çağırdık. isci sınıfının main metoduna ise aşağıdaki kodları yazalım. KayitGetir sınıfından nesne oluşturarakKayitGetir adlı metoda parametre olarak Okan String'ini gönderdik. İsmi Okan olan kayıtlar getirilecek. Çünkü sorgumuzda WHERE ifadesinden sonra şart olarak ad alanını koyduk. public static void main(String[] args) 1 { 2 KayitGetir k = new KayitGetir(); // isci sınıfının main 3 metodu 4 k.KayitGetir("Okan"); 5 } Programı çalıştırdığımızda konsolda aşağıdaki gibi bir çıktı elde edeceğiz. 1 Okan - Bilke - Ankara - Yazılımcı Adı Okan olan tüm kayıtları getirdi. Navicat üzerinden bir şeye bakmamıza gerek yoktur. Çünkü biz sadece kayıt getirme işlemi yaptık. Ders 169 - Thread Kavramına Giriş Yazdığınız bir uygulamada bir metot işlenirken, aynı anda for döngüsünü işleyemeyiz. Başka bir döngüye girmek için metodun işlenmesi gerekir. Fakat gelişmiş uygulamalarda bu böyle olmayacaktır. Mesela; network üzerinde iletişim sağlayan bir uygulama geliştirdiğimizde aynı anda veri alabilmeli ve veri gönderebilmeliyiz. Çalıştırdığınız her farklı blok için bir kanal açılır. Buna thread denir. Bu sayede bir işin bitmesini beklemeden başka bir iş yapabiliriz. Bilgisayar ortamında da bu böyledir. Aynı anda birçok programı açabilir ve çalışmalarını sağlayabiliriz. Buna multithreading denir. Dediğimiz gibi açılan her program için bir kanal verilir ve bu sayede programlarımızı eş zamanlı olarak çalıştırabiliriz. Thread kavramı için olaya başka yönden yaklaşalım. Yazacağımız büyük çaplı uygulamalarımızda, işlemcimizi tek bir görev için uzun süre çalıştırmak, akılcı bir çözüm olmayacaktır. Thread yapısı, uygulama işlemlerinin işlemciyi zaman paylaşımlı olarak kullanmasını sağlar. Bu yüzden çok fazla işlem yapacağımız veya işlemin icra edilmesi sırasında bekleme süresi olan işlemlerimiz için thread yapısını kullanmak akılcı bir çözüm olacaktır. Başka bir örnek vermek gerekirse; internetten veri indirirken, form üzerinde bazı işlemlerinde yapılması gereken bir uygulama yapmamız gerekiyor. Bu durumda normal şartlarda uygulamamız veri internetten indirilene kadar form üzerindeki işlemleri gerçekleştiremeyecektir. Bu uygulama üzerinde threadyapısı kullanılırsa, form üzerindeki işlemleri yapan metot ve internetten veri indirme metodu zaman paylaşımlı olarak işlemciyi kullanır ve uygulama üzerinde aksaklık olmaz. Bundan sonraki dersimizde thread nasıl oluşturulur ve çalıştırılır onu göreceğiz. Ders 170 - Thread Oluşturma Java dilinde thread oluşturmanın iki yolu vardır. Bunlardan birincisi thread sınıfını miras(extend) almaktır. Bu yöntemi kullandığınızda başka sınıfları miras alamayacaksınız. İkinci yöntem ise Runnable arayüzünü implement etmek. İkinci yöntem birinci yöntemden karmaşık yapısıyla daha fazla kod yazmanızı gerektirebilir, ama başka sınıfları miras almanıza olanak sağlayacaktır. Aşağıdaki örnekte thread sınıfını miras alarak nasıl thread nesnesi oluşturulacağı gösterilmiştir. //ThreadYapisi.java - 27.04.2014 1 2 public class ThreadYapisi 3 { 4 public static void main(String[] args) 5 { 6 Ornek o1 = new Ornek(); 7 o1.start(); 8 } 9 } 10 class Ornek extends Thread 11 { 12 public void run() 13 { 14 System.out.println("Ornek adlı kanal 15 çalışıyor"); 16 } 17 } 18 Ekran çıktısı: 1 Ornek adlı kanal çalışıyor Yukarıda, işlemlerimizi yapacağımız ornek adlı sınıfı, Thread sınıfından miras alıyoruz. Bu sınıftan bir nesne oluşturuyoruz ve kanalı başlatmak için start() metodunu kullanıyoruz. Bu metot çağırıldığında run()metodu çalışır. Bu run() metodu, thread içerisinde yapılacak işlemleri içerir. Kısacası bir sınıfın threadolabilmesi için run() metodunu içermesi gerekir. Thread sınıfına ait bu run() metodu, override edilmiştir. Başka bir örnek verelim. 1 //ThreadYapisi2.java - 27.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class ThreadYapisi2 { public static void main(String[] args) { Ornek2 o1 = new Ornek2(); } } class Ornek2 extends Thread { public Ornek2() { start(); } public void run() { for (int i = 0 ; i < 5 ; i++) System.out.println(i); } } Ekran çıktısı: 1 0 2 1 3 2 4 3 5 4 Bu örnekte ise nesnemiz üzerinden start() metodunu çağırmadık. Bir nesne oluştuğu ilk anda çalışan yapıcı içerisine start() metodunu yazdık. Bu metot da run() metodunu çağırdı ve for döngümüz çalıştı. Thread sınfını miras alarak son bir örnek yapalım. 1 //ThreadYapisi3.java - 27.04.2014 2 3 public class ThreadYapisi3 4 { 5 public static void main(String[] args) 6 { 7 Ornek3 o1 = new Ornek3(3, "Okan"); 8 } 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 } class Ornek3 extends Thread { private int sayi; private String ad; public Ornek3(int sayi, String ad) { this.ad = ad; this.sayi = sayi; start(); } public void run() { for (int i = 0 ; i < 5 ; i++) System.out.println("Sayı ve Ad: " + ad + " - " + sayi); } } Ekran çıktısı: 1 Sayı ve Ad: Okan - 3 2 Sayı ve Ad: Okan - 3 3 Sayı ve Ad: Okan - 3 4 Sayı ve Ad: Okan - 3 5 Sayı ve Ad: Okan - 3 Bu örneğimizde de yapıcımız içinde atama işlemleri yaptık. Daha sonra start() metodu ile kalanı başlattık. Başlatınca run() metodu çalıştı ve içerisindeki işlemler yapıldı. Runnable arayüzünü implement ettiğimizde is, Thread sınıfını miras alamadığımız için bu sınıfa özel bazı metotları kullanamayacağız. Bu nedenden dolayı ilk yönteme göre daha fazla kod yazmamız gerekecektir. Aşağıdaki örnekte Runnable sınıfını implement ederek, nasıl thread nesnesi oluşturulabileceği gösterilmiştir. 1 //threadOrnegiRunnable.java - 27.04.2014 2 3 public class threadOrnegiRunnable implements Runnable 4 { 5 Thread kanal; 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // thread nesnemizi oluşturduk. public void threadOrnegiRunnable() { kanal = new Thread(this); // oluşturduğumuz nesneye metodumuzu referans olarak verdik kanal.start(); // nesnemizi başlattık try { kanal.sleep(1000); // nesnemizi beklettik } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { threadOrnegiRunnable(); // yapılandırıcı metod } } Yukarıdaki örneğimizde daha önceki yaptığımız örneğimizin aynısını, bu sefer Runnable arayüzünüimplement ederek yaptık. Thread sınıfının metotlarını kullanamadığımız için bu sınıfın metotlarına oluşturduğumuz thread nesnesi üzerinden eriştik. Sınıfımızın metodunu yine oluşturduğumuz nesneyereferans olarak gönderdik. Runnable arayüzünün avantajı, daha önce de belirttiğimiz gibi başka sınıfları miras almaya olanak sağlar. Aşağıdaki örnek, thread nesnesi oluşturma ve kullanımı ile ilgilidir. 1 2 public class threadOrnek 3 { 4 public static void main(String[] 5 args) 6 { 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 Thread thread = new threadOrnk(); // thread nesnemizi oluşturduk } } class threadOrnk extends Thread { threadOrnk() { start(); // thread başlatıldı. } public void run() { for (int i = 0 ; i <= 5 ; i++) { System.out.print(i); } // ekrana sayıları yazdırdık } } Ekran çıktısı: 1 012345 Ders 171 - Thread'i Başlatmak ve Durdurmak Thread nesnelerini belirli zamanlarda başlatıp durdurabiliriz. Bunun için Thread sınıfının bize sağladığıstart() ve stop() metotlarını kullanacağız. start() metodu ile Thread nesnemizin yaşam döngüsünü başlatırız ve stop() metodu ile nesnemizin yaşam döngüsünü kalıcı olarak sonlandırırız. Birden fazla Thread nesnesi çalışacaksa, ilk başlatılan nesnenin daha önce çalışacağı garanti edilmez. Thread nesneleri işlemcinin çalışma boşluklarına göre hareket ederler. Bu sebeple daha önce başlatılan nesnenin önce çalışacağı garanti edilemez. Aşağıdaki örnek Thread nesnelerini başlatıp durdurmayı gösteren ve ekrana Thread numarasınıyazdıran bir örnektir. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 //threadBasDurOrnegi.java - 27.04.2014 public class threadBasDurOrnegi { public static void main(String[] args) { Thread thread1 = new threadOrnek("1.thread"); Thread thread2 = new threadOrnek("2.thread"); thread2.stop(); Thread thread3 = new threadOrnek("3.thread"); Thread thread4 = new threadOrnek("4.thread"); // nesnelerimiz oluşturduk ve 2. nesnemizi durdurduk. } } class threadOrnek extends Thread { threadOrnek (String isim) { // nesnemize ismini verdik ve yapılandırdık super (isim); start(); // nesnemizi başlattık } public void run() { System.out.println(Thread.currentThread().getName()); // Şu an çalışır durumda olan nesnenin ismini ekrana yazdırdık. } } Ekran çıktısı: 1 3.thread 2 4.thread 3 1.thread Örnekte görüldüğü gibi Thread sınıfını miras alan bir sınıf oluşturduk ve bu sınıfımızdan nesne türettik. Birinci nesnemiz aynı zamanda ilk başlattığımız nesnemiz oldu. Fakat ekran çıktımıza baktığımızda ise ilk olaraküçüncü nesnemizin çalıştığını görüyoruz. İkinci nesnemiz de çalıştıktan kısa bir süre sonra durdurduk. Bu kısa süre içerisinde ekran çktısında ikinci nesnemizin çalıştığını da görebilirdik. Nesnemizi durdurduğumuz için ekran çıktısında görmedik. Thread nesneleri başlatılırken, dikkat edilecek bir diğer önemli nokta ise; nesneyi iki kerebaşlatmamaktır. Thread nesnesini iki kere başlatmamız IllegalThreadStateException hatasını üretmeye sebep olacaktır. Bu noktayı daha iyi görebilmek için yukarıdaki örneğimizi değiştirelim. //threadBasDurOrnegi2.java - 27.04.2014 1 2 public class threadBasDurOrnegi2 3 { 4 public static void main(String[] args) 5 { 6 Thread thread1 = new threadOrnek("1.thread"); 7 thread1.start(); 8 // nesnemizi oluşturduk ve 2. kez başlattık 9 } 10 } 11 12 class threadOrnek2 extends Thread 13 { 14 threadOrnek2 (String isim) 15 { 16 // nesnemize ismini verdik ve yapılandırdık 17 super (isim); 18 start(); 19 // nesnemizi başlattık 20 } 21 22 public void run() 23 { 24 System.out.println(Thread.currentThread().getName()); 25 // Şu an çalışır durumda olan nesnenin ismini ekrana 26 yazdırdık. 27 } 28 } 29 Ekran çıktısı: 1 Exception in thread "main" java.lang.IllegalThreadStateException 2 at java.lang.Thread.start(Unknown Source) 3 at threadBasDurOrnegi2.main(threadBasDurOrnegi2.java:8) 4 1.thread Yukarıdaki örneğimizde görüldüğü gibi thread1 nesnemizi iki defa başlattık. Ekran çıktımızda ise IllegalThreadStateException hatası verildiğini, ardından ise nesnemizin icra edildiğini gördük. Ders 172 - Thread'i Beklemeye Almak ve Devam Ettirmek Thread nesnelerinin belirli aralıklarla çalışıp durmasını veya biz tekrar çalışmasını isteyene kadar durmasını sağlayabiliriz. Nesnemizi üç yöntem ile beklemeye alabiliriz. 1. İlk yol, nesnemize bir süre vererek onu bu süre zarfı içerisinde uykuya gönderme metodudur. Bu yöntemde nesnemize sleep() metodu ile milisaniye cinsinden uyuması için bir süre göndeririz. Nesnemiz bu süre zarfında uykuda bekler. 2. İkinci yöntemde ise yield() metodunu kullanırız. Bu metot, kullanıldığı nesne ile aynı önceliğe sahipThread nesnesinin çalışmasını bekler ve bu nesnenin işi bittikten hemen sonra tekrar çalışır duruma geçer. 3. Üçüncü yöntem ise nesne wait() metodu yardımıyla beklemeye alınır ve tekrar çalışması için uyarılana kadar beklemede kalır. Nesneyi tekrar çalışma durumuna geçirmek için notify() veya notifyAll()metotlarını kullanırız. Şimdi bu metotları daha iyi anlayabilmek için bir örnek yapalım. 1 //threadBekleme.java - 27.04.2014 2 3 public class threadBekleme 4 { 5 public static void main(String[] args) throws InterruptedException 6 { 7 for (int i = 1 ; i <= 3 ; i++) 8 { 9 Thread kanal1 = new threadOrnek(i, "thread1"); 10 kanal1.yield(); 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 Thread kanal2 = new threadOrnek(i, "thread2"); // nesnelerimizi oluşturduk ve ilk nesnemizi kısa süreliğini uyuttuk } } } class threadOrnek extends Thread { int sayi = 0; String isim; threadOrnek (int sayi, String isim) throws InterruptedException { super(isim); this.sayi = sayi; this.isim = isim; start(); // nesnemizi başlattık sleep(100); // nesnemizi 0.1 sn uykuya aldık } public void run() { System.out.println(Thread.currentThread().getName() + "[" + sayi + "]"); // nesnemiz içerisindeki sayıyı yazdırdık } } Ekran çıktısı: 1 thread1[1] 2 thread2[1] 3 thread1[2] 4 thread2[2] 5 thread1[3] 6 thread2[3] Örneğimizde nesnelerimize verdiğimiz sayıları ekranda yazdırdık. Ekran çıktısında görüldüğü gibi ilk nesnemizi, ikinci nesnemize kısa süreliğine avantaj sağlamak için beklemeye aldık. sleep() metoduna verdiğimiz süre ile nesnemizin 0.1 sn uyumasını sağladık. Uygulamamız bu işlem sayesinde ekrana sonuçları0.1 sn aralıklarla yazdırdı. Ders 173 - Bir Thread Nesnesine Öncelik Atamak Kullanacağımız Thread nesnelerimizde bazı nesnelerimizin daha önce çalışmasını veya daha öncelikli olmasını sağlayabiliriz. Öncelikli olan bu nesnelere, işlemci daha çok yer ayırır ve öncelik tanır. Şimdi aşağıda bir örnek yapalım ve öncelik konusunu örnek üzerinde gösterelim. 1 //threadYapisi.java - 27.04.2014 2 3 public class threadYapisi 4 { 5 public static void main(String[] args) throws 6 InterruptedException 7 { 8 thread1 t1 = new thread1(); 9 t1.setPriority(Thread.MIN_PRIORITY); // öncelik 10 ataması 11 t1.start(); 12 thread2 t2 = new thread2(); 13 t2.setPriority(Thread.MAX_PRIORITY); // öncelik 14 ataması 15 t2.start(); 16 } 17 } 18 19 class thread1 extends Thread 20 { 21 public void run() 22 { 23 while(true) // sonsuz döngü 24 { 25 System.out.println("Okan"); 26 } 27 } 28 } 29 30 class thread2 extends Thread 31 { 32 public void run() 33 34 35 36 37 { while(true) // sonsuz döngü { System.out.println("Onur"); } } } Bu programın çıktısında, Onur isminin daha çok çıktığını göreceksiniz. Çünkü t2 nesnesine yüksek öncelik atadık. Tam tersini yaptığımızda ise işlerin farklı olduğunu göreceksiniz. Tabi işlemci, arkaplanda t2 kanalıdadaha çok alan ayıracaktır. Değerleri görebilmek için programı sonsuz döngüye soktuk. Console'daki kırmızı renkli durdurma tuşuna basarak programı durdurabilirsiniz. Bu işlemi Thread sınıfının öncelik atama metodu olan setPriority() metodu ile sağlarız. Bu metoda yineThread sınıfı içerisinde tanımlı olan üç sabitten birini göndererek nesnemize öncelik atayabiliriz. Bu sabitler şöyledir: MIN_PRIORITY: Düşük öncelik. NORM_PRIORITY: Normal öncelik, aynı zamanda varsayılan öncelik tipidir. MAX_PRIORITY: Yüksek öncelik. Parentez içerisine yukarıdaki değerleri yazmak yerine sayısal değerler de yazabiliriz. Thread nesnesinin önceliğini yüksek atamak, düşük öncelikli nesnelere göre erişimi kolaylaştıracaktır. BirThread nesnesine öncelik atayabileceğimiz gibi nesnemizin önceliğini de kontrol edebiliriz. Bu işlemi isegetPriority(); metodu ile halledebiliriz. Bu metot ile thread'lerin öncelikleri öğrenilir. Bu metotları daha iyi görebileceğimiz bir örnek yapalım. 1 //threadOncelikOrnegi.java - 27.04.2014 2 3 public class threadOncelikOrnegi 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 { public static void main(String[] args) throws InterruptedException { Thread kanal1 = new threadOrnek("1. thread"); kanal1.setPriority(Thread.MIN_PRIORITY); // ilk nesnemizi oluşturduk ve önceliği düşük olarak atadık Thread kanal2 = new threadOrnek("2. thread"); kanal2.setPriority(Thread.MAX_PRIORITY); // ikinci nesnemizi oluşturduk ve önceliği yüksek olarak atadık Thread kanal3 = new threadOrnek("3. thread"); // üçüncü nesnemizi oluşturduk ve öncelik atamadık System.out.println(kanal1.getPriority()); System.out.println(kanal2.getPriority()); System.out.println(kanal3.getPriority()); // nesnelerimizin öncelik değerlerini ekrana yazdırdık } } class threadOrnek extends Thread { threadOrnek(String isim) // yapıcı { super(isim); start(); // nesnemizi başlattık } public void run() { System.out.println(Thread.currentThread().getName()); // nesnemizin ismini yazdırdık } } Ekran çıktısı: 1 1. thread 2 2. thread 3 4 5 6 1 10 5 3. thread Yukarıdaki örneğimizde nesnelerimizi oluşturduktan sonra önceliklerini belirledik. Daha sonrasında ise nesnelerimizin önceliklerini elde edebilmek için sınıfımızın sağladığı metodu kullandık. Nesnelerimizin öncelikleri, nesnelerimiz icra edilmeden elde edildi. Buna göre ilk nesnemizin önceliğinin sayısal değeri en düşük, ikinci nesnemizin sayısal değeri en büyük ve öncelik atamadığımız nesnemizin sayısal değeri ise bunlararasında kalıyor. Nesnelerimize atadığımız öncelik değerlerine göre sayısal değerlerin öncelikle doğru orantılı olduğunu söyleyebiliriz. Ekran çıktımızda tekrar baktığımızda ise önceliği en yüksek olan nesnemizin ilk önce icra edildiğini ve önceliği en düşük olan nesnemizin en son icra edildiğini görüyoruz. Ders 174 - Thread'in Çalışıp Çalışmadığının Kontrolü Thread nesneleriyle uygulama yazarken bazen nesnenin halen çalışıp çalışmadığını kontrol etmemiz gerekir. Bazı durumlarda yapılacak işleri, nesnenin çalışıp çalışmaması durumuna göre yönlendiririz. Bu gibi durumlarda Thread sınıfının bize sağlamış olduğu isAlive() metodunu kullanabiliriz. Bu metot, bize Threadnesnesi halen runnable durumunda ise true, Thread nesnesi terminated (durdurulmuş) durumda ise, geriyefalse değer döndürecektir. Şimdi bu metotla ilgili bir örnek yapalım. 1 //threadKontrolOrnegi.java - 27.04.2014 2 3 public class threadKontrolOrnegi 4 { 5 public static void main(String[] args) throws 6 InterruptedException 7 { 8 Thread kanal1 = new threadOrnek("1. thread"); 9 Thread kanal2 = new threadOrnek("2. thread"); 10 // nesnelerimizi oluşturduk 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 kanal1.stop(); // ilk nesnemizi durdurduk System.out.println(kanal1.isAlive()); System.out.println(kanal2.isAlive()); // nesnelerimizin çalışıp çalışmadığının kontrolü } } class threadOrnek extends Thread { threadOrnek(String isim) { super(isim); start(); // nesnemizi başlattık } public void run() { System.out.println(Thread.currentThread().getName()); // nesnemizin ismini yazdırdık } } Ekran çıktısı: 1 2. thread 2 false 3 false Yukarıdaki örneğimizde öncelikle nesnelerimizi oluşturduk. Daha sonrasında ilk nesnemizi durdurduk. Bundan sonra ise nesnelerimizin çalışıp çalışmadığını ekrana yazdırdık. Ders 175 - MultiThreading MultiThreading, sözlük anlamıyla çok kanal anlamına gelmektedir. Çok kanallı programlama sayesinde iki işlemi paralel olarak zaman paylaşımlı yürütebiliriz. Thread'leri anlatırken işlemlerin thread'ler sayesinde zaman paylaşımlı olarak işlemciyi kullandıkları fakat işlemcinin işlemleri çok hızlı işlediğinden işlemlerin aynı anda yapıldığı izlenimine kapıldığımızı anlatmıştık. Bazı durumlarda birçok işlem için birçok thread yapısı kullanmamız gerekir. Bu thread yapıları birbirinden bağımsız veya ortak işlemleri içerebilirler. Ortak işlemleri işlediklerinde thread'lerin düzgün çalışabilmesi için thread'lerin senkronizasyonunun sağlanması gerekmektedir. Şimdi thread'lerin senkronizasyonu konusunu inceleyelim. THREAD'LERİN SENKRONİZASYONUNU SAĞLAMAK Thread nesneleriyle uygulama yazarken her zaman tek bir nesnenin ilgileneceği veriler üzerinde çalışmayız. Bazı durumlarda Thread nesnelerinin ortak veriler üzerinde işlem yapması gerekebilir. Böyle durumlarda veri bütünlüğünün sağlanması için Thread senkronizasyonu kullanılır. Olabilecek çakışmalar önlenir. Bu yöntem sayesinde bir Thread nesnesi, anahtar kelimeyle işaretlenmiş yerdeki işini bitirene kadar başka Thread nesnesi bu alanda işlem yapamaz. Thread senkronizasyonunu sağlamak için metodumuzu veya belirli bir kod bloğunu synchronized anahtar kelimesiyle işaretleriz. Şimdi bu olay ile ilgili bir örnek yapalım. 1 //threadSyncOrnegi.java - 27.04.2014 2 3 public class threadSyncOrnegi 4 { 5 public static void main(String[] args) throws 6 InterruptedException 7 { 8 Thread kanal1 = new threadOrnek(3, 6); 9 Thread kanal2 = new threadOrnek(2, 4); 10 // nesnelerimizi oluşturduk ve başlangıç değerlerini 11 verdik. 12 } 13 } 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class threadOrnek extends Thread { threadOrnek(int sayi, int sayi2) { // senkronize kod bloğu oluşturduk synchronized (this) { start(); // nesnemizi başlattık System.out.println(); for(int i = sayi ; i <= sayi2 ; i++) { System.out.print(i + " - "); } // ekrana sayıları yazdırdık } } } Ekran çıktısı: 1 3-4-5-62 2-3-4Yukarıdaki örneğimizde iki Thread nesnesi oluşturduk ve bu nesnelere değer aralıkları verdik. Bu değer aralıklarını yapıcı metodumuz, sayıları ekrana yazdırmak için kullandı. Buna göre ilk nesnemiz için metodumuz ekrana 36 arası sayıları; ikinci nesnemiz için 2-4 arası sayıları yazdıracaktı. Daha önceki threadörneklerimizde de gördüğümüz gibi Thread nesnelerinde belli bir sıra yoktu. Ekran çıktımıza baktığımızda ise ilk ve ikinci nesnemizin sırayla çalışmış olduğunu görüyoruz. Bunun sebebi; oluşturduğumuz senkronize kod bloğudur. İlk nesnemiz bu kod bloğu içerisine ilk olarak girer. Bu nesnemizin işi bitene kadar diğer Threadnesneleri bu bloğun içerisine giremezler. Bu örneğimizde senkronizasyonu, bir kod bloğu oluşturarak sağladık. Senkronizasyonu sağlamanın bir diğer yolu da oluşturacağımız metodu synchronized anahtar kelimesiyle işaretlemektir. Buna göre yukarıdaki örneğimizi bu yönteme göre düzenlersek: 1 //threadSyncOrnegi.java - 27.04.2014 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class threadSyncOrnegi2 { public static void main(String[] args) throws InterruptedException { Thread kanal1 = new threadOrnek2(3, 6); Thread kanal2 = new threadOrnek2(2, 4); // nesnelerimizi oluşturduk ve başlangıç değerlerini verdik. } } class threadOrnek2 extends Thread { int sayi, sayi2; private synchronized void threadSync() { System.out.println(); for(int i = sayi ; i <= sayi2 ; i++) { System.out.print(i + "-"); } // ekrana sayıları yazdırdık } threadOrnek2(int sayi, int sayi2) { start(); // nesnemizi başlattık this.sayi = sayi; this.sayi2 = sayi2; } public void run() { threadSync(); } } Ekran çıktısı: 1 2-3-3-4-5-6-4- Bu yazım şekli ile bir önceki yazım şekli ile aynıdır. Aralarında uygulamasal olarak bir fark yoktur. Ders 176 - Switch İçerisinde String İfadeleri Kıyaslama Kontrol Yapıları ve Döngüler derslerinde switch yapılarını anlatırken bundan bahsetmiştik. switch ile kontrol yaparken yalnızca Primitive tipleri switch içerisine ekleyebiliyorduk. Java 7 ile gelen özellikle artıkswitch içerisinde String ifadeleri de karşılaştırabiliyoruz. Örnek vererek açıklayalım. 1 //SwitchYapisi.java - 27.04.2014 2 3 import java.util.Scanner; 4 5 public class SwitchYapisi 6 { 7 public static void main(String[] args) throws 8 InterruptedException 9 { 10 Scanner s = new Scanner(System.in); 11 for (int i = 0 ; i < 3 ; i++) 12 { 13 System.out.println("İsminizi Girin: "); 14 String ad = s.next(); 15 switch (ad) 16 { 17 case "Okan": 18 case "okan": 19 System.out.println("Adınız Okan'dır"); 20 break; 21 case "Onur": 22 case "onur": 23 System.out.println("Adınız Onur'dur"); 24 break; 25 default: 26 System.out.println("Adınız hiçbirisi değil"); 27 } 28 } 29 } 30 } 31 Ekran çıktısı: 1 İsminizi Girin: 2 Okan 3 Adınız Okan'dır 4 İsminizi Girin: 5 onur 6 Adınız Onur'dur 7 İsminizi Girin: 8 göksu 9 Adınız hiçbirisi değil Örneğimizde döngü ile kullanıcıdan 3 defa isim girmesini istedik. Girilen bu String değerlerini switchyapısı ile karşılaştırdık. Girilen isme göre ekrana bilgilendirme mesajı yazdık. Java 6'da bu özellik yoktu. Yalnızca Primitive tipleri switch içerisinde kullanabiliyorduk. Bu gelen yenilikten önce karşılaştırmamızı şu şekilde yapıyorduk. 1 //SwitchYapisi2.java - 27.04.2014 2 3 import java.util.Scanner; 4 5 public class SwitchYapisi2 6 { 7 public static void main(String[] args) throws 8 InterruptedException 9 { 10 Scanner s = new Scanner(System.in); 11 for (int i = 0 ; i < 3 ; i++) 12 { 13 System.out.println("İsminizi Girin: "); 14 String ad = s.next(); 15 16 if(ad.equals("Okan")) 17 System.out.println("Adınız Okan'dır"); 18 else if(ad.equals("Onur")) 19 System.out.println("Adınız Onur'dur"); 20 else 21 System.out.println("Adınız hiçbirisi değil"); 22 } 23 } 24 } 25 Ders 177 - Sayılarda Altçizgi Kullanarak Sayıları Bölümleme Java7 ile gelen bir özellik ile int, float gibi sayısal veri tiplerimiz içerisinde altçizgi (_) kullanabiliyoruz. Bunu farklı amaçlar için yapabiliriz. Mesela; bir telefon numarasını ayırt etmek için kullanabiliriz. Örnek üzerinde gösterelim. //Java7.java - 27.04.2014 1 2 public class Java7 3 { 4 public static void main(String[] args) throws 5 InterruptedException 6 { 7 int tel = 444_67_444; 8 System.out.println(tel); 9 int ogrNo = 10_90_406_22; 10 System.out.println(ogrNo); 11 int sonuc = 56_4 + 12_8; 12 System.out.println(sonuc); 13 float sayi = 47_6; 14 System.out.println(sayi); 15 } 16 } 17 18 Ekran çıktısı: 1 44467444 2 109040622 3 692 4 476.0 Değişkenlerin değerlerine, okunabilirliği arttırmak için _ koyabiliyoruz. Tabi bu çizgiler, derleyici tarafındanokunmuyor. Örneğimizde toplama işlemi yaptık fakat altçizgi yokmuş gibi davrandı. Genelde telefon numarası gibi hane ve bölümlere ayırmak için kullanılır. Bu da Java 7 ile gelen hoş bir özelliktir. ! Istisnalar: Altçizgi, sayılarımızın başına ve sonuna gelemez. Böyle kullanılırsa derleyici hata üretir. Yalnızca sayılarımızın aralarına koyulabilir. Ders 178 - İkili Tabandaki Sayıları Değişkenlerde Tutma Java 7'den önce değişkenlerimizde sadece o tipteki verileri tutabiliyorduk. Örneğin; int tipindeki bir değişkende int tipindeki bir değeri, float tipindeki değişkenlerde float tipindeki bir değeri tutmamız gibi. Java 7 ile gelen yenilikle artık değişkenlerimizde binary sayıları da tutabiliyoruz. Örnek verirsek: //Java7.java - 27.04.2014 1 2 import java.util.Scanner; 3 4 public class Java7 5 { 6 public static void main(String[] args) throws 7 InterruptedException 8 { 9 int x = 0b11110; 10 float y = 0b01010; 11 byte z = 0b111111; 12 System.out.println(x); 13 System.out.println(y); 14 System.out.println(z); 15 } 16 } 17 18 Ekran çıktısı: 1 30 2 10.0 3 63 Örneğimizde değişkenlerimiz içerisinde binary tipteki sayıları da tutabiliyoruz. Bunun için binary sayımızın başına 0b (sıfır-b) getiriyoruz. Böylece binary sayımız, onluk tabana dönüştürülerek değişkenlerimizde tutulabiliyor. Java 7'den önce bu şekilde tanımlama yapamıyorduk. Peki, Java 7'den önce nasıl tanımlama yapıyorduk, onu inceleyelim. Binary sayımızın tanına vereceğimiz parametre ile hangi tabanda dönüştürme yapacağımızı söylüyoruz. Fakat Java 7 ile gelen yenilikle beraber artık bunu kısa yoldan yapıyoruz. //Ornek.java - 27.04.2014 1 2 public class Ornek 3 { 4 public static void main(String[] args) throws 5 InterruptedException 6 { 7 int a = Integer.parseInt("001100", 2); 8 System.out.println(a); 9 int b = Integer.parseInt("111", 8); 10 System.out.println(b); 11 int c = Integer.parseInt("1111", 10); 12 System.out.println(c); 13 int d = Integer.parseInt("10101010", 16); 14 System.out.println(d); 15 } 16 } 17 18 Ekran çıktısı: 1 12 2 73 3 1111 4 269488144 Yukarıda 4 adet binary sayı tanımladık. Bunları çift tırnak içerisinde yazıyoruz. Daha sonra yanına, hangi tabana dönüştürme yapacağımızı yazıyoruz. Bu işlemleri Integer.parseInt() metodu ile yapıyoruz. Bunun yerine Integer.valueOf() metodu ile de yapabilirdik. 3. satırda onluk tabanda yazılmasını istedik. Bu da doğrudan sayının kendisi oldu. Onluk taban sayının kendisi oluyor her zaman. Son satırda ise 16'lık tabanda 10101010 sayısını yazdırmak istedik ve sonuçları inceledik. Bu işlemleri Java 7 ile tek satırda yapabiliyoruz. Doğrudan binary sayımızın başına 0b getirerek sayımızı bir değişkene atayabiliyoruz. Son bir örnek olarak Java 7 ile gelen özelliği kullanarak bir dizi oluşturalım ve dizi elemanlarını ekrana yazdıralım. //JavaSE7.java - 27.04.2014 1 2 public class JavaSE7 3 { 4 public static void main(String[] args) throws 5 InterruptedException 6 { 7 int[] dizi = {0b1100, 0b01110, 0b100110}; 8 for (int i = 0 ; i < dizi.length ; i++) 9 { 10 System.out.println(dizi[i]); 11 } 12 } 13 } 14 15 Ekran çıktısı: 1 12 2 14 3 38 Dizimizin içerisinde binary elemanlar, otomatik olarak int tipine dönüştürülerek saklanmıştır. Ders 179 - Hata Yakalamada Yeni Catch Bloğu Sistemi Exception dersinde anlatmıştık; programımızda bir hata yakalandığında catch bloğu içerisinde kodlar işleniyordu. Eğer birden fazla hata olma ihtimali varsa, biz de o kadar catch bloğu oluşturuyorduk. Java 7 ile gelen yenilikle birden fazla catch bloğu oluşturmak yerine tek catch bloğu içerisinde bunları kontrol edebiliyoruz. Bir örnekle açıklayalım. 1 2 public class Java7 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 { public static void main(String[] args) throws InterruptedException { try { int x = 10; int y = 0; System.out.println(x / y); } catch (ArrayIndexOutOfBoundsException | ArithmeticException ex) { System.out.println(ex.toString()); } } } Ekran çıktısı: 1 java.lang.ArithmeticException: / by zero Yukarıdaki örnekte catch bloğu içerisinde, doğabilecek tüm hata tiplerini araya bitwise (|) koyarak tanımladık. Bu hata tiplerinden herhangi biri try içerisinde olursa, catch içerisindeki kodlar işlenecektir. Java 7'den önceki sürümlerde bunları tek tek kontrol ediyorduk. Aynı örneği bir de Java 7'den önce nasıl yaptığımıza bakalım. 1 //Java6.java - 27.04.2014 2 3 public class Java6 4 { 5 public static void main(String[] args) throws 6 InterruptedException 7 { 8 try 9 { 10 int x = 10; 11 int y = 0; 12 System.out.println(x / y); 13 } 14 catch (ArrayIndexOutOfBoundsException ex) 15 16 17 18 19 20 21 22 { System.out.println(ex.toString()); } catch (ArithmeticException ex) { System.out.println(ex.toString()); } } } Ders 180 - Hata Yakalamada Finally Bloğunun Alternatifi Hata yakalama işlemi yaparken genelde dosyalama ve veritabanı işlemlerinde kapatılması gereken dosyaları ve bağlantıları finally bloğu içerisinde kapatıyorduk. Java 7 ile gelen yenilikle beraber, artık tryiçerisinde de bunları yapabileceğiz. try bloğunu tanımlarken parantez içerisinde kapanmasını istediğimiz dosya ve bağlantıları tanımlıyoruz ve bunlar otomatik olarak kapatılıyor. Şimdi bir örnek verelim. 1 //FileReaderSinifiOrnek.java - 27.04.2014 2 3 import java.io.*; 4 5 public class FileReaderSinifiOrnek 6 { 7 public static void main(String[] args) throws 8 InterruptedException 9 { 10 File f = new File("C:\\elektroarge\\sehirler.txt"); 11 File ff = new File("C:\\elektroarge\\sehirler2.txt"); 12 char veriler[] = new char[(int) f.length()]; 13 14 try(FileWriter yazdir = new FileWriter(ff)) 15 { 16 FileReader f2 = new FileReader(f); 17 f2.read(veriler); 18 String okunan = new String(veriler); 19 yazdir.write(okunan); 20 } 21 catch (IOException e) 22 { 23 e.printStackTrace(); 24 } 25 } 26 } 27 Örneğimizde try ifadesinin yanına parantez içerisinde kapatılacak olan dosyamızı yazıyoruz. Bu, oluşturulan herhangi bir bağlantı nesnesi de olabilirdi. Java 7'den önceki sürümlerde ise bu şekilde yapamıyor, kapatılacak olan dosyaları finally bloğu içerisinde yazıyorduk. Artık bu bizim için otomatik olarak yapılıyor. Bunun sebebi, Java 7'de, java.lang paketinin içerisine AutoClosable arayüzünün eklenmiş olmasıdır. Peki, bu örneğimizi JavaSE 7'den önce nasıl yapıyorduk, onu gösterelim. 1 //FileReaderSinifiOrnek2.java - 27.04.2014 2 3 import java.io.*; 4 5 public class FileReaderSinifiOrnek2 6 { 7 public static void main(String[] args) throws 8 InterruptedException 9 { 10 File f = new File("C:\\elektroarge\\sehirler.txt"); 11 File ff = new File("C:\\elektroarge\\sehirler2.txt"); 12 char veriler[] = new char[(int) f.length()]; 13 14 try(FileWriter yazdir = new FileWriter(ff)) 15 { 16 FileReader f2 = new FileReader(f); 17 f2.read(veriler); 18 String okunan = new String(veriler); 19 yazdir.write(okunan); 20 } 21 catch (IOException e) 22 { 23 e.printStackTrace(); 24 } 25 finally 26 { 27 yazdir.close(); 28 } 29 } 30 31 } Ders 181 - Elmas Operatör İçerisindeki Tanım Zorunluluğu Generic tipleri tanımlamak için kullandığımız < > operatörüne elmas operatör diyoruz. Eskiden Java'da bir generic nesnesinin tanımını yaparken hem nesne tanımında hem de nesneyi oluştururken (instance alırken) elmas operatör ile tür belirtmek zorundaydık. Bu durum bazen nesne tanımı yaparken büyük karmaşalara sebep olabiliyordu. Java 7'de ise sadece nesne tanımını yaparken, generic nesnenin tipinin belirlemek yeterli olacaktır. Bir örnek içerisinde bu durumun Java 7'den önce ve sonra nasıl olduğunu gösterelim. //listOrnegi.java - 27.04.2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.ArrayList; import java.util.Map; public class listOrnegi { Map<Integer, ArrayList<String>> Java7denOnce = new Map<Integer, ArrayList<String>>(); // Java 7 den önce new Map <tip belirtmek zorunlu> (); Map<Integer, ArrayList<String>> Java7denSonra = new Map<>(); // Java 7 den sonra instance alırken tip belirtimi zorunluluğu kalktı } Ders 182 - Safevarags İle Uyarı ve Hata Giderimi Java'nın eski versiyonlarında varags() metodunu, parametre sayısı belli olmayan bir değişkenle çağırdığınızda, derleyici bu bölüm için uyarı mesajı vermekteydi. Şu örnek üzerinden konumuza devam edelim. //varags.java - 27.04.2014 1 2 import java.util.Map; 3 import java.util.HashMap; 4 5 public class varags 6 { 7 // çok parametreli(Varargs) metod 8 public static <Tip> void yazdir(Tip...elemanlar) 9 { 10 for(Tip t : elemanlar) 11 { 12 System.out.println(t.toString()); 13 } 14 } 15 16 public static void main(String[] args) 17 { 18 yazdir("Merhaba", "-", "JAVA SE", "-", "7"); 19 // bu kısımda derleyici hata veya uyarı vermeyecektir 20 21 Map<Integer, String> map1 = new HashMap<>(); 22 Map<Integer, String> map2 = new HashMap<>(); 23 // map türünden nesnelerimizi tanımladık. 24 25 map1.put(1, "Bir"); 26 map1.put(2, "İki"); 27 map2.put(3, "Üç"); 28 map2.put(4, "Dört"); 29 // map nesnelerimize değerleri ekledik 30 31 yazdir(map1, map2); 32 /* bu kısımda derleyici bize bir uyarı mesajı verecektir. bu 33 uyarı: 34 * WARNING: Type safety: A generic array of Map<Integer, 35 String> 36 * is created for a varags parameter şeklinde olacaktır */ 37 } 38 } 39 Ekran çıktısı: 1 Merhaba 2 3 JAVA SE 4 5 7 6 {1=Bir, 2=İki} 7 {3=Üç, 4=Dört} Örnekte derleyici, yazdir() metodunun ikinci kullanımında bu metodun bir dizisini oluşturmaya çalışıyor. Derleme anında bu parametrelerin tipleri silinerek derleniyor. Bu da tip uyuşmazlığı gibi sorunlara neden oluyor. Örnekteki uyarı, bu hatanın alınabileceğini belirtmek için çıkıyor. Bu gibi uyarıları almamamız için metodun başına @SafeVarargs annotation tipini kullanabiliriz. Bu annotation'u kullanmak, alacağımız uyarıları bastıracaktır. Yani bu annotation'u kullandığımızda örneğimiz aşağıdaki gibi olacaktır ve uyarı mesajı bastırılacaktır. 1 //varags2.java - 27.04.2014 2 3 import java.util.Map; 4 import java.util.HashMap; 5 6 public class varags2 7 { 8 @SafeVarargs 9 // çok parametreli(Varargs) metod 10 public static <Tip> void yazdir(Tip...elemanlar) 11 { 12 for(Tip t : elemanlar) 13 { 14 System.out.println(t.toString()); 15 } 16 } 17 18 public static void main(String[] args) 19 { 20 yazdir("Merhaba", "-", "JAVA SE", "-", "7"); 21 // bu kısımda derleyici hata veya uyarı 22 vermeyecektir 23 24 25 26 27 28 29 30 31 32 33 34 35 Map<Integer, String> map1 = new HashMap<>(); Map<Integer, String> map2 = new HashMap<>(); // map türünden nesnelerimizi tanımladık. map1.put(1, "Bir"); map1.put(2, "İki"); map2.put(3, "Üç"); map2.put(4, "Dört"); // map nesnelerimize değerleri ekledik yazdir(map1, map2); // uyarı mesajı almıyoruz } }
Benzer belgeler
java programlamaya giriş
Burada kırmızı çizgilerle belirtilmiş olan programlar kurulmalıdır. Önce JDK daha
sonra NetBeans IDE kurulur.