Pewarisan, Polimorfisme, dan Kelas Abstrak

Posted by roberto in Java on July 14th, 2010 |  No Comments »

Kelas melambangkan cetak biru objek yang memiliki kesamaan struktuk dan perilaku. Kelas menentukan struktur suatu objek melalui variabel yang terkandung dalam setiap objek, dan menentukan perilaku melalui metode instansi yang merupakan perilaku suatu objek.

Ide utama dari pemrograman berorientasi objek — yang membedakannya dari pemrograman tradisional — adalah menciptakan kelas yang memiliki hanya beberapa (tidak semua) struktur dan perilaku. Kemiripan ini diekspresikan dalam bentuk pewarisan dan polimorfisme (perubahan bentuk).

Istilah pewarisan berarti suatu kelas bisa mewariskan sebagian atau keseluruhan struktur dan perilaku kelas lain. Jika kelas B adalah kelas turunan dari kelas A, maka kita bisa juga menyebut kelas A adalah kelas super dari kelas B. Kelas turunan bisa memiliki struktur atau perilaku tambahan dari kelas supernya. Atau bahkan kelas turunan bisa mengubah atau mengganti perilaku kelas supernya. Hubungan antara kelas turunan dan kelas super sering dilukiskan dalam bentuk diagram di mana kelas turunan digambarkan di bawah kelas supernya, dan dihubungkan dengan garis penghubung dengan tanda segitiga yang diletakkan di dekat kelas supernya.

Dalam bahasa Java, ketika kita membuat suatu kelas, kita bisa menyatakan bahwa kelas tersebut merupakan kelas turunan dari kelas lain. Jika kita buat kelas yang bernama “B” dan kita ingin kelas ini menjadi kelas turunan dari kelas “A”, kita akan tulis dalam bentuk :

class B extends A {
    .
    .  // tambahan atau perubahan
    .  // struktur dan perilaku dari kelas A
    .
}

Beberapa kelas dapat menurunkan kelas yang sama. Kelas-kelas turunan ini masing-masing disebut kelas saudara, yaitu diwariskan dari satu kelas super yang sama. Struktur dan perilaku kelas super ini akan dimiliki oleh masing-masing turunannya. Pada diagram berikut, kelas B, C, dan D adalah kelas saudara. Pewarisan juga bisa dilakukan beberapa kali, atau suatu kelas bisa memiliki cucu, buyut, dan seterusnya. Pada diagram, kelas E merupakan kelas turunan kelas D, sehingga kelas E adalah “cucu” dari kelas A. Kelas E masih bisa disebut turunan dari kelas A, walaupun bukan merupakan turunan langsungnya.

Mari kita buat sebuah contoh. Kita akan membuat program yang berhubungan dengan kendaraan bermotor, yang meliputi mobil, truk, dan motor. Program tersebut memiliki kelas yang dinamakan Kendaraan yang melambangkan semua  jenis kendaraan bermotor. Kelas Kendaraan memiliki variabel instansi seperti nomorPolisi dan pemilik dan metode instansi yang bernama gantiPemilik. Variabel dan metode instansi ini bisa digunakan oleh segala jenis kendaraan bermotor.

Ada 3 kelas turunannya yaitu Mobil, Truk dan Motor yang akan menyimpan variabel dan metode khusus untuk setiap jenis kendaraan. Kelas Mobil misalnya memiliki variabel jumlahPintu, kelas Truk memiliki variabel jumlahRoda, dan kelas Motor memiliki variabel jumlahTak. Kelas-kelas ini bisa dideklarasikan dalam Java dalam bentuk

class Kendaraan {
    int nomorPolisi;
    Orang pemilik;  // (anggap kelas Orang telah dibuat sebelumnya)
    void gantiPemilik(Orang pemilikBaru) {
        . . .
    }
    . . .
}

class Mobil extends Kendaraan {
    int jumlahPintu;
    . . .
}

class Truk extends Kendaraan {
    int jumlahRoda;
    . . .
}

class Motor extends Kendaraan {
    int jumlahTak;  // 2-tak atau 4-tak
    . . .
}

