spring framework ile java tabanlı datasource konfigurasyonu

Merhaba arkadaşlar ,
bu yazdıma Spring Framework DataSource konfigurasyonunu XML kullanmadan sadece Java tabanlı olarak oluşturacağız.(Bu örnekte MySQL kullanılacaktır.)

Öncelikle .properties dosyamızı oluşturuyoruz.


driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/database-name
username = root
password = 


Ardından sınıfımızı oluşturuyoruz.


@Configuration
@PropertySource("classpath:/mysql.properties")
@ComponentScan(basePackages = "io.github.alicankustemur.blogproject")
public class BeanConfiguration
{

 @Autowired
 public Environment  environment;

 @Bean
 public SingleConnectionDataSource createDriverManagerDataSourceBean()
 {
  SingleConnectionDataSource driverManager = new SingleConnectionDataSource();
  driverManager.setDriverClassName(environment.getProperty("driverClassName"));
  driverManager.setUrl(environment.getProperty("url"));
  driverManager.setUsername(environment.getProperty("username"));
  driverManager.setPassword(environment.getProperty("password"));
  return driverManager;
 }

}
Bu sınıfın bir konfigurasyon işlemi yaptığını belirtmek için @Configuration anotasyonunu sınıfın başına ekliyoruz.

@PropertySource anotasyonu içerisinde ki "classpath:/mysql.properties" değeri mysql.properties dosyasını classpath içerisinde arayıp Environment'a enjekte etmektedir.
Daha sonra getProperty()  methodu ile birlikte properties dosyasında ki değişken değerlerine erişiyoruz.Bu değerleri de oluşturduğumuz SingleConnectionDataSource nesnesine set ediyoruz.

Burada SingleConnectionDataSource kullanmamın sebebi bu sınıf ile yapılan DataSource tanımlamaları sadece bir Connection nesnesinin kullanımına izin verir.Uygulama her zaman aynı Connection nesnesini kullanarak çalışmayı sürdürür.DriverManagerDataSource kullanılarak oluşturulan bir DataSource tanımlaması her veri tabanı bağlantı isteği için yeni bir Connection nesnesi oluşturacaktır.

@ComponentScan anotasyonu ile Spring'e gerekli sınıfları classpath içerisinde araması gerektiğini belirtiyoruz.

Burada createDriverManagerDataSourceBean() methodu üzerinde ki @Bean anotasyonu methodu bean haline getirip DAO işlemleri için Repository sınıfları içerisinde DataSource tanımlamalarına @Autowired anotasyonu ile otomatik olarak enjekte edeceğiz.
Aşağıda bununla ilgili kısa bir örnek verilmiştir.


@Component
public class JdbcRepositoryImpl implements Repository
{
 
 @Autowired
 private DataSource dataSource;
 
 @Override
 public void save(User user)
 {
  PreparedStatement preparedStatement = null;

  try
  {
   Connection connection = dataSource.getConnection();
   preparedStatement = connection
     .prepareStatement("INSERT INTO user (id,name) VALUES (?,?)");
   preparedStatement.setLong(1, user.getId());
   preparedStatement.setString(2, user.getName());
   preparedStatement.executeUpdate();
   preparedStatement.close();

  }
  catch (Exception e)
  {
  }

 }

 
}
Oluşturduğumuz konfigurasyon sınıfını ApplicationContext üzerinden çağırabilmek için AnnotationConfigApplicationContext nesnesi ile oluşturup constructor değerine ilgili konfigurasyon sınıfını belirtmek gerekmektedir.

Aşağıda bununla ilgili kısa bir örnek verilmiştir.


public class Main
{

 public static void main(String[] args) throws SQLException
 {

  ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfiguration.class);
  Repository repository = applicationContext.getBean(Repository.class);
  repository.save(1,"Ali Can Kuştemur");
 }

}

Giriş Sayfası ve CRUD Paneli (Servlet JSP / PHP)

Bu yazımda yapmış olduğum ufak bir projeyi paylaşıyorum.
Projeyi kaynak belirtmeden herhangi bir yerde kullanabilirsiniz.
Bir giriş sayfamız var,eğer giriş başarılı bir şekilde gerçekleşirse yine giriş sayfası için anlık olarak kullanıcı/yetkili oluşurup , listeleyip, güncelleyip , silebileceğimiz bir sayfa geliyor.
Veritabanı sunucusu olarak MySQL'i kullandım.Bazı işlemler için çok kısa JavaScript kullanılmıştır.

Servlet ile oluşturulan versiyonu JDBC , JSP sayfaları ise JSTL kullanılarak  MVC ve DAO Tasarım Şablonları uygulanarak Maven Project olarak Eclipse'de hazırlanmıştır.

PHP versiyonunda herhangi bir framework kullanılmamıştır.

Servlet  JSP versiyonu GitHub linki :
https://github.com/kustemura/LoginCrudServletJSPExample

