Java Object Serialization

Java tamamen nesne yönelimli bir programlama dili olduğu için, Java üzerinde uygulama geliştirirken nesneleri sıkça kullanıyoruz. Java platformunda bilindiği gibi, int, double, byte gibi primitive tipler dışındaki herşey nesnedir.

Ancak Java’da kullanılan nesneler, Java platformunda (JVM) hayat bulurlar. Platform dışında nesnelerin, hiçbir anlamı yoktur. Nesne yönelimli programlama paradigmasını destekleyen Java’da, tasarlanan nesnelerin tekrar kullanılabilmesi (reuse) önemli bir konu olduğuna göre, bu nesneleri Java platformu dışında da hayata geçirmek gerçekten önemlidir. Bahsedilen bu problem, Java Serialization API sayesinde çok kolay bir şekilde aşılabiliyor.

Konuya bir de şu yönden bakarsak, herhangi bir nesne içerisindeki fieldları bir dosyaya yazdırdığımızda, bu verilerin sadece değerlerini (values) dosya içerisinde depolarız. Halbuki bu verilerin sınıf tanımlaması içerisindeki tipleri de en az değerleri kadar önemlidir. Herhangi bir nesnenin fieldındaki değer 3 ise, bu değerin string mi int mi olduğunun dosya üzerinde bir anlamı yoktur.

Java Serialization API sayesinde bir nesnenin birebir kopyasını, Java platformu dışında da depolayabiliriz. Bu mekanizma ile daha sonra,  nesneyi depolanan yerden çekip, aynı durum (state) ve özellikleri ile kullanmaya devam edebiliriz. Tüm bu sisteme, Object Serialization (Nesne Serileştirme) adı verilir.

Object Serialization Temelleri

Nesneleri serileştirmek için yapılması gereken tek şey, serileştirilecek nesnemizin serileştirilebilir (serializable) olduğunu tagging interface sayesinde sınıf deklarasyonunun başında belirtmek.

Peki, tagging interface tam olarak nedir? Tagging Interface, basit bir Java interfaceidir. Özelliği, içerisinde herhangi bir method tanımlaması yapmaz. Sadece belirli işlerin, belirli nesneler tarafından yapılabilmesi için sınıflara bazı standartlar oluşturmak için tasarlanmıştır. Nesne serileştirme işleminde de yapmamız gereken tek şey Serializable adındaki tagging interface i, serileştirilecek olan nesnenin sınıf deklarasyonunda ya da kalıtım ile türediği sınıfın bu interfacei uygulaması gerekmektedir. (implement edilmesi)

Nesneleri serileştirmek için Java platformu 2 temel sınıf sunar. ObjectInputStream ve ObjectOutputStream adı verilen bu iki sınıf ile, Serializable interfaceini uygulayan herhangi bir sınıfı serileştirebiliriz. Bu iki sınıfdan ilki olan ObjectInputStream, ObjectInput interfaceini uygular ve serileştrilen nesneyi tekrar akışdan okumak için kullanılır. ObjectInputStream adındaki diğer sınıf, ObjectOutput interfaceini uygular ve herhangi bir nesneyi akışa yazdırmak için kullanılır.

ObjectInput interfacei, readObject adında bir method sunar ve serileştirilen nesneyi akışdan okumak için kullanılır. Yine aynı şekilde ObjectOutput interfacei, writeObject adında bir method sunar ve bu method sayesinde Serializable interfaceini uygulayan herhangi bir nesneyi herhangi bir akışa yazdırabiliriz. Bu iki interfacei sırasıyla uygulayan ObjectInputStream ve ObjectOutputStream sınıfları bu methodları kendi içinde tanımlayarak, kullanıma hazırlar.

Bu iki sınıfı kullanmak çok basittir. Serileştirilecek ve geri çekilecek nesneler eğer dosyalar üzerinde yapılacaksa, bu iki sınıfa dosyaya yazdırmak için java.io paketince sunulan FileInputStream veya FileOutputStream nesnelerini geçirmek yeterlidir.

NonSerializable Objects