Anggap mobilku adalah variabel dengan tipe Mobil akan dideklarasikan dan diinisialisasi dengan pernyataan berikut

Mobil mobilku = new Mobil();

Dengan deklarasi seperti ini, maka program akan bisa mengakses mobilku.jumlahPintu, karena jumlahPintu adalah variabel instansi dari kelas Mobil. Akan tetapi karena kelas Mobil merupakan turunan dari kelas Kendaraan, maka mobil ini juga memiliki stuktur dan perilaku dari kendaraan. Artinya program juga bisa mengakses mobilku.nomorPolisi, mobilku.pemilik, dan menjalankan metode mobilku.gantiPemilik()

Dalam dunia nyata mobil, truk dan motor memang kendaraan (bukan hanya pada program). Dalam arti objek yang memiliki tipe Mobil atau Truk atau Motor juga secara otomatis objek bertipe Kendaraan. Fakta penting berikutnya :

Variabel yang dapat diisi referensi ke objek suatu kelas A juga dapat diisi referensi ke objek kelas turunan dari kelas A.

Efek praktis dari penyataan ini adalah, objek dengan tipe Mobil dapat diisi ke dalam variabel bertipe Kendaraan, atau dengan kata lain perintah berikut adalah valid

Kendaraan kendaraanku = mobilku;

atau bahkan juga perintah berikut

Kendaraan kendaraanku = new Mobil();

Setelah pernyataan di atas, variabel kendaraanku berisi referensi ke objek Kendaraan, yang kebetulan merupakan instansi dari kelas turunannya, yaitu kelas Mobil. Objek akan “mengingat” bahwa yang disimpan dalam variabel tersebut adalah objek bertipe Mobil, bukan Kendaraan. Informasi tentang objek apa yang disimpan pada memori ikut disertakan bersama objek tersebut, sehingga variabel yang bertipe Kendaraan akan tahu dengan pasti tipe objek yang dirujuknya. Kita juga dapat menguji jenis objek yang disimpan suatu variabel dengan menggunakan operator instanceof. Misalnya

if (kendaraanku instanceof Mobil) { ... }

menguji apakah objek yang dirujuk pada variabel kendaraanku merupakan objek bertipe Mobil.

Kebalikannya, pernyataan berikut tidak bisa dilakukan

mobilku = kendaraanku;

karena kendaraanku bisa bertipe objek lain seperti Truk atau Motor. Apabila kita tahu persis bahwa kendaraanku bertipe Mobil, kita bisa menggunakan casting, untuk memberi tahu komputer untuk memperlakukan variabel kendaraanku memiliki tipe Mobil. Jadi kita bisa gunakan perintah

mobilku = (Mobil)kendaraanku;

Atau kita juga bisa mengakses ((Mobil)kendaraanku).jumlahPintu. Mari kita gunakan kelas ini dalam program, dan kita ingin mencetak informasi yang sesuai dengan suatu kendaraan. Misalnya:

System.out.println("Data Kendaraan:");
System.out.println("Nomor polisi:  " + kendaraanku.nomorPolisi);
if (kendaraanku instanceof Mobil)
    System.out.println("Jenis kendaraan:  Mobil");
    Mobil m = (Mobil)kendaraanku;
    System.out.println("Jumlah pintu:  " + m.jumlahPintu);
}
else if (kendaraanku instanceof Truk) {
    System.out.println("Jenis kendaraan:  Truk");
    Truk t = (Truk)kendaraanku ;
    System.out.println("Jumlah roda:  " + t.jumlahRoda);
}
else if (kendaraanku instanceof Motor) {
    System.out.println("Jenis kendaraan:  Motor");
    Motor sm = (Motor)kendaraanku ;
    System.out.println("Jumlah tak:    " + sm.jumlahTak);
}

Lihat bahwa untuk setiap jenis objek, komputer akan menguji satu per satu tipe objek yang disimpan dalam kendaraanku. Jika kendaraanku[code] merujuk pada objek bertipe Truk maka casting [code](Mobil)kendaraanku akan menampilkan pesan kesalahan.