Servlet JSP versiyonu Google Drive linki :
https://drive.google.com/file/d/0BytHrEwKQAMjOVJFMERZRThuRTg/view

PHP versiyonu GitHub linki :
https://github.com/kustemura/LoginCrudPHPExample

PHP versiyonu Google Drive linki :
https://drive.google.com/open?id=0BytHrEwKQAMjT3ZJRWhHTV80c1E

Aşağıdaki resimler projenin 2 versiyonundaki ekran görüntüleri bulunmaktadır.

Giriş Sayfası

 
    giriş sayfasında oluşan durumlar için bir validasyon sistemine sahip ve üst tarafta uyarılar oluşmakta .Kullanıcı adı veya şifre boş geçilirse ,


sistemdeki tüm kullanıcıları kaldırıp çıkış yaptıktan sonra tekrar giriş yapmayı denersek ,


 hatalı girilirse ,


eğer giriş yapan kişi yetkili değil ise ,  

 

kullanıcı adı ve şifre doğru girildikten sonra giren kişi yetkili ise CRUD paneli ve kullanıcı listesi sayfası ekranı gelmektedir.



Yapılan diğer işlemlerde oluşan ekran görüntüleri aşağıdadır.
         
 aynı isme sahip eklemelere izin verilmez.


Güncelleme yapılacağı zaman sadece kullanıcı adı değiştirilip şifre boş geçilirse aynı şifre geçerliliğini devam ettirmektedir.Güncellemeden önce



güncellendikten sonra ,


kullanıcı adı ve şifre güncellendiğinde , 

silinmek istendiğinde



Java - Jenerikler ( Generics )


Merhaba , bu yazımda Jenerikler(Generics)'den bahsedeceğim. Jenerikler Java'ya JDK 5 ile eklenmiştir.
Jeneriklerin kullanıldığı kaynak kodlar javac derleyicisinin daha önceki versiyonlarında derlenemez.
Jenerikler, Java'yı iki önemli bakımdan değiştirmiştir.Birincisi , bu yeni özellik dile yeni bir sözdizimi öğesi eklemiştir.İkincisi ise , çekirdek API'daki birçok sınıf ve method'da değişikliklere neden olmuştur.Java kodlarının yazılma biçimini temelden değiştirmiştir.
Temel olarak jenerikler terimi , parametreli tipler anlamına gelir.Bu yapı önemlidir , üzerinde çalışacakları veri tipinin bir parametre olarak belirtildiği sınıflar , arabirimler ve methodlar oluşturabilmenizi sağlar.
Jenerikler'den önce Object tipindeki referanslar yoluyla yazılan kaynak kodları hala günümüzde kullanıma devam etmektedir.Object tipindeki sorun tip güvenliği olmamasıydı.Jenerikler bu soruna çözüm olarak tasarlanmıştır.Ayrıca süreci hızlandırır artık Object ve üzerinde çalışan tip arasında dönüşüm yapılmasına gerek duyulmaz.Jeneriklerde tüm tip atamaları otomatik ve kapalı olarak yapılır.Bu şekilde Jenerikler kodunuzu tekrar kullanabilme yeteneğinizi arttırır , bunu güvenle ve kolaylıkla yapabilmenizi sağlar.Bir örnek üzerinden inceleyelim.

package com.blogger_project;
class NonGen {
 Object type;

 NonGen(final Object type) {
  this.type = type;
 }

 Object getObject() {
  return type;
 }

 void showType() {
  System.out.println("Object type'ın tipi :" + type.getClass().getName());
 }

}

class NonGenDemo {
 public static void main(final String args[]) {
  final NonGen intType = new NonGen(35);
  final int v = (Integer) intType.getObject();
  intType.showType();
  System.out.println("Değeri :" + v);

  System.out.println();

  final NonGen strType = new NonGen("Hello World!");
  final String str = (String) strType.getObject();
  strType.showType();
  System.out.println("Değeri : " + str);

  System.out.println();

  final NonGen doubleType = new NonGen(12.5);
  final Double d = (Double) doubleType.getObject();
  doubleType.showType();
  System.out.println("Değeri : " + d);

 }
}
Programın Çıktısı : 
Object type'ın tipi :java.lang.Integer
Değeri :35

Object type'ın tipi :java.lang.String
Değeri : Hello World!

Object type'ın tipi :java.lang.Double
Değeri : 12.5


Yukarıdaki programda Object tanımlamaları olduğu için NonGen'in jenerik versiyon gibi her tipte nesneyi depolayabilmesini sağlar.Ancak aynı zamanda java derleyicisinin gerçekte NonGen içerisinde depolanan verinin tipi hakkında gerçek bir bilgiye sahip olmasını önler.Bu , iki nedenle kötüdür.Birincisi depolanan veriyi elde etmek için açık tip atamaları gereklidir.İkincisi ise çalışma zamanında çeşitli türlerde tip uyuşmazlığı hataları oluşabilir.

int v = (Integer) intType.getObject();

