Apa perbedaan antara Serializable
dan Externalizable
di Jawa?
Apa perbedaan antara Serializable
dan Externalizable
di Jawa?
Jawaban:
Untuk menambah jawaban lain, dengan mengimplementasikan java.io.Serializable
, Anda mendapatkan kemampuan serialisasi "otomatis" untuk objek kelas Anda. Tidak perlu menerapkan logika lain, itu hanya akan berfungsi. Java runtime akan menggunakan refleksi untuk mengetahui cara menyusun dan menghapus objek Anda.
Dalam versi Java yang lebih lama, refleksi sangat lambat, dan karenanya serializaing grafik objek besar (misalnya dalam aplikasi RMI client-server) adalah sedikit masalah kinerja. Untuk menangani situasi ini, java.io.Externalizable
antarmuka disediakan, yang seperti java.io.Serializable
tetapi dengan mekanisme yang dibuat khusus untuk melakukan fungsi marshalling dan unmarshalling (Anda perlu mengimplementasikan readExternal
dan writeExternal
metode pada kelas Anda). Ini memberi Anda sarana untuk mengatasi hambatan kinerja refleksi.
Dalam versi Jawa terbaru (1.3 dan seterusnya, tentu saja) kinerja refleksi jauh lebih baik daripada sebelumnya, dan ini jauh lebih sedikit masalah. Saya curiga Anda akan kesulitan untuk mendapatkan manfaat yang berarti dari Externalizable
JVM modern.
Juga, mekanisme serialisasi Java bawaan bukan satu-satunya, Anda bisa mendapatkan penggantian pihak ketiga, seperti JBoss Serialization, yang jauh lebih cepat, dan merupakan pengganti drop-in untuk default.
Kelemahan besar Externalizable
adalah Anda harus mempertahankan logika ini sendiri - jika Anda menambah, menghapus, atau mengubah bidang di kelas Anda, Anda harus mengubah metode writeExternal
/ Anda readExternal
untuk menjelaskannya.
Singkatnya, Externalizable
adalah peninggalan dari Jawa 1,1 hari. Benar-benar tidak perlu lagi.
Externalizable
membantu banyak .
Externalizable
cocok untuk saya jauh lebih baik, karena saya tidak ingin menampilkan array dengan ruang kosong atau objek placeholder, ditambah dengan antarmuka eksplisit Anda dapat menangani warisan, yang berarti sub tersinkronisasi saya -kelas dapat dengan mudah menambahkan mengunci di sekitar panggilan writeExternal()
. Jadi ya, Externalizable masih sangat relevan, tentunya untuk objek besar atau kompleks.
Serialisasi memberikan fungsionalitas default untuk menyimpan dan kemudian membuat ulang objek. Menggunakan format verbose untuk mendefinisikan seluruh grafik objek yang akan disimpan misalkan Anda memiliki linkedList dan kode Anda seperti di bawah ini, maka serialisasi default akan menemukan semua objek yang terhubung dan akan bersambung. Dalam serialisasi default, objek dibangun sepenuhnya dari bit yang tersimpan, tanpa panggilan konstruktor.
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("/Users/Desktop/files/temp.txt"));
oos.writeObject(linkedListHead); //writing head of linked list
oos.close();
Tetapi jika Anda ingin serialisasi terbatas atau tidak ingin sebagian dari objek Anda menjadi serial, gunakan Externalizable. Antarmuka Externalizable memperluas antarmuka Serializable dan menambahkan dua metode, writeExternal () dan readExternal (). Ini secara otomatis disebut serialisasi atau deserialization. Ketika bekerja dengan Externalizable kita harus ingat bahwa konstructer default harus publik atau kode akan membuang pengecualian. Silakan ikuti kode di bawah ini:
public class MyExternalizable implements Externalizable
{
private String userName;
private String passWord;
private Integer roll;
public MyExternalizable()
{
}
public MyExternalizable(String userName, String passWord, Integer roll)
{
this.userName = userName;
this.passWord = passWord;
this.roll = roll;
}
@Override
public void writeExternal(ObjectOutput oo) throws IOException
{
oo.writeObject(userName);
oo.writeObject(roll);
}
@Override
public void readExternal(ObjectInput oi) throws IOException, ClassNotFoundException
{
userName = (String)oi.readObject();
roll = (Integer)oi.readObject();
}
public String toString()
{
StringBuilder b = new StringBuilder();
b.append("userName: ");
b.append(userName);
b.append(" passWord: ");
b.append(passWord);
b.append(" roll: ");
b.append(roll);
return b.toString();
}
public static void main(String[] args)
{
try
{
MyExternalizable m = new MyExternalizable("nikki", "student001", 20);
System.out.println(m.toString());
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/Users/Desktop/files/temp1.txt"));
oos.writeObject(m);
oos.close();
System.out.println("***********************************************************************");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/Users/Desktop/files/temp1.txt"));
MyExternalizable mm = (MyExternalizable)ois.readObject();
mm.toString();
System.out.println(mm.toString());
}
catch (ClassNotFoundException ex)
{
Logger.getLogger(MyExternalizable.class.getName()).log(Level.SEVERE, null, ex);
}
catch(IOException ex)
{
Logger.getLogger(MyExternalizable.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Di sini jika Anda mengomentari konstruktor default, maka kode tersebut akan membuang pengecualian di bawah ini:
java.io.InvalidClassException: javaserialization.MyExternalizable;
javaserialization.MyExternalizable; no valid constructor.
Kita dapat mengamati bahwa kata sandi adalah informasi sensitif, jadi saya tidak membuat serialisasi dalam metode writeExternal (ObjectOutput oo) dan tidak menetapkan nilai yang sama di readExternal (ObjectInput oi). Itulah fleksibilitas yang disediakan oleh Externalizable.
Output dari kode di atas adalah seperti di bawah ini:
userName: nikki passWord: student001 roll: 20
***********************************************************************
userName: nikki passWord: null roll: 20
Kita dapat mengamati karena kita tidak menetapkan nilai passWord jadi nol.
Hal yang sama juga dapat dicapai dengan mendeklarasikan bidang kata sandi sebagai sementara.
private transient String passWord;
Semoga ini bisa membantu. Saya minta maaf jika saya melakukan kesalahan. Terima kasih.
Perbedaan utama antara Serializable
danExternalizable
Serializable
adalah antarmuka penanda tanpa metode apa pun. Externalizable
antarmuka berisi dua metode: writeExternal()
dan readExternal()
.Serializable
antarmuka yang mengimplementasikan kelas . Programer mendefinisikan proses Serialisasi akan ditendang untuk kelas yang mengimplementasikan Externalizable
antarmuka.Externalizable
antarmuka. Anda dapat mendukung berbagai versi objek Anda. Jika Anda menerapkan Externalizable
, Anda bertanggung jawab untuk membuat cerita bersambung super
kelasSerializable
menggunakan refleksi untuk membangun objek dan tidak memerlukan konstruktor arg. Tetapi Externalizable
menuntut konstruktor tanpa argumen publik.Rujuk ke blog dengan Hitesh Garg
untuk lebih jelasnya.
Serialisasi menggunakan perilaku default tertentu untuk menyimpan dan kemudian membuat ulang objek. Anda dapat menentukan dalam urutan apa atau bagaimana menangani referensi dan struktur data yang kompleks, tetapi pada akhirnya bermuara pada penggunaan perilaku default untuk setiap bidang data primitif.
Eksternalisasi digunakan dalam kasus langka yang Anda benar-benar ingin menyimpan dan membangun kembali objek Anda dengan cara yang sama sekali berbeda dan tanpa menggunakan mekanisme serialisasi default untuk bidang data. Misalnya, bayangkan Anda memiliki skema penyandian dan kompresi unik Anda sendiri.
Obyek Serialization menggunakan antarmuka Serializable dan Externalizable. Objek Java hanya bisa serial. jika suatu kelas atau salah satu dari superclasses mengimplementasikan antarmuka java.io.Serializable atau subinterface-nya, java.io.Externalizable. Sebagian besar kelas java serializable .
NotSerializableException
: packageName.ClassName
«Untuk berpartisipasi dalam Obyek Kelas dalam proses serialisasi, kelas harus mengimplementasikan antarmuka Serializable atau Eksternalisasi.Serialisasi objek menghasilkan aliran dengan informasi tentang kelas Java untuk objek yang disimpan. Untuk objek serializable, informasi yang cukup disimpan untuk mengembalikan objek-objek itu bahkan jika versi implementasi kelas yang berbeda (namun kompatibel) ada. Antarmuka Serializable didefinisikan untuk mengidentifikasi kelas yang mengimplementasikan protokol serializable:
package java.io;
public interface Serializable {};
InvalidClassException
«Dalam proses deserialisasi, jika nilai serialVersionUID kelas lokal berbeda dari kelas pengirim yang bersangkutan. kemudian berakibat konflik sebagai
java.io.InvalidClassException: com.github.objects.User; local class incompatible: stream classdesc serialVersionUID = 5081877, local class serialVersionUID = 50818771
Untuk objek yang dapat dieksternalisasi, hanya identitas kelas objek yang disimpan oleh wadah; kelas harus menyimpan dan mengembalikan konten. Antarmuka yang Eksternalisasi didefinisikan sebagai berikut:
package java.io;
public interface Externalizable extends Serializable
{
public void writeExternal(ObjectOutput out)
throws IOException;
public void readExternal(ObjectInput in)
throws IOException, java.lang.ClassNotFoundException;
}
OptionalDataException
«Kolom HARUS DALAM PESANAN DAN TIPE YANG SAMA saat kami menuliskannya. Jika ada ketidakcocokan jenis dari aliran itu melempar OptionalDataException.
@Override public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt( id );
out.writeUTF( role );
out.writeObject(address);
}
@Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.id = in.readInt();
this.address = (Address) in.readObject();
this.role = in.readUTF();
}
Bidang instance kelas yang ditulis (terbuka) untuk ObjectOutput
mendapatkan serial.
Contoh « mengimplementasikan Serializable
class Role {
String role;
}
class User extends Role implements Serializable {
private static final long serialVersionUID = 5081877L;
Integer id;
Address address;
public User() {
System.out.println("Default Constructor get executed.");
}
public User( String role ) {
this.role = role;
System.out.println("Parametarised Constructor.");
}
}
class Address implements Serializable {
private static final long serialVersionUID = 5081877L;
String country;
}
Contoh « mengimplementasikan Externalizable
class User extends Role implements Externalizable {
Integer id;
Address address;
// mandatory public no-arg constructor
public User() {
System.out.println("Default Constructor get executed.");
}
public User( String role ) {
this.role = role;
System.out.println("Parametarised Constructor.");
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt( id );
out.writeUTF( role );
out.writeObject(address);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.id = in.readInt();
this.address = (Address) in.readObject();
this.role = in.readUTF();
}
}
Contoh
public class CustomClass_Serialization {
static String serFilename = "D:/serializable_CustomClass.ser";
public static void main(String[] args) throws IOException {
Address add = new Address();
add.country = "IND";
User obj = new User("SE");
obj.id = 7;
obj.address = add;
// Serialization
objects_serialize(obj, serFilename);
objects_deserialize(obj, serFilename);
// Externalization
objects_WriteRead_External(obj, serFilename);
}
public static void objects_serialize( User obj, String serFilename ) throws IOException{
FileOutputStream fos = new FileOutputStream( new File( serFilename ) );
ObjectOutputStream objectOut = new ObjectOutputStream( fos );
// java.io.NotSerializableException: com.github.objects.Address
objectOut.writeObject( obj );
objectOut.flush();
objectOut.close();
fos.close();
System.out.println("Data Stored in to a file");
}
public static void objects_deserialize( User obj, String serFilename ) throws IOException{
try {
FileInputStream fis = new FileInputStream( new File( serFilename ) );
ObjectInputStream ois = new ObjectInputStream( fis );
Object readObject;
readObject = ois.readObject();
String calssName = readObject.getClass().getName();
System.out.println("Restoring Class Name : "+ calssName); // InvalidClassException
User user = (User) readObject;
System.out.format("Obj[Id:%d, Role:%s] \n", user.id, user.role);
Address add = (Address) user.address;
System.out.println("Inner Obj : "+ add.country );
ois.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void objects_WriteRead_External( User obj, String serFilename ) throws IOException {
FileOutputStream fos = new FileOutputStream(new File( serFilename ));
ObjectOutputStream objectOut = new ObjectOutputStream( fos );
obj.writeExternal( objectOut );
objectOut.flush();
fos.close();
System.out.println("Data Stored in to a file");
try {
// create a new instance and read the assign the contents from stream.
User user = new User();
FileInputStream fis = new FileInputStream(new File( serFilename ));
ObjectInputStream ois = new ObjectInputStream( fis );
user.readExternal(ois);
System.out.format("Obj[Id:%d, Role:%s] \n", user.id, user.role);
Address add = (Address) user.address;
System.out.println("Inner Obj : "+ add.country );
ois.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
@Lihat
Antarmuka yang Eksternalisasi sebenarnya tidak disediakan untuk mengoptimalkan kinerja proses serialisasi! tetapi untuk menyediakan cara menerapkan pemrosesan kustom Anda sendiri dan menawarkan kontrol penuh atas format dan konten aliran untuk objek dan tipe supernya!
Contohnya adalah penerapan remoting AMF (ActionScript Message Format) untuk mentransfer objek skrip aksi asli melalui jaringan.
https://docs.oracle.com/javase/8/docs/platform/serialization/spec/serialTOC.html
Serialisasi default agak bertele-tele, dan mengasumsikan skenario penggunaan seluas mungkin dari objek berseri, dan karenanya format default (Serializable) menjelaskan aliran yang dihasilkan dengan informasi tentang kelas objek berseri.
Eksternalisasi memberi produsen aliran objek kontrol penuh atas meta-data kelas yang tepat (jika ada) di luar identifikasi kelas yang minimal diperlukan (misalnya namanya). Ini jelas diinginkan dalam situasi tertentu, seperti lingkungan tertutup, di mana produsen aliran objek dan penggunanya (yang mengubah objek dari aliran) dicocokkan, dan metadata tambahan tentang kelas tidak memiliki tujuan dan menurunkan kinerja.
Selain itu (seperti yang ditunjukkan oleh Uri) eksternalisasi juga menyediakan kontrol penuh atas penyandian data dalam aliran yang sesuai dengan tipe Java. Sebagai contoh (dibuat-buat), Anda mungkin ingin merekam boolean true sebagai 'Y' dan false sebagai 'N'. Eksternalisasi memungkinkan Anda melakukan itu.
Saat mempertimbangkan opsi untuk meningkatkan kinerja, jangan lupa serialisasi khusus. Anda dapat membiarkan Java melakukan apa yang dilakukannya dengan baik, atau setidaknya cukup baik, gratis , dan memberikan dukungan khusus untuk apa yang dilakukannya dengan buruk. Ini biasanya jauh lebih sedikit kode daripada dukungan penuh eksternalisasi.
Ada begitu banyak perbedaan yang ada antara Serializable dan Externalizable tetapi ketika kita membandingkan perbedaan antara custom Serializable (override writeObject () & readObject ()) dan Externalizable maka kita menemukan bahwa implementasi custom terikat erat dengan kelas ObjectOutputStream di mana seperti dalam kasus Externalizable, kita sendiri menyediakan implementasi ObjectOutput yang mungkin kelas ObjectOutputStream atau bisa juga yang lain seperti org.apache.mina.filter.codec.serialization.ObjectSerializationOutputStream
Dalam hal antarmuka Externalizable
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(key);
out.writeUTF(value);
out.writeObject(emp);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.key = in.readUTF();
this.value = in.readUTF();
this.emp = (Employee) in.readObject();
}
**In case of Serializable interface**
/*
We can comment below two method and use default serialization process as well
Sequence of class attributes in read and write methods MUST BE same.
// below will not work it will not work .
// Exception = java.io.StreamCorruptedException: invalid type code: 00\
private void writeObject(java.io.ObjectOutput stream)
*/
private void writeObject(java.io.ObjectOutputStream Outstream)
throws IOException {
System.out.println("from writeObject()");
/* We can define custom validation or business rules inside read/write methods.
This way our validation methods will be automatically
called by JVM, immediately after default serialization
and deserialization process
happens.
checkTestInfo();
*/
stream.writeUTF(name);
stream.writeInt(age);
stream.writeObject(salary);
stream.writeObject(address);
}
private void readObject(java.io.ObjectInputStream Instream)
throws IOException, ClassNotFoundException {
System.out.println("from readObject()");
name = (String) stream.readUTF();
age = stream.readInt();
salary = (BigDecimal) stream.readObject();
address = (Address) stream.readObject();
// validateTestInfo();
}
Saya telah menambahkan kode sampel untuk menjelaskan lebih baik. silakan periksa objek objek Externalizable. Ini tidak terikat dengan implementasi apa pun secara langsung.
Sedangkan Outstream / Instream mengikat erat ke kelas. Kita dapat memperluas ObjectOutputStream / ObjectInputStream tetapi akan sedikit sulit untuk digunakan.
Pada dasarnya, Serializable
adalah antarmuka penanda yang menyiratkan bahwa suatu kelas aman untuk serialisasi dan JVM menentukan bagaimana itu serial. Externalizable
berisi 2 metode, readExternal
dan writeExternal
. Externalizable
memungkinkan pelaksana untuk memutuskan bagaimana suatu objek diserialisasi, Serializable
sedangkan serialisasi objek dengan cara default.
Beberapa perbedaan:
Untuk Serialisasi tidak diperlukan konstruktor default kelas itu karena Objek karena JVM membangun yang sama dengan bantuan API Refleksi. Dalam kasus kontruktor Eksternalisasi tanpa arg diperlukan, karena kontrol ada di tangan program dan kemudian menetapkan data deserialized ke objek melalui setter.
Dalam serialisasi jika pengguna ingin melewatkan properti tertentu untuk diserialisasi maka harus menandai properti itu sebagai sementara, sebaliknya tidak diperlukan untuk Eksternalisasi.
Ketika dukungan kompatibilitas mundur diharapkan untuk kelas apa pun maka disarankan untuk pergi dengan Externalizable. Serialisasi mendukung defaultObject bertahan dan jika struktur objek rusak maka akan menyebabkan masalah saat deserializing.