Contoh lain, mari kita buat program untuk menggambar suatu bentuk geometri pada layar. Misalnya bentuk geometri tersebut terdiri dari persegi panjang, oval, dan kotak bersudut lingkar dengan berbagai warna.

Kelas yang akan kita buat adalah PersegiPanjang, Oval, dan KotakLingkar. Ketiga kelas tersebut memiliki kelas super yang sama yang disebut BentukGeometris. Kelas BentukGeometris memiliki variabel instansi warna, lokasi, dan ukuran. Untuk mengganti warna kita bisa mengganti variabel instansi warna pada kelas ini, kemudian menjalankan metode instansi gambar() untuk menggambar bentuk tersebut dengan warna baru:

class BentukGeometris {
    Color warna;   // Warna suatu bentuk geometri
                   // (Kelas Color diimport dari paket java.awt)

    void setWarna(Color warnaBaru) {
        // Metode untuk mengganti warna
        warna = warnaBaru; // ganti nilai variabel instansi
        gambar(); // gambar ulang bentuk geometris ini, dengan warna baru
    }

    void gambar() {
        // metode untuk menggambar
        ? ? ?  // perintaha apa yang harus diletakkan di sini?
    }

    . . .          // variabel dan metode instansi lain

} // akhir kelas BentukGeometris

Sekarang metode gambar() mungkin menjadi serba salah. Masalahnya, setiap bentuk digambar dengan cara berbeda. Metode setWarna() dapat digunakan oleh semua bentuk. Lalu bagaimana komputer tahu bagaimana menggambar bentuk tersebut jika metode gambar() dipanggil? Mudahnya, kita bisa jawab dengan : Komputer akan menjalankan perintah gambar() dengan meminta bentuk tersebut untuk menggambar sendiri. Setiap objek bentuk tahu apa yang harus dilakukan untuk menggambar dirinya.

Dalam prakteknya, ini berarti setiap kelas turunan dari kelas BentukGeometris memiliki metode gambar() sendiri-sendiri, yaitu :

class PersegiPanjang extends BentukGeometris {
    void gambar() {
        . . .  // perintah untuk menggambar persegi panjang
    }
    . . . // metode atau variabel lain
}

class Oval extends BentukGeometris {
    void gambar() {
        . . .  // perintah untuk menggambar oval
    }
    . . . // metode atau variabel lain
}

class KotakLingkar extends BentukGeometris {
    void gambar() {
        . . .  // perintah untuk menggambar kotak bersudut lingkar
    }
    . . . // metode atau variabel lain
}

Jika gambarku adalah variabel bertipe BentukGeometri, variabel ini bisa merujuk pada objek dengan bertipe PersegiPanjang, Oval, atau KotakLingkar. Ketika program dijalankan, isi variabel gambarku akan berubah-ubah, tergantung pada objek yang dirujuknya. Suatu saat di tengah program, jika perintah gambarku.gambar() dijalankan, maka metode gambar() akan dijalankan tergantung pada isi variabel gambarku saat itu.

Kita tidak akan bisa menebak metode apa yang akan dipanggil pada suatu saat hanya dengan membaca program tersebut, karena kita tidak pernah tahu isi variabel gambarku pada suatu saat tertentu. Misalnya perintah gambar() berada dalam suatu perulangan yang dijalankan berkali-kali. Maka akan sangat mungkin perintah gambarku.gambar() dipanggil berulang-ulang tetapi dengan objek yang berbeda-beda.

Kita sebut metode gambar() bersifat polimorfis. Suatu metode disebut polimorfis jika aksi yang dilakukan oleh suatu metode berbeda-beda tergantung pada objek aktual pada saat metode itu dijalankan. Polimorfisme adalah fitur utama dalam pemrograman berorientasi objek.

Mungkin akan lebih mudah dimengerti jika kita ganti bahasanya : Dalam PBO, memanggil metode sering disebut juga dengan mengirim pesan kepada suatu objek. Objek tersebut merespon pesan tersebut dengan melaksanakan metode yang sesuai. Pernyataan “gambarku.gambar();” adalah pesan yang dikirim ke objek gambarku. Karena objek tersebut tahu jenis objeknya sendiri, dia akan tahu bagaimana merespon pesan tersebut. Dari sudut pandang ini, komputer akan selalu mengeksekusi perintah “gambarku.gambar();” dengan cara yang sama, yaitu dengan mengirim pesan. Pesan tersebut bergantung pada siapa yang menerima pesan tersebut.