Burada , getObject() methodunun dönüş tipi Object olduğundan , değerin kutudan çıkartılıp v değişkeninde depolanmasını sağlamak için Integer'a tip ataması gereklidir.Tip atamasını kaldırırsanız program derlenmemez.

intType = strType;
v = (Integer) intType.getObject();

Burada bir çalışma zamanı hatası oluşur.Çünkü intType'a strType atanır.Ancak strType bir tamsayı değil , karakter katarı içeren bir nesneye referans yapar.Bu atama sözdizimsel açıdan geçerli değildir.Çünkü tüm NonGen referansları aynıdır ve herhangi bir NonGen referansı bir başka NonGen nesnesine referans yapabilir.Ancak bu mantıksal olarak yanlıştır.getObject() methodunun döüş tipi tip atamasıyla integer yapılır ve sonra bu değeri v değişkenine atama yapılır.Sorun artık intType'in bir Integer değil bir String içeren nesneye referans yapmasıdır.İşte burada Jenerikler kullanılmadan java derleyicisinin bunu bilmesine imkan yoktur ve bir çalışma zamanı hatası ortaya çıkmıştır.Jeneriklerde aynı işlem denenseydi , derleyici sorunu yakalayacak ve bir hata bildirecekti.Bu da bir çalışma zamanı hatasını önleyecekti.Jenerikler sayesinde oluşan çalışma zamanı hataları , artık derlenme zamanı hatası haline gelmiştir.

Bir programcının en çok korktuğu şeydir bu! Eğer iyi bir programcı olmak istiyorsak , kullanacağımız herşey tüm kurallara uygun olmalıdır.İyi bir programcı çalışma zamanı hatalarına izin vermemelidir.Bir işi yapan her program doğru sonuçlar verebilir fakat doğru kullanıma sahip değildir  :)

Şimdi yukarıda ki programın Jenerik versiyonunu oluşturalım.

package com.blogger_project;

class Gen<T> {
 T type;

 Gen(final T type) {
  this.type = type;
 }

 T getType() {
  return type;
 }

 void showType() {
  System.out.println("Jenerik type'ın tipi : "+ type.getClass().getName());
 }

}

class GenDemo {
 public static void main(final String args[]) {
  final Gen<Integer> intType = new Gen<Integer>(35);
  intType.showType();
  final int v = intType.getType();
  System.out.println("Değeri :" + v);

  System.out.println();

  final Gen<String> strType = new Gen<String>("Hello World!");
  strType.showType();
  final String str = strType.getType();
  System.out.println("Değeri : " + str);

  System.out.println();

  final Gen<Double> doubleType = new Gen<Double>(12.5);
  doubleType.showType();
  final Double d = doubleType.getType();
  System.out.println("Değeri : " + d);
 }
}
Programın Çıktısı :
Jenerik type'ın tipi : java.lang.Integer
Değeri :35

Jenerik type'ın tipi : java.lang.String
Değeri : Hello World!

Jenerik type'ın tipi : java.lang.Double
Değeri : 12.5

class Gen<T> { ..

Bu kullanıma dikkat edelim.
T , bir tip parametresinin adıdır.Bu ad nesne oluşturulurken Gen sınıfına aktarılacak olan gerçek tip için bir yer tutucudur.Bu yüzden type , T'ye akratılan tipte bir nesne olucaktır.Örnekte olduğu gibi T'ye aktarılan tip Integer,String ve Double tipleri , type'ı o tipe ait bir nesne yapıyor.Java derleyicisinin gerçekte Gen'in ya da bir başka jenerik sınıfın değişik versiyonlarının oluşturulmadığını belirtmemiz gerekir.Derleyici , tüm jenerik tip bilgilerini ortadan kaldırır.Bu işleme silme( erasure ) denir.

Gen<Integer> intType = new Gen<Integer>(35);

Bu satır Gen constructoru çağrıldığında , Integer tip argümanının da belirtildiğine dikkat edelim.Bu gereklidir , çünkü referans atanacağı nesnenin (intType) tipi Gen < Integer >'dır.Bu yüzden new tarafından döndürülen referansda aynı tipe sahip olmalıdır.Değilse bir derleme zamanı hatası gerçekleşir.

Gen<Integer> intType;
intType = new Gen<Double>(35);

Yukarıdaki kod buna bir örnektir.Nesne Gen tipinde olduğundan Gen tipinde bir nesneye başvuramaz.Tip kontrolü Jeneriklerin en başlıca avantajlarından biridir.

Jenerikler sadece nesnelerle çalışır.Jenerik bir tipte örnek deklare ederken , tip parametresine aktarılan tip sınıf tipi olmalıdır.int yada char gibi bir primitif tip kullanılamaz.


Gen<int> intType = new Gen<int>(35);
Örnek olarak Gen sınıfında , T'ye herhangi bir sınıf tipi aktarabilirsiniz,ancak tip parametresine bir primitif tip aktaramazsınız.


Jenerikler iki tip parametreli olarakda kullanılabilir.Aşağıdaki programı inceleyelim.

package com.blogger_project;

class TwoGen<T, Y> {
 T type;
 Y type2;