Buraya kadar nesnelerin neden serileştirilmesi gerektiğini ve bunlar için hangi adımları takip etmemiz gerektiğinden bahsettik. Serializable arayüzünü uygulayan bir sınıfın tüm nesneleri serileştirilebilirdir. Ancak, eğer sınıf içerisindeki değişkenlerin tamamı primitive tip ise sorun yok, çünkü tüm primitive tipler otomatik olarak serileştirilebilir. Ama, sınıf içerisinde referans tipde değişkenler (reference type variables) var ise, bu değişkenlerin tuttuğu nesne örneklerinin serileştirilebilir (Serializable) olduğunu sınıf tanımlamasından tespit etmelisiniz. Çünkü tüm nesnelerin türediği java.lang.Object sınıfı Serializable interfaceini uygulamaz. Örnek olarak String nesneleri Java da öntanımlı olarak Serializable interfaceini tanımlar.

Burda bahsetmem gereken bir diğer nokta da, serileştirilme işleminin yapılmasını istemediğiniz sınıf alanları varsa (fields) bunları transient olarak sınıf tanımlamasında belirtmemiz gerekiyor. Eğer, herhangi bir sınıf içinde javaBlog adında bir field var ve siz bu fieldı serileştirilme işleminden hariç tutmak istiyor iseniz, şu şekilde tanımlamanız gerekiyor.

transient private JavaBlog javaBlog;

Örnek Kod

Şimdi, içinde bazı fieldlar bulunan “JavaBlogSerializable.java” adında bir sınıf tanımlayalım.  Daha sonra bu sınıfı “java.dat” adında bir dosyaya serileştirip (serialization), daha sonra bu dosyadan nesnemizi geri alalım (deserialization)

JavaBlogSerializable.java adındaki sınıf tanımlaması.

//Serializable interfaceinin bulunduğu paketi koda dahil et
import java.io.Serializable;
 
class JavaBlogSerializable implements Serializable
{
    //Fieldlarımızı tanımlayalım
    // Tüm fieldlar serializable tipde !
 
    public int toplamYazi;
    public String yaziKonusu;
    public int blogHit;
    // Diğer kodlar, methodlar vs
 
} //end of class

Şimdi “java.dat” adındaki dosyaya bu nesneyi yazdıran sınıfımızı tanımlayalım

//Serileştirme işini yapan sınıf
import java.io.ObjectOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
 
class Serilestir
{
    private ObjectOutputStream objectOutputStream;
    public void kaydet()
    {
        try
        {
            objectOutputStream = new ObjectOutputStream(new FileOutputStream("java.dat"));
        }
        catch (IOException e)
        {
            System.err.println("Dosya Açılamadı, Hata!");
        }
        //serileştirilecek nesnemizi oluşturalım
        JavaBlogSerializable blog = new JavaBlogSerializable();
        blog.toplamYazi = 100;
        blog.yaziKonusu = "Java Serialization";
        blog.toplamHit = 150;
        //serileştirme işlemini başlat
        objectOutputStream.writeObject(blog);
    } //end of kaydet()
 
}//end of class

Şimdide “java.dat” dosyasına yazdığımız nesnemizi geri çekelim (deserialization)

//DeSerialization yapan sınıf
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
 
class DeSerializationOfObject
{
    private ObjectInputStream input;
    public void oku()
    {
        try
        {
             input = new ObjectInputStream(new FileInputStream("java.dat"));
        }
        catch (IOException e)
        {
            Syste.err.println("Dosya açılamadı, Hata !");
        }
        JavaBlogSerializable blog;
        blog = (JavaBlogSerializable) input.readObject();
    }
} // end of class

Görüldüğü gibi Java’da nesnelerin serileştirilmesi oldukça basit bir işlem.

Not : Bu arada örnek kod, Java’da nesne serileştirme işleminin nasıl yapıldığını göstermek için pek de özen gösterilmeden yazılmıştır.

Yorum bırakmak için buraya, Sitenizden trackback vermek için buraya tıklayabilirsiniz.

3 Responses to “Java Object Serialization”

  1. taha diyor ki:

    hocam elinize sağlık çok teşekkür ederim sonunda genel olarak anladim

  2. Noyan diyor ki:

    Muhtesem aciklama, tesekkurler!

  3. fatih diyor ki:

    Ben teşekkür ederim :)

Leave a Reply