Dengan kata lain, objek merupakan sesuatu yang memiliki perilaku aktif, yaitu sesuatu yang bisa mengirim dan menerima pesan. Polimorfisme dianggap sebagai sifat yang natural jika dilihat dari sudut pandang ini. Polimorfisme juga berarti bahwa beberapa objek dapat merespon suatu pesan dengan cara yang berbeda-beda.

Salah satu keindahan dari poliformisme adalah kita bisa membuat kode program tanpa harus mengetahui persis apa yang akan dilakukan program saat kita menulis program tersebut. Jika kita ingin menambah objek lain, misalnya segitiga, maka kita cukup menulis kelas turunan baru dan membuat metode gambar() sendiri. Secara otomatis, program akan tahu jika kita beri perintah “gambarku.gambar()” maka metode gambar() pada kelas segitiga akan dijalankan apabila gambarku menunjuk pada objek yang memiliki kelas segitiga.


Ketika suatu objek, misalnya PersegiPanjang, Oval, atau KotakLingkar, harus menggambar dirinya sendiri, metode gambar() yang sesuai dengan objek yang menerima pesan akan dilaksanakan. Pertanyaannya, apa yang harus kita isi pada metode gambar() di kelas BentukGeometri?

Jawabannya: kosongkan saja. Intinya kelas BentukGeometri adalah kelas abstrak, karena tidak ada cara untuk menggambar BentukGeometri. Apabila kelas tersebut telah direalisasikan dalam suatu bentuk, misalnya PersegiPanjang, barulah objek tersebut bisa menggambar sesuatu.

Lalu kenapa kita harus mendeklarasikan metode gambar() di kelas BentukGeometri? Jawabannya, itu harus ada karena metode ini dibutuhkan untuk memanggil metode setWarna() pada kelas BentukGeometri. Program kita akan menampilkan pesan kesalahan jika kita berikan perintah gambarku.gambar(), karena gambarku bertipe BentukGeometri, apabila di dalam kelas ini tidak ada metode yang bernama gambar().

Kita bisa menyebut kelas BentukGeometri merupakan kelas abstrak. Kelas abstrak adalah kelas yang tidak bisa digunakan untuk membuat suatu objek, dan hanya digunakan untuk membuat kelas turunan. Kelas abstrak hanya ada untuk mengekspresikan sifat umum yang dimiliki oleh kelas-kelas turunannya.

Demikian juga, kita bisa menyebut metode gambar() pada kelas BentukGeometri merupakan metode abstrak, karena metode ini bukan untuk dipanggil. Akan tetapi metode ini ada untuk memberi tahu komputer bahwa semua kelas turunannya mengerti dan bisa menjalankan metode gambar().

BentukGeometri dan metode gambar() secara sematik merupakan kelas dan metode abstrak. Kita juga bisa memberi tahu komputer secara langsung dengan memberi sifat “abstract” pada definisinya. Untuk metode abstrak, blok perintahnya diganti dengan titik koma (;). Metode ini harus diimplementasikan secara detail pada kelas turunannya.

Perhatikan contoh berikut.

abstract class BentukGeometri {
    Color warna;

    void setWarna(Color warnaBaru) {
        // metode untuk mengganti warna suatu bentuk
        warna = warnaBaru; // ganti isi variabel instansi warna
        gambar(); // menggambar kembali suatu bentuk dengan warna baru
    }

    abstract void gambar();
        // metode abstrak yang harus diimplementasikan
        // pada kelas turunannya

        . . .          // variabel dan metode instansi lainnya

} // akhir kelas BentukGeometri

Setelah kita buat seperti ini, kita tidak bisa lagi membuat objek langsung dari kelas BentukGeometri.