 TwoGen(final T type, final Y type2) {
  this.type = type;
  this.type2 = type2;
 }

 T getType() {
  return type;
 }

 Y getType2() {
  return type2;
 }

 void showType() {
  System.out.println("Jenerik type'ın tipi : "
    + type.getClass().getName());
  System.out.println("Jenerik type2'ın tipi : "
    + type2.getClass().getName());
 }

}

class GenDemo {
 public static void main(final String args[]) {
  final TwoGen<Integer, String> twoType = new TwoGen<Integer, String>(35,
    "Hello World!");
  twoType.showType();
  final int v = twoType.getType();
  System.out.println("Değeri (int):" + v);

  final String str = twoType.getType2();
  System.out.println("Değeri (String):" + str);

 }
}
Programın Çıktısı : 
Jenerik type'ın tipi : java.lang.Integer
Jenerik type2'ın tipi : java.lang.String
Değeri (int):35
Değeri (String):Hello World!

Java - instanceof Anahtar Sözcüğü


Bu yazımda instanceof anahtar sözcüğünün ne işe yaradığını ve kullanımını anlatacağım.
Java'da geçersiz tip dönüşümü bir çalışma hatasına neden olur.Geçersiz tip dönüşümlerinin çoğu çalışma zamanında yakalanabilir.Ancak sınıf hiyerarşisindeki tip dönüşümleri ancak çalışma zamanında algılabilen geçersiz tip dönüşümleri üretebilirler.Bu bir çalışma zamanı hatası fırlatır.Java bu durumlara çözüm bulabilmek için instanceof adında bir çalışma zamanı operatoru tanımlar.
 Kullanım şekli aşağıda olduğu gibidir.

< Örnek Referans > instanceof < Sınıf Tipi>
"Örnek Referans" belirtilen sınıf tipinde ise veya belirtilen tipe dönüştürebiliyorsa true değerini döndürür. Bir örnek ile inceleyelim.
package com.blogger_project;

/**
 * @Author    : Ali Can Kuştemur
 * @Date      : 24 May 2015
 * @File_Name : InstanceOf.java
 * @Blog      : http://kustemura.blogspot.com.tr 
 */
class Ford {
 int weight, model;
}

class Volkswagen {
 int weight, model;
}

class GT extends Ford {
 int speed;
}

class Mustang extends Ford {
 int speed;

}

class InstanceOf {
 public static void main(final String args[]) {
  final Ford car = new Ford();
  final Volkswagen car1 = new Volkswagen();
  final GT car2 = new GT();
  final Mustang car3 = new Mustang();

  if (car instanceof Ford) {
   System.out.println("car örnek referansı ,"
     + " Ford sınıf tipinin bir örneğidir.");
  }
  if (car1 instanceof Volkswagen) {
   System.out.println("car1 örnek referansı ,"
     + " Volkswagen sınıf tipinin bir örneğidir.");
  }
  if (car2 instanceof GT) {
   System.out.println("car2 örnek referansı ,"
     + " GT sınıf tipinin bir örneğidir.");
  }
  if (car3 instanceof Mustang) {
   System.out.println("car3 örnek referansı ,"
     + " Mustang sınıf tipinin bir örneğidir.");
  }
  if (car instanceof GT) {
   System.out.println("car örnek referansı ,"
     + " GT sınıf tipine dönüştürülebilir.");
  }

  System.out.println();

  Ford newCar;

  newCar = car3;

  if (newCar instanceof Mustang) {
   System.out.println("newCar örnek referansı ,"
     + " Mustang sınıf tipinin bir örneğidir.");
  }

  newCar = car2;

  if (newCar instanceof GT) {
   System.out.println("newCar örnek referansı ,"
     + " GT sınıf tipinin bir örneğidir.");
  }

  if (newCar instanceof Mustang) {
   System.out.println("newCar örnek referansı ,"
     + " Mustang sınıf tipine dönüştürülebilir.");
  } else {
   System.out.println("newCar örnek referansı ,"
     + " Mustang sınıf tipine dönüştürülemez!");
  }

  if (newCar instanceof Ford) {
   System.out.println("newCar örnek referansı ,"
     + " Ford sınıf tipine dönüştürülebilir.");
  }

 }
}
Programın Çıktısı:
car örnek değişkeni , Ford sınıf tipinin bir örneğidir.
car1 örnek referansı , Volkswagen sınıf tipinin bir örneğidir.
car2 örnek referansı , GT sınıf tipinin bir örneğidir.
car3 örnek referansı , Mustang sınıf tipinin bir örneğidir.

newCar örnek referansı , Mustang sınıf tipinin bir örneğidir.
newCar örnek referansı , GT sınıf tipinin bir örneğidir.
newCar örnek referansı , Mustang sınıf tipine dönüştürülemez!
newCar örnek referansı , Ford sınıf tipine dönüştürülebilir.

Java - Dosya Okuma ve Dosya Yazma #2


Bir önceki yazıma buradan ulaşabilirsiniz.

Bu yazımda daha gelişmiş JDK 7 sürümü ile gelen bir özellik try-with resources ile birlikte Dosya Okuma ve Dosya Yazma işlemlerini göstereceğim.

JDK 7'den önce dosya kapatma işlemi halen geçerli ve faydalı olmasına rağmen , yeni özellik ile kapatma işlemini otomatik hale getirerek daha kullanışlı bir yapı oluşturur.

Artık bu yeni özellik ile close() methodunu çağırmamıza gerek yoktur.Bir başka deyişle dosyayı kapatmayı unutmamıza imkan yoktur.
Hemen örnek üzerinde bunu görelim.


package com.blogger_project;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

class FileRead {
 public static void main(final String args[]) {
  int i;

  try (FileInputStream input = new FileInputStream("C:\\first.txt");
    FileOutputStream output = new FileOutputStream("C:\\second.txt")) {

   do {
    i = input.read();
    if (i != -1) {
     output.write(i);
    }

   } while (i != -1);
  } catch (final IOException e) {
   e.printStackTrace();
  }
 }
}
Bu program ile " Dosya Yazma " bölümündeki program aynı işlemi yapar.Daha kısa ve sade bir kullanıma sahiptir.Ayrıca daha kullanışlıdır.
try (FileInputStream input = new FileInputStream("C:\\first.txt");
    FileOutputStream output = new FileOutputStream("C:\\second.txt")) {
Buradaki kullanıma dikkat edelim.try bloğu sonlandığında otomatik olarak input ve output dosya işlemleri kapatılacaktır.

Java - Dosya Okuma ve Dosya Yazma


Merhaba bu yazımda Java'da Dosya İşlemleri ile ilgili en çok kullanılan 2 yapıyı anlatacağım.

FileInputStream(String fileName) throws FileNotFoundException
FileOutputStream(String fileName) throws FileNotFoundException
Buradaki fileName açmak istediğiniz dosyanın ismini belirtir.Eğer dosya bulunamaz ise IOException sınıfının bir alt sınıfı olan FileNotFoundException'ı fırlatır.

Yapılan dosya işlemleri tamamlandığında close() methodu ile kapatılmalıdır.Aksi takdirde sistem kaynakları serbest kalır ve burada bir güvenlik açığı meydana gelmiş olur.

1 - Dosya Okuma

Örnek üzerinden anlatayım :

package com.blogger_project;

import java.io.FileInputStream;
import java.io.IOException;

class FileRead {
 public static void main(final String args[]) {
  int i;
  String str = "";
  FileInputStream input = null;

  try {
   input = new FileInputStream("C:\\first.txt");

   do {
    i = input.read();
    if (i != -1) {
     str += (char) i;
    }
   } while (i != -1);
  } catch (final IOException e) {
   e.printStackTrace();
  }

  try {
   input.close();
  } catch (final IOException e) {
   e.printStackTrace();
  }

  System.out.println(str);
 }
}
Programın Çıktısı : 
Hello World !
Yukarıda ki programda input değişkeni FileInputStream sınıfını referans etmektedir.try bloğunun içerisinde nesnemizi oluşturuyoruz ve bir parametreli Constructor'un aldığı argüman değeri dosyanın ismidir.(Dosya ismi içerisindeki argümanın iki adet "\" ifadesi almasının sebebi derleyicinin "\" karakterinden sonraki karakteri dikkate almadan derleme işlemine devam etmesini sağladık.Yani "C:\\first.txt" bu değerin çıktısı "C:\first.txt" bu olucaktır.Onu başka bir yazımda anlatacağım.[Escape Characters]) . do-while içerisinde ki i değişkenine atadığımız input değişkeni FileInputStream sınıfının read() methodunu çağırır ve bu method bir tamsayı değer döndürür.Eğer dosya okuma işleminin sonuna yaklaşırsa döndürdürüğü değer -1 olur.i değişkenini char tipinde cast ettikten sonra str'ye ekliyoruz.Ben örnek olarak first.txt içerisine "Hello World !" yazıp kaydettim.Okuma işlemini yaptıktan sonra yukarıda belirttiğim gibi dosyayı kapatmamız gerekiyor.Bunuda bir try-catch bloğunda close() methodunu çağırarak yapıyoruz.Yapılan bu işlemlerin hepsi birer IOException fırlatabilir.

 2 - Dosya Yazma

Buradaki program " first.txt " içerisindeki verileri " second.txt " 'ye aktarır.

package com.blogger_project;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

class FileRead {
 public static void main(final String args[]) {
  int i;
  FileInputStream input = null;
  FileOutputStream output = null;

  try {
   input = new FileInputStream("C:\\first.txt");
   output = new FileOutputStream("C:\\second.txt");

   do {
    i = input.read();
    if (i != -1) {
     output.write(i);
    }
   } while (i != -1);
  } catch (final IOException e) {
   e.printStackTrace();
  } finally {
   try {
    if (input != null) {
     input.close();
    }

   } catch (final IOException e) {
    e.printStackTrace();
   }
   try {
    if (output != null) {
     output.close();
    }
   } catch (final IOException e2) {
    e2.printStackTrace();
   }
  }

 }
}
Burada "Dosya Okuma" işlemlerinde yapmış olduğumuz str  değişkenine eklediğimiz değerleri output nesnesine FileOutputStream sınıfının write() methodunu kullanarak aktarıyoruz.Bir önceki işlemlerden farklı olarak try-catch bloğunda bir finally bloğu yer alıyor.Burası programımıza bir esneklik sağlıyor.finally bloğu her zaman try-catch bloklarından sonra kesinlikle çalıştırılır.Dosya kapatma işlemlerini burdan yönetmek hem daha önceden oluşan sorunlardan ötürü kapanmayan dosyaları kapatır hemde kodu kısaltır.

Java - Enums ( Numaralandırmalar )


Bu özellik Java'ya 1.5 sürümüyle beraber eklenmiştir.
Enum adlandırılmış sabitlerden oluşan bir listedir.Örneğin günler gibi.
Java'da numaralandırmalar bir sınıf tipini tanımlarlar.
Bir örnek ile ele alalım.

package com.blogger_project;

/**
 * @Author    : Ali Can Kuştemur
 * @Date      : 22 May 2015
 * @File_Name : EnumDemo.java
 * @Blog      : http://kustemura.blogspot.com.tr 
 */
public class EnumDemo {

 public enum Day {
  PAZARTESI, SALI, CARSAMBA, PERSEMBE, CUMA, CUMARTESİ, PAZAR
 }

 public static void main(final String[] args) {
  Day theDay = Day.PAZARTESI;
  printToday(theDay);

  theDay = Day.PERSEMBE;
  printToday(theDay);

  theDay = Day.valueOf("PERSEMBE");
  printToday(theDay);

  System.out.println();

  for (final Day allDay : Day.values()) {
   System.out.println(allDay);
  }

 }

 public static void printToday(final Day day) {
  if (day == Day.PAZARTESI) {
   System.out.println("Pazartesi gününe bir \"Merhaba\" de bakalım. ");
  } else {
   System.out.println("Bugün şanslı günündesin.");
  }
 }

}
Programın Çıktısı : 
Pazartesi gününe bir "Merhaba" de bakalım. 
Bugün şanslı günündesin.
Bugün şanslı günündesin.

PAZARTESI
SALI
CARSAMBA
PERSEMBE
CUMA
CUMARTESİ
PAZAR
Burada PAZARTESI,SALI ve diğer tanımlayıcılar , numaralandırma sabitleri olarak adlandırılırlar.Her biri kapalı olarak Day'in public,static ve final birer üyesi olarak deklare edilmiştir.Bu sabitlerin tipleri deklare edildikleri tiplerdir yani burada Day tipinde.Enum'lar bir sınıf tipi olmalarına rağmen new anahtar sözcüğü ile bir enum örneği oluşturulamaz;ama bir numaralandırma değişkenini ilkel değişken tiplerinde olduğu gibi aynı şekilde deklare edebilirsiniz. Örneğimizde theDay adında bir Day örneği oluşturduk ve bu örneğe PAZARTESI sabitini atadık.)enumlar if veya switch yapılarında kullanılabilirler.)Ardından printToday() methoduna argüman olarak geçtiğimiz theDay değişkeni ile dönen değere göre yazdırma işlemlerimizi yapıyoruz. valueOf() methoduna aktarılan karakter katarına karşılık gelen sabiti döndürür. "Bugün şanslı günündesin." çıktısının iki adet olduğuna dikkat edin.Bunun sebebi valueOf() methoduna argüman olarak yazdığımız "PERSEMBE" karakter katarının printToday() methodunda else bloğuna düşmesidir. values() methodu çağrıldı enum tipinde bir diziyi döndürür.Burada for-each içerisindeki allDay değişkenine Day enum'unun sabitleri birer birer aktarılır ve ekrana yazdırılır.

