Panduan untuk Antarmuka Eksternal di Java

1. Perkenalan

Dalam tutorial ini, kita akan melihat sekilas antarmuka java.io.Externalizable . Tujuan utama dari antarmuka ini adalah untuk memfasilitasi serialisasi dan deserialisasi kustom.

Sebelum melanjutkan, pastikan Anda melihat artikel serialisasi di Java. Bab selanjutnya adalah tentang cara membuat serial objek Java dengan antarmuka ini.

Setelah itu, kita akan membahas perbedaan utama dibandingkan dengan antarmuka java.io.Serializable .

2. Antarmuka Eksternal

Dapat dieksternalisasi meluas dari antarmuka penanda java.io.Serializable . Setiap kelas yang mengimplementasikan Externalizable antarmuka harus menimpa writeExternal () , readExternal () metode . Dengan cara itu kami dapat mengubah perilaku serialisasi default JVM.

2.1. Serialisasi

Mari kita lihat contoh sederhana ini:

public class Country implements Externalizable { private static final long serialVersionUID = 1L; private String name; private int code; // getters, setters @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeUTF(name); out.writeInt(code); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { this.name = in.readUTF(); this.code = in.readInt(); } }

Di sini, kami telah menetapkan Negara kelas yang mengimplementasikan antarmuka Dapat Dieksternalisasikan dan mengimplementasikan dua metode yang disebutkan di atas.

Dalam metode writeExternal () , kami menambahkan properti objek ke aliran ObjectOutput . Ini memiliki metode standar seperti writeUTF () untuk String dan writeInt () untuk nilai int.

Selanjutnya, untuk deserialisasi objek, kita membaca dari aliran ObjectInput menggunakan metode readUTF (), readInt () untuk membaca properti dalam urutan yang sama persis dengan yang mereka tulis.

Ini adalah praktik yang baik untuk menambahkan serialVersionUID secara manual. Jika ini tidak ada, JVM akan menambahkannya secara otomatis.

Nomor yang dibuat secara otomatis bergantung pada kompiler. Ini berarti hal itu dapat menyebabkan InvalidClassException yang tidak mungkin .

Mari kita uji perilaku yang kami terapkan di atas:

@Test public void whenSerializing_thenUseExternalizable() throws IOException, ClassNotFoundException { Country c = new Country(); c.setCode(374); c.setName("Armenia"); FileOutputStream fileOutputStream = new FileOutputStream(OUTPUT_FILE); ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); c.writeExternal(objectOutputStream); objectOutputStream.flush(); objectOutputStream.close(); fileOutputStream.close(); FileInputStream fileInputStream = new FileInputStream(OUTPUT_FILE); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); Country c2 = new Country(); c2.readExternal(objectInputStream); objectInputStream.close(); fileInputStream.close(); assertTrue(c2.getCode() == c.getCode()); assertTrue(c2.getName().equals(c.getName())); }

Dalam contoh ini, pertama-tama kita membuat objek Negara dan menulisnya ke file. Kemudian, kami deserialisasi objek dari file dan memverifikasi nilainya sudah benar.

Output dari objek c2 yang dicetak :

Country{name='Armenia', code=374}

Ini menunjukkan bahwa kita telah berhasil melakukan deserialisasi objek.

2.2. Warisan

Ketika kelas mewarisi dari antarmuka Serializable , JVM secara otomatis mengumpulkan semua bidang dari sub-kelas juga dan membuatnya dapat serial.

Perlu diingat bahwa kami juga dapat menerapkan ini ke Dapat Dieksternalisasikan . Kita hanya perlu mengimplementasikan metode baca / tulis untuk setiap sub-kelas dari hierarki pewarisan.

Mari kita lihat kelas Wilayah di bawah ini yang memperluas kelas Negara kita dari bagian sebelumnya:

public class Region extends Country implements Externalizable { private static final long serialVersionUID = 1L; private String climate; private Double population; // getters, setters @Override public void writeExternal(ObjectOutput out) throws IOException { super.writeExternal(out); out.writeUTF(climate); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal(in); this.climate = in.readUTF(); } }

Di sini, kami menambahkan dua properti tambahan dan membuat serial yang pertama.

Perhatikan bahwa kami juga memanggil super.writeExternal (out), super.readExternal (in) dalam metode serializer untuk menyimpan / memulihkan bidang kelas induk juga .

Mari kita jalankan unit test dengan data berikut:

Region r = new Region(); r.setCode(374); r.setName("Armenia"); r.setClimate("Mediterranean"); r.setPopulation(120.000);

Inilah objek deserialisasi:

Region{ country="Country{ name="Armenia', code=374}' climate="Mediterranean", population=null }

Perhatikan bahwa karena kami tidak membuat serial bidang populasi di kelas Region , nilai properti itu adalah null.

3. Dapat Dieksternalisasi vs Dapat Berseri

Mari kita bahas perbedaan utama antara kedua antarmuka:

  • Tanggung Jawab Serialisasi

Perbedaan utama di sini adalah bagaimana kami menangani proses serialisasi. Ketika kelas mengimplementasikan antarmuka java.io.Serializable , JVM bertanggung jawab penuh untuk membuat serial instance kelas. Dalam kasus Externalizable, programmerlah yang harus mengurus keseluruhan serialisasi dan juga proses deserialisasi.

  • Kasus Penggunaan

Jika kita perlu membuat serialisasi seluruh objek, antarmuka Serializable lebih cocok. Di sisi lain, untuk serialisasi kustom, kami dapat mengontrol proses menggunakan Externalizable .

  • Performa

The java.io.Serializable antarmuka menggunakan refleksi dan metadata yang menyebabkan kinerja relatif lambat. Sebagai perbandingan, antarmuka Externalizable memberi Anda kendali penuh atas proses serialisasi.

  • Urutan Membaca

Saat menggunakan Eksternalisasi , Anda wajib membaca semua status bidang dalam urutan persis seperti yang tertulis. Jika tidak, kami akan mendapatkan pengecualian.

Misalnya, jika kita mengubah urutan pembacaan kode dan nama properti di kelas Negara , java.io.EOFException akan dilempar.

Sementara itu, antarmuka Serializable tidak memiliki persyaratan itu.

  • Serialisasi Kustom

Kami dapat mencapai serialisasi kustom dengan antarmuka Serializable dengan menandai bidang dengan kata kunci transien . JVM tidak akan membuat serial bidang tertentu tetapi akan menambahkan bidang ke penyimpanan file dengan nilai default . Itulah mengapa praktik yang baik untuk menggunakan Eksternalisasi jika serialisasi kustom.

4. Kesimpulan

Dalam panduan singkat untuk antarmuka Eksternal ini , kami membahas fitur utama, keuntungan, dan contoh penggunaan sederhana. Kami juga membuat perbandingan dengan antarmuka Serializable .

Seperti biasa, kode sumber lengkap dari tutorial tersedia di GitHub.