Dalam Java, setiap kelas yang kita buat akan memiliki kelas super, atau dengan kata lain setiap kelas merupakan turunan dari kelas lain. Jika kita tidak memberi kelas supernya (melalui operator extends), maka kelas tersebut otomatis memiliki kelas super Object, yaitu kelas bawaan yang sudah didefinisikan dalam paket java.lang. Kelas Object adalah satu-satunya kelas yang tidak memiliki kelas super.

Jadi dengan demikian, perintah

class Kelasku { ... }

sama artinya dengan

class Kelasku extends Object { . . . }

Semua kelas akan merupakan turunan langsung atau tidak langsung dari kelas Object. Artinya suatu obek yang merupakan kelas apapun dapat direferensikan oleh variabel bertipe Object. Kelas Objek memiliki sifat-sifat umum yang dapat digunakan oleh semua objek. Kelas Object adalah kelas yang paling abstrak dari kelas-kelas lainnya.

Kelas Object digunakan dalam beberapa kasus di mana kumpulan objek yang sangat umum ingin diolah. Misalnya, Java memiliki kelas standar java.util.ArrayList yang merupakan kumpulan Objects. ArrayList akan dibahas kemudian dalam topik tentang struktur data dan algoritma. Kelas ini digunakan untuk menampung kumpulan objek, tak ditentukan jumlahnya, dan bisa diperbanyak ketika objek baru ditambahkan. Objek yang dapat ditampung pada dasarnya adalah semua objek dari beragam kelas.

Kita dapat juga membuat program untuk menampung semua BentukGeometri yang telah digambar di layar dalam kontainer ArrayList. Milsanya ArrayList kita bernama kumpulanGambar. Suatu objek dengan tipe BentukGeometri misalnya gambarku dapat ditambahkan ke dalam kumpulan ini dengan menggunakan perintah “kumpulanGambar.add(gambarku);“. Gambar tersebut dapat dibuang dari dalam kumpulan dengan perintah “kumpulanGambar.remove(gambarku);“. Jumlah obejk dalam kumpulanGambar dapat diubah dengan perintah “kumpulanGambar.size()“. Juga kita bisa mengambil gambar ke-n dari dalam kumpulanGambar dengan perintah “kumpulanGambar.get(n);“. Perlu diingat bahwa metode tersebut akan mengembalikan objek bertipe Object bukan BentukGeometri, dan sebetulnya kontainer ini bisa menampung objek apa saja, bukan hanya BentukGeometri, sehingga untuk mengambil objek ke-n yang kemudian kita letakkan dalam variabel bertipe BentukGeometri, kita bisa gunakan perintah

gambarku = (BentukGeometri)kumpulanGambar.get(n);

Katakan misalnya kita ingin menggambar semua objek dengan berbagai tipe di dalam kumpulan tersebut, kita bisa gunakan perulangan for sederhana (sekaligus memberi contoh betapa indagnya PBO dan polimorfisme), yaitu dengan :

for (int n = 0; n < kumpulanGambar.size(); n++) {
    BentukGeometri bg = (BentukGeometri)kumpulanGambar.get(n);
    bg.gambar();
}

Penutup

Dalam pemrograman sehari-hari, terutama bagi programmer yang baru belajar dan bekerja dengan objek, penurunan kelas akan sering digunakan. Salah satunya adalah untuk memperluas kegunaan suatu kelas, yang disesuaikan dengan situasi dan kondisi permasalahan yang kita hadapi. Kita bisa membuat kelas baru yang merupakan turunan kelas yang sudah ada, menambah beberapa variabel dan metode instansi baru, yaitu dengan operator extends seperti dijelaskan sebelumnya pada bagian ini.

Secara umum, sintaksnya adalah dalam bentuk

class kelas_turunan extends kelas_yang_sudah_ada {
   ... // tambahan atau perubahan variabel dan metode instansi
}

Kita akan lihat nanti bahwa banyak kelas-kelas standar pada Java yang digunakan hanya sebagai kelas dasar yang untuk dikembangkan lebih jauh oleh kita sebagai programmer

Serialization

Posted by roberto in Java on July 14th, 2010 |  No Comments »