Java Numaralandırmaları Sınıf Tipleridir
enum'larda new kullanarak bir enum örneği oluşturamasakta , bunun dışında diğer sınıflar ile aynı yeteneklere sahiptirler.Örneğin numaralandırmalara yapılandırıcı verebilir ,örnek değişken ve methodlar ekleyebilir hatta arabirimler uygulayabilirsiniz.
Bir örnekle inceleyelim.

package com.blogger_project;

/**
 * @Author : Ali Can Kuştemur
 * @Date : 22 May 2015
 * @File_Name : EnumDemo.java
 * @Blog : http://kustemura.blogspot.com.tr
 */
public class EnumDemo {
 enum Fruit {
  Apple(5), Banana(7), Orange(2), Peach(4), Melon(6), WaterMelon;
  private int price;

  Fruit() {
   price = -1;
  }

  Fruit(final int price) {
   setPrice(price);
  }

  void setPrice(final int price) {
   this.price = price;
  }

  int getPrice() {
   return price;
  }

 }

 public static void main(final String args[]) {
  Fruit myFruit = Fruit.Orange;
  System.out.println(myFruit + " : " + myFruit.getPrice() + " $");

  myFruit = Fruit.Peach;
  System.out.println(myFruit + " : " + myFruit.getPrice() + " $");

  System.out.println("Fruit/Melon :" + Fruit.Melon.getPrice() + " $");

  System.out.println();

  System.out.println("Fruit Numaralandırma Sabitleri Listesi ");
  for (final Fruit fruit : Fruit.values()) {
   System.out.println(fruit + " : " + fruit.getPrice() + " $");
  }

 }
}
Orange : 2 $
Peach : 4 $
Fruit/Melon :6 $

