Jan 1, 0001  

title: Java Dersleri 10 - Nesne Serileştirme (Serialization) link: http://orhanbalci.net/tr/?p=1052 author: Orhan Balci description: post_id: 1052 created: 2011/07/07 00:43:05 created_gmt: 2011/07/06 21:43:05 comment_status: open post_name: java-dersleri-10-nesne-serilestirme-serialization status: publish post_type: post

Java Dersleri 10 - Nesne Serileştirme (Serialization)

Bu makalede nesnelerin serileştirilmesi ve serileştirilmiş ortamdan tekrar nesnelerimizi oluşturmayı öğreneceğiz. Serileştirme işlemi elimizde bulunan nesneleri belirli bir binary formatta kaydetme işlemidir. Java bu işleme özel bir önem atfettiği için dilin temeline bu işlemleri kolaylaştıracak yapılar eklemiştir ve çoğu işlemi kullanıcının haberi olmadan otomatik gerçekleştirmektedir. Serileştirme işlemi özellikle networkten veri aktarma ve persistence işlemlerinde sıkça kullanılmaktadır. Serileştirme işlemini yapmak için kullanacağımız en temel üç öğe Serializable arayüzü, ObjectInputStream ve ObjectOutputStream akım sınıflarıdır. Serializable arayüzü bir işaretleyici arayüzdür. Arayüzleri anlattığım makalade işaretleyici arayüzlerşn özelliklerine değinmiştim. Herhangi bir metod içermeyen bu arayüzler implement edildiği sınıfları özel işlemler için işaretler. Serializable arayüzünü gerçekleyen herhangi bir sınıf JVM tarafından serileştirilebilir olarak nitelendirilmiş olur. Serileştirme işlemlerini daha iyi kavrayabilmek için bir örnek verelim. Bu örneğimizde bir insanı yazılımsal olarak tanımlamaya çalışalım. Kolaylık olması amacıyla insanın iki el ve bu ellerinde bulunan beşer parmaktan oluştuğunu varsayalım. Ve her bir sınıfın birer “isim” özelliği bulunsun sınıflarımız şu şekilde olacaktır : [java] package net.orhanbalci.serialization; import java.io.Serializable; /** * * @author orhan */ public class Insan implements Serializable { private El[] _eller; private String _isim; public Insan(String _isim) { this._isim = _isim; _eller = new El[2]; _eller[0] = new El(“Sağ El”); _eller[1] = new El(“Sol El”); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(“İnsan{isim=”).append(_isim).append(“}”).append(”\n”); for (El e : _eller) { sb.append(e.toString()); sb.append(”\n”); } return sb.toString(); } } [/java] [java] package net.orhanbalci.serialization; import java.io.Serializable; /** * * @author orhan */ public class El implements Serializable { private String _isim; private Parmak[] _parmaklar; public El(String _isim) { this._isim = _isim; _parmaklar = new Parmak[5]; _parmaklar[0] = new Parmak(“Bas Parmak”); _parmaklar[1] = new Parmak(“İşaret Parmak”); _parmaklar[2] = new Parmak(“Orta Parmak”); _parmaklar[3] = new Parmak(“Yüzük Parmak”); _parmaklar[4] = new Parmak(“Serçe Parmak”); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(“El{isim=”).append(_isim).append(“}”).append(”\n”); for (Parmak p : _parmaklar) { sb.append(p.toString()); sb.append(”\n”); } return sb.toString(); } } [/java] [java] package net.orhanbalci.serialization; import java.io.Serializable; /** * * @author orhan */ public class Parmak implements Serializable { private String _isim; public Parmak(String _isim) { this._isim = _isim; } public String getIsim() { return _isim; } public void setIsim(String _isim) { this._isim = _isim; } @Override public String toString() { return “Parmak{” + “isim=” + _isim + ‘}’; } } [/java] Sınıflarımızı tanımladıktan sonra bir adet insan nesnesi oluşturup bunu öncelikle bir dosyaya serileştirip daha sonra aynı dosyadan tekrar okuyan örneğimize bakalım. Bu örnekte nesnemizin özellikleri dosyaya serileştirilmeden önce ve sonra ekrana yazdırılıyor böylelikle iki nesne arasında fark olmadığı anlaşılabilir : [java] package net.orhanbalci.serialization; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * * @author orhan */ public class Main { public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { Insan ali = new Insan(“ali”); System.out.println(ali); FileOutputStream fos = new FileOutputStream(new File(“ali.bin”)); ObjectOutputStream ous = new ObjectOutputStream(fos); ous.writeObject(ali); FileInputStream fis = new FileInputStream(“ali.bin”); ObjectInputStream ois = new ObjectInputStream(fis); Insan okunmusAli = (Insan) ois.readObject(); System.out.println(okunmusAli); } } [/java] 23. ve 27. satırlardaki çağrımlarla nesneyi serileştirip, tekrar oluşturuyoruz. Burada Java’nın bizim adımıza yaptığı birden fazla iş vardır. Örneğin Insan sınıfı komposit bir sınıf olduğu için bu sınıfa ait bir nesne serileştirildiğinde bu nesneye ait olan El nesneleri dolayısıyla da Parmak nesneleri de otomatik olarak serileştirilir. İçerisinde serileştirilemeyen bir üye taşıyan sınıflar serileştirilemez. Bunu yukarıdaki örnekte El veya Parmak sınıfının Serializable interface’ini kaldırarak deneyebilirsiniz. Bu durumda “NotSerializableException” çalışma zamanı hatası alacaksınız. Peki herhangi bir üye elemanı serileştirmeden bu üyeye sahip nesneyi nasıl serileştirebilirim? Bunun için de “transient” anahtar kelimesi mevcuttur. Yine yukarıdaki örnekte Parmek sınıfının Serializable interfaceini kaldıralım ve El sınıfında [java] transient private Parmak[] _parmaklar; [/java] değişikliğini yaparsak serileştirme açısından problem yaşamayacağız. Fakat nesnemizi serileştirilmiş veriden tekrar oluştururken bu bilgileri kaybedeceğiz. Peki Java bu işleri bizim için yapmasına karşılık kendi serileştirme mekanizmamızı yazmak istersek ne yapmalıyız? Sınıfımıza şu metodları eklememiz yeterli olacaktır : [java] private void writeObject(ObjectOutputStream out) throws IOException; private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException; [/java] [ad#Yazi Ici Buyuk]