Serialization melibatkan state dari objek yang sedang disimpan ke sebuah stream dan mengembalikan objek yang sama dari stream tersebut. Stream berfungsi sebagai container bagi objek.  Sumber lain mengatakan Serialization dari sebuah objek adalah proses penyimpanan dari state objek menjadi rangkaian rangkaian bytes,  dan juga proses membangun kembali byte2 tersebut menjadi objek yang hidup dalam beberapa waktu kedepan. Java Serialization API menyediakan suatu mekanisme standart utk para developer agar dapat menghandle serialization dari suatu objek. API itu kecil dan mudah menggunakannya, dapat dimengerti karena menyediakan klas2 dan metod2.

Suatu object yang dapat disimpan dan dibuat lagi (persist) harus dibuat
menjadi persistance object. Sebuah objek yang ditandai serializable dengan mengimplementasikan java.io.Serializable interface. Contoh sebuah persisten class yang akan kita gunakan utk mendemonstrasikan mekanisme serialization:

10 import java.io.Serializable;
20 import java.util.Date;
30 import java.util.Calendar;
40 public class PersistentTime implements Serializable
50 {
60 private Date time;
70
80 public PersistentTime()
90 {
100      time = Calendar.getInstance().getTime();
110    }
120
130    public Date getTime()
140    {
150      return time;
160    }
170  }

Rule #1 : Objek yang ingin terus eksist (persisted) harus mengimplementasikan Serializable interface atau mewarisi pengimplementasian itu dari hirarki objek itu sendiri. Step berikutnya adalah bener2 membuat objek itu persist.

Liat kode berikut digunakan utk menyimpan objek PersistentTime:

10 import java.io.ObjectOutputStream;
20 import java.io.FileOutputStream;
30 import java.io.IOException;
40 public class FlattenTime
50 {
60 public static void main(String [] args)
70 {
80 String filename = "time.ser";
90 if(args.length > 0)
100     {
110       filename = args[0];
120     }
130     PersistentTime time = new PersistentTime();
140     FileOutputStream fos = null;
150     ObjectOutputStream out = null;
160     try
170     {
180       fos = new FileOutputStream(filename);
190       out = new ObjectOutputStream(fos);
200       out.writeObject(time);
210       out.close();
220     }
230     catch(IOException ex)
240     {
250       ex.printStackTrace();
260     }
270   }
280 }

Tugas nyata yang terjadi adalah pada baris ke 200 ketika kita memanggil metod ObjectOutputStream.writeObject(), yang mana memulai mekanisme serialization dan objek itu diratakan/dipaparkan.

Untuk mengembalikan file tersebut, kita dapat menggunakan kode sbb:

10 import java.io.ObjectInputStream;
20 import java.io.FileInputStream;
30 import java.io.IOException;
40 import java.util.Calendar;
50 public class InflateTime
60 {
70 public static void main(String [] args)
80 {
90 String filename = "time.ser";
100     if(args.length > 0)
110     {
120       filename = args[0];
130     }
140   PersistentTime time = null;
150   FileInputStream fis = null;
160   ObjectInputStream in = null;
170   try
180   {
190     fis = new FileInputStream(filename);
200     in = new ObjectInputStream(fis);
210     time = (PersistentTime)in.readObject();
220     in.close();
230   }
240   catch(IOException ex)
250   {
260     ex.printStackTrace();
270   }
280   catch(ClassNotFoundException ex)
290   {
300     ex.printStackTrace();
310   }
320   // print out restored time
330   System.out.println("Flattened time: " + time.getTime());
340   System.out.println();
350      // print out the current time
360   System.out.println("Current time: " + Calendar.getInstance().getTime());
370 }
380}

Pada kode di atas, pengembalian objek terjadi pada baris ke 210 dengan memanggil metod ObjectInputStream.readObject () .

Object Serialization

Posted by roberto in Java on July 14th, 2010 |  No Comments »

Serializable secara teori didefinisikan sebagai “Mengubah sebuah object menjadi barisan bit sedemikian rupa sehingga object tersebut dapat disimpan ke dalam secondary memory.”