Fruit Numaralandırma Sabitleri Listesi 
Apple : 5 $
Banana : 7 $
Orange : 2 $
Peach : 4 $
Melon : 6 $
WaterMelon : -1 $
Constructor değerlerini sabitlere tanımladıktan sonra getPrice() methodu ile Fruit numaralandırıcı sabitlerinin price değerlerine ulaşıp yazdırdık.Bir enum örnek değişkeni oluşturup new ifadesi kullanmadığımıza dikkat edelim. Constructor'u boş geçilen WaterMelon sabiti ise yine sınıflarda olduğu gibi aşırı yüklenebilir.Constructor argümanı boş geçilen sabit'in -1 değer aldığını görüyoruz.Buradaki önemli parçalar :

Fruit myFruit = Fruit.Orange;
myFruit.getPrice(); 
Fruit.Melon.getPrice();
Burada getPrice() methodunun 2 farklı çağrılma şeklini gördük. Numaralandırlar ile ilgili önemli kısıtlamalar: 1 - Bir numaralandırma bir başka sınıfı kalıtımla devralamaz. 2 - Bir enum bir üst sınıf olamaz. ( enum'lar genişletilemezler.) 3 - Her bir numaralandırma sabiti tanımlandığı sınıfın tipinde bir nesne olmalıdır.


package com.blogger_project;

/**
 * @Author : Ali Can Kuştemur
 * @Date : 23 May 2015
 * @File_Name : EnumDemo2.java
 * @Blog : http://kustemura.blogspot.com.tr
 */
public class EnumDemo2 {
 enum Fruit {
  Apple, Banana, Orange, Peach, Melon, WaterMelon;
 }

 public static void main(final String args[]) {

  final Fruit fr1, fr2, fr3;

  for (final Fruit fruit : Fruit.values()) {
   System.out.println(fruit + " : " + fruit.ordinal());
  }

  System.out.println();

  fr1 = Fruit.Apple;
  fr2 = Fruit.Banana;
  fr3 = Fruit.Apple;

  if (fr1.compareTo(fr2) < 0) {
   System.out.println(fr1 + " " + fr2 + "'dan önce gelir.");
  }

  if (fr1.compareTo(fr2) > 0) {
   System.out.println(fr2 + " " + fr1 + "'dan önce gelir.");
  }

  if (fr1.compareTo(fr3) == 0) {
   System.out.println(fr1 + " eşittir " + fr3 + "'a");
  }

  if (fr1.equals(fr3)) {
   System.out.println(fr1 + " eşittir " + fr3 + "'a");
  }

 }
}
Programın Çıktısı : 
Apple : 0
Banana : 1
Orange : 2
Peach : 3
Melon : 4
WaterMelon : 5

Apple Banana'dan önce gelir.
Apple eşittir Apple'a
Apple eşittir Apple'a
Tüm numaralandırmalar java.lang.Enum sınıfını devralır.Bu sınıfın bazı methodları vardır.Bu örnekte for-each döngüsü içerisinde kullanmış olduğum ordinal() methodu ilgili enum sabitinin konumunu integer olarak dönderir.( Dizideki indis(index) mantığı ile aynı) compareTo() methodu ise çağrıldığı sabit ile parametresine aldığı sabit'in konumlarını karşılaştırır.Eğer çağıran sabitin ordinal değeri çağrılandan küçük ise negatif bir değer döndürür.Büyük ise pozitif değer döndürür.Eğer sıfır değerini döndürürse 2 sabitin konumu eşit demektir.Buradaki equals() methodu ise çağıran ve çağrılan sabitlerin her ikiside aynı numaralandırmadan gelen aynı sabite karşılık geliyorsa true döndürür.

Java - Set ve Get Methodları


Bu yazımdaki örnekleri this anahtar sözcüğü üzerinden devam etmek istiyorum.
Önceki programlarda oluşturduğumuz yapılar kullanışlı olsada tam olarak yeterli değildir.Hiçbir değişkene direk erişim mümkün olmamalıdır.Nesneye Yönelimli Programlama'nın en önemli özelliklerinden olan Encapsulation ( Kapsülleme ) kavramını tam olarak uygulamamız için değişkenlerimizin Set ve Get methodlarını oluşturmalıyız.
Örnek üzerinden devam edelim.


class Rectangle {
 double width;
 double height;
 double depth;

 Rectangle(double width, double height, double depth) {
  this.width = width;
  this.height = height;
  this.depth = depth;
 }
}
Buradaki değişkenler default değer olarak sadece kendi paketleri içerisinde çağrılabilirler , fakat direkt olarak çağrılıp üzerinde işlem yapılabilir durumdadırlar.Bu kullanım oldukça tehlikeli ve yanlıştır.Aşağıdaki programı inceleyelim:
package com.blogger_project;

class Rectangle {
 private double width;
 private double height;
 private double depth;

 Rectangle(final double width, final double height, final double depth) {
  setWidth(width);
  setHeight(height);
  setDepth(depth);
 }

 Rectangle() {
  setWidth(-1);
  setHeight(-1);
  setDepth(-1);
 }

 double volume() {
  return width * height * depth;
 }

 public double getWidth() {
  return width;
 }

 public void setWidth(final double width) {
  this.width = width;
 }

 public double getHeight() {
  return height;
 }

 public void setHeight(final double height) {
  this.height = height;
 }

 public double getDepth() {
  return depth;
 }

 public void setDepth(final double depth) {
  this.depth = depth;
 }
}

class RectangleDemo {
 public static void main(final String args[]) {
  final Rectangle myRectangle = new Rectangle(5, 12, 6);
  System.out.println("Genişlik :" + myRectangle.getWidth());
  System.out.println("Yükseklik :" + myRectangle.getHeight());
  System.out.println("Derinlik :" + myRectangle.getDepth());
  System.out.println("Hacim : " + myRectangle.volume());

 }
}
Programın Çıktısı : 
Genişlik :5.0
Yükseklik :12.0
Derinlik :6.0
Hacim : 360.0
Bir önceki kullanımda
        
 this.width = width;
 this.height = height;
 this.depth = depth;
olarak constructor'e uygulayarak değerlerimizi atamıştık.Fakat burada set< Değişken Adı> isimli methodlarımızda yaptığımız işlemler aslında üstteki üç işlem ile aynı işi yapar. ( set < Değişken Adı> ve get < Değişken Adı> kullanımı programcılıkta bir standart haline geldiği için bu örnekte bu şekilde kullanılmaktadır.Eclipse -> Sağ Tık -> Source -> Generate Setters and Getters işlemini uygulayarak Set ve Get methodlarını otomatik oluşturabilirsiniz.Eclipse standart kullanımı yapmakla beraber method isimlerini değiştirmenize olanak sağlar. )Ayrıca değişkenleri gizler ve dışardan herhangi bir değişime izin vermezler.Burada değişken değerini değiştirmek için sadece değişkenin set methodu kullanılabilir.Bu yapıyı kullanarak artık değişkenlere direkt bir şekilde erişilemez.Sadece get< Değişken Adı> methodu kullanılarak erişilebilir.

Java - Çok Kanallı Programlama (Multi-Threaded
Programming) #3 Thread Sınıfını Genişletmek


Önceki örneklere aşağıdaki bağlantılardan ulaşabilirsiniz:
Java - Çok Kanallı Programlama (Multi-Threaded Programming)  #2
Java - Çok Kanallı Programlama (Multi-Threaded Programming)  #1

Bir önceki örneği daha iyi bir yoldan yapalım.

package com.blogger_project;

class NewThread extends Thread {
 NewThread() {
  super("Demo Thread");
  System.out.print("Çocuk Thread");
  System.out.print("Çocuk Thread" + this);
  start();
 }

 @Override
 public void run() {
  try {
   for (int i = 5; i > 0; i--) {
    System.out.println("Çocuk Thread" + i);
    Thread.sleep(500);
   }
  } catch (final InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("Çocuk Thread'den çıkıldı.");
 }
}

class ExtendThread {
 public static void main(final String args[]) {
  new NewThread();
  try {
   for (int i = 5; i > 0; i--) {
    System.out.println("Ana Thread" + i);
    Thread.sleep(1000);
   }
  } catch (final InterruptedException e) {
   e.printStackTrace();
  }
 }
}
Bir önceki program ile bu programın yaptığı iş aynıdır.Yeni bir kanal oluşturmanın bir diğer yolu ise Thread sınıfını genişleten bir sınıf oluşturup ve bu sınıfın bir örneğini oluşturmak.
super("Demo Thread");
NewThread'in içindeki super()'e yapılan çağrı Thread yapılandırıcısının aşağıdaki formunu çağırır.
public Thread(String threadName);
Buradaki threadName kanalın adını belirler.