Di Java, agar sebuah kelas dapat diserialisasi, maka kelas itu harus mengimplementjava.io.Serializable untuk memberitahu Java Virtual Machine bahwa instans-instans dari kelas ini dapat diserialisasi dan disimpan di dalam secondary memory such sebagai file atau lebih jauh lagi, dikirim via jaringan.

Beberapa hal yang perlu anda ketahui tentang object serialization:

  1. Security
    Isu penting dalam serialisasi adalah sekuriti. Karena, ketika sebuah objek diserialisasi, objek tersebut menjadi barisan bit-bit yang tersimpan dalam sebuah file biner. Jika seseorang dapat mengakses file tersebut (yang merupakan hasil serialisasi) dan memanipulasi bit-bit itu, maka objek-objek anda telah di-hack dan hal ini dapat dilakukan dengan mudah karena access modifier apapun tidak akan berpengaruh lagi :D
  2. State dari suatu objek
    Satu hal yang perlu dipertimbangkan ketika men-serialisasi suatu objek adalah state dari objek tersebut. Banyak objek berubah menurut waktu dan ada juga objek-objek yang sangat dependent kepada environment-nya. Sebagai contoh, sebuah object dari kelas Thread biasanya berubah dari waktu ke waktu dan sebuah object dari kelas Socket sangat spesifik terhadap workstation tertentu pada waktu tertentu. Berdasarkan inilah, maka Java memutuskan untuk membiarkan anda menentukan kelas mana yang boleh diserialisasi dan mana yang tidak.
  3. Keyword Static
    Hal tricky yang harus anda pertimbangkan ketika memutuskan apakah harus mengimplement interface Serializable atau tidak adalah keyword static. Sekarang perhatikan baik-baik kelas java.lang.Math!! Kelas ini tidak tergantung waktu dan juga tidak tergantung mesin ataupun JVM, tetapi kelas ini tidak serializable. Kenapa? Karena semua fitur yang ditawarkan oleh kelas Math diberi tanda static yang berarti bahwa fitur-fitur tersebut akan di-load ke dalam JVM pada saat kompilasi. Hal ini berarti kelas tersebut tidak perlu diserialisasi. Jadi, jika suatu kelas hanya memiliki method private atau static, kemungkinan besar kelas tersebut tidak perlu mengimplement interface Serializable.
  4. Transient
    Hal terakhir yang perlu diketahui ketika mendesain suatu kelas yang serializable adlah keyword Transient. Field manapun yang dideklarasikan sebagai transient akan di-skip oleh JVM ketika JVM menserialisasi objek dari kelas tersebut.

Bagaimana jika kelas saya memiliki object reference(s)? Apakah JVM men-serialisasi mereka juga? Jawabannya adalah Ya. Selama object reference tersebut adalah reference yang menuju ke object yang serialisable, dan anda tidak memberikan keyword transient di sekitarnya, maka JVM akan men-serialisasi objek-objek yang direfer tersebut. :D

Hal lain yang menarik dalam serialisasi adalah field statik yang bernama serialVersionUID. Field ini merepresentasikan versi dari kelas. Artinya, kita tidak bisa me-load suatu objek jika serialVersionUID dari objek tersebut berbeda dengan serialVersionUID yang anda punya. Walaupun objek tersebut datang dari kelas yang sama, JVM akan menghalangi anda untuk me-load suatu serialized object ketika JVM mengetahui bahwa serialVersionUID-nya berbeda. Catatlah bahwa anda tidak perlu mengganti serialVersionUID jika anda hanya mengganti method-method atau field-field static. Ubahlah nilai serialVersionUID hanya jika anda mengubah field-field non-static pada objek tersebut.

Apakah nilai serialVersionUID acak? Tidak. Yah.. sebenarnya, anda dapat saja memberikan nilai yang anda inginkan tapi itu tidak baik karena serialVersionUID yang anda berikan mungkin saja sudah dipakai oleh kelas lain. Sangat dianjurkan untuk meng-generate nilai serialVersionUID dari IDE yang anda pakai seperti Eclipse, Netbeans atau JDeveloper.

public class SerializableObject implements Serializable{
private static final long serialVersionUID = -6849794470754337710L;
}

Sumber : http://hjaya.wordpress.com/2008/11/29/object-serialization/