Arasındaki fark nedir Serializable
ve Externalizable
Java?
Arasındaki fark nedir Serializable
ve Externalizable
Java?
Yanıtlar:
Diğer cevaplara eklemek için, uygulayarak java.io.Serializable
, sınıfınızdaki nesneler için "otomatik" serileştirme yeteneği elde edersiniz. Başka bir mantık uygulamaya gerek yok, sadece işe yarayacak. Java çalışma zamanı, nesnelerinizi nasıl marshal ve unmarshal yapacağınızı anlamak için yansıma kullanır.
Java'nın önceki sürümlerinde, yansıma çok yavaştı ve bu nedenle büyük nesne grafiklerinin (örneğin, istemci-sunucu RMI uygulamalarında) serileştirilmesi biraz performans sorunuydu. Bu durumla başa çıkmak için, java.io.Externalizable
ara java.io.Serializable
sıra ve sıradan olmayan işlevleri yerine getirmek için özel yazılı mekanizmalara sahip olan arayüz sağlanmıştır ( sınıfınıza uygulamanız readExternal
ve writeExternal
yöntemleriniz gerekir ). Bu size yansıma performansı darboğazını aşmanın yollarını sunar.
Java'nın son sürümlerinde (kesinlikle 1.3), yansıma performansı eskisinden çok daha iyi ve bu yüzden bu çok daha az sorun. Externalizable
Modern bir JVM ile anlamlı bir fayda elde etmek için zorlanacağınızdan şüpheleniyorum .
Ayrıca, yerleşik Java serileştirme mekanizması tek değil, JBoss Serialization gibi oldukça hızlı olan ve varsayılan için bir bırakma yedeği olan üçüncü taraf yedekleri alabilirsiniz.
Büyük bir dezavantajı, Externalizable
bu mantığı kendiniz tutmanız gerektiğidir - sınıfınıza bir alan ekler, kaldırır veya değiştirirseniz, bunu hesaba katmak için writeExternal
/ readExternal
yöntemlerinizi değiştirmeniz gerekir.
Özetle, Externalizable
Java 1.1 gününün bir kalıntısıdır. Artık buna gerçekten gerek yok.
Externalizable
yardımcı olur .
Externalizable
boş alanlara veya yer tutucu nesnelere sahip diziler çıkarmak istemediğimden, bana çok daha uygun olduğunu söylemeliyim , ayrıca açık arabirimle mirasımı işleyebilirsin, yani senkronize edilmiş altım -class kolayca çağrı etrafında kilitleme ekleyebilirsiniz writeExternal()
. Yani evet, Dışsallaştırılabilir, kesinlikle büyük veya karmaşık nesneler için hala çok alakalı.
Serileştirme, nesneyi depolamak ve daha sonra yeniden oluşturmak için varsayılan işlevsellik sağlar. Depolanacak nesnelerin tüm grafiğini tanımlamak için ayrıntılı format kullanır, örneğin bir LinkedList'iniz olduğunu ve aşağıdaki gibi kodladığınızı varsayalım, o zaman varsayılan serileştirme, bağlantılı ve serileştirilecek tüm nesneleri keşfedecektir. Varsayılan serileştirmede nesne, yapıcı çağrısı olmadan tamamen depolanmış bitlerinden oluşturulur.
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("/Users/Desktop/files/temp.txt"));
oos.writeObject(linkedListHead); //writing head of linked list
oos.close();
Ancak kısıtlı serileştirme yapmak veya nesnenizin bir bölümünün serileştirilmesini istemiyorsanız Externalizable'ı kullanın. Externalizable arabirimi Serializable arabirimini genişletir ve iki yöntem ekler: writeExternal () ve readExternal (). Bunlar serileştirme veya serileştirme sırasında otomatik olarak çağrılır. Externalizable ile çalışırken, varsayılan kurucunun herkese açık olması gerektiğini unutmamalıyız, aksi takdirde kod istisna atar. Lütfen aşağıdaki kodu takip edin:
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);
}
}
}
Burada varsayılan yapıcıya yorum yaparsanız, kod istisnanın altına atılacaktır:
java.io.InvalidClassException: javaserialization.MyExternalizable;
javaserialization.MyExternalizable; no valid constructor.
Parola hassas bilgi olarak gözlemleyebiliriz, bu yüzden writeExternal (ObjectOutput oo) yönteminde seri hale getirmiyorum ve readExternal (ObjectInput oi) içinde aynı değeri ayarlamıyorum. Externalizable tarafından sağlanan esneklik budur.
Yukarıdaki kodun çıktısı aşağıdaki gibidir:
userName: nikki passWord: student001 roll: 20
***********************************************************************
userName: nikki passWord: null roll: 20
PassWord'un değerini ayarlamadığımız için gözlemleyebiliriz, bu yüzden null.
Aynı şey, şifre alanının geçici olarak bildirilmesiyle de elde edilebilir.
private transient String passWord;
Umarım yardımcı olur. Herhangi bir hata yaptıysam özür dilerim. Teşekkürler.
Serializable
Ve arasındaki temel farklarExternalizable
Serializable
herhangi bir yöntem olmadan marker arayüzüdür. Externalizable
arayüz iki yöntem içerir: writeExternal()
ve readExternal()
.Serializable
Arayüzü uygulayan sınıflar için varsayılan Serileştirme süreci başlatılacaktır . Programcı tanımlı serileştirme süreci Externalizable
arabirimi uygulayan sınıflar için devreye girecektir.Externalizable
arabirim ile tam kontrole sahip olabilirsiniz . Nesnenizin farklı sürümlerini destekleyebilirsiniz. Eğer uygularsanız Externalizable
, bu serialize sizin sorumluluğunuzdur super
sınıfınSerializable
nesneyi oluşturmak için yansıma kullanır ve arg yapıcısı gerektirmez. Ancak Externalizable
kamuya tartışmasız yapıcı talep ediyor.Bakınız blog tarafından Hitesh Garg
daha fazla ayrıntı için.
Serileştirme, nesneyi depolamak ve daha sonra yeniden oluşturmak için belirli varsayılan davranışları kullanır. Referansları ve karmaşık veri yapılarını hangi sırada veya nasıl işleyeceğinizi belirtebilirsiniz, ancak sonunda her ilkel veri alanı için varsayılan davranışı kullanmaya gelir.
Haricilaştırma, nesnenizi tamamen farklı bir şekilde depolamak ve yeniden oluşturmak istediğiniz nadir durumlarda ve veri alanları için varsayılan serileştirme mekanizmalarını kullanmadan kullanılır. Örneğin, kendi benzersiz kodlama ve sıkıştırma düzeninize sahip olduğunuzu düşünün.
Nesne Dizileştirme, Serileştirilebilir ve Dışsallaştırılabilir arabirimleri kullanır. Bir Java nesnesi yalnızca serileştirilebilir. bir sınıf veya üst sınıflarından herhangi biri java.io.Serializable arabirimini veya alt arabirimini java.io.Externalizable uygularsa. Java sınıfının çoğu serileştirilebilir .
NotSerializableException
: packageName.ClassName
«Bir Sınıf Nesnesini serileştirme sürecine katılmak için, sınıfın Seri veya Harici olarak kullanılabilen arabirim uygulaması gerekir.Nesne Dizileştirme, kaydedilmekte olan nesneler için Java sınıfları hakkında bilgi içeren bir akış oluşturur. Serileştirilebilir nesneler için, sınıfın uygulanmasının farklı (ancak uyumlu) bir sürümü mevcut olsa bile bu nesneleri geri yüklemek için yeterli bilgi tutulur. Serileştirilebilir arayüz, serileştirilebilir protokolü uygulayan sınıfları tanımlamak için tanımlanmıştır:
package java.io;
public interface Serializable {};
InvalidClassException
« Serisini kaldırma işleminde, yerel sınıf serialVersionUID değeri karşılık gelen gönderenin sınıfından farklıysa . sonuç şu şekilde çelişkilidir:
java.io.InvalidClassException: com.github.objects.User; local class incompatible: stream classdesc serialVersionUID = 5081877, local class serialVersionUID = 50818771
Haricilaştırılabilir nesneler için, yalnızca nesne sınıfının kimliği kapsayıcı tarafından kaydedilir; sınıf içeriği kaydetmeli ve geri yüklemelidir. Haricilaştırılabilir arayüz aşağıdaki gibi tanımlanır:
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
« Yazdığımız gibi alanlar AYNI SİPARİŞ VE TÜRDE OLMALIDIR . Akıştan herhangi bir tür uyuşmazlığı varsa OptionalDataException öğesini atar.
@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();
}
Serileştirilmek için yazılan (pozlanan) sınıfın örnek alanları ObjectOutput
.
Örnek « Serializable uygular
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;
}
Örnek «, Haricilaştırılabilir
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();
}
}
Misal
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();
}
}
}
@görmek
Dışsallaştırılabilir arayüz, serileştirme işlemi performansını optimize etmek için gerçekte sağlanmadı! ancak kendi özel işlemlerinizi gerçekleştirmenin yollarını sağlamak ve bir nesne ve onun süper türleri için akışın biçimi ve içeriği üzerinde tam kontrol sağlamak!
Bunun örnekleri, yerel eylem komut dosyası nesnelerini ağ üzerinden aktarmak için AMF (ActionScript İleti Biçimi) uzaktan uygulamasının uygulanmasıdır.
https://docs.oracle.com/javase/8/docs/platform/serialization/spec/serialTOC.html
Varsayılan serileştirme biraz ayrıntılıdır ve serileştirilmiş nesnenin mümkün olan en geniş kullanım senaryosunu varsayar ve buna göre varsayılan biçim (Serileştirilebilir), serileştirilmiş nesnenin sınıfı hakkında bilgi ile sonuç akışına açıklama ekler.
Dışsallaştırma, nesne akışı üreticisine, sınıfın gerekli minimum tanımlamasının (örneğin adı) kesin sınıf meta verileri (varsa) üzerinde tam kontrol sağlar. Bu, nesne akışı üreticisi ve tüketicisinin (nesneyi akıştan ayıran) eşleştiği ve sınıf hakkındaki ek meta verilerin hiçbir amaca hizmet etmediği ve performansı düşürdüğü kapalı ortamlar gibi belirli durumlarda açıkça istenir.
Ek olarak (Uri'nin işaret ettiği gibi) haricilaştırma, Java türlerine karşılık gelen akıştaki verilerin kodlanması üzerinde tam kontrol sağlar. (Tutarlı) bir örnek için, boole true değerini 'Y' ve false 'N' olarak kaydetmek isteyebilirsiniz. Dışsallaştırma bunu yapmanızı sağlar.
Performansı artırma seçeneklerini göz önünde bulundururken, özel serileştirmeyi unutmayın. Java'nın iyi veya en azından yeterince iyi bir şekilde ücretsiz yapmasına izin verebilir ve kötü bir şekilde yaptığı şey için özel destek sağlayabilirsiniz. Bu genellikle tam Haricileştirilebilir desteğe göre çok daha az koddur.
Serializable ve Externalizable arasında çok fazla fark var, ancak özel Serializable (geçersiz kılınan writeObject () & readObject ()) ve Externalizable arasındaki farkı karşılaştırdığımızda, özel uygulamanın ObjectOutputStream sınıfı ile sıkı bir şekilde bağlandığını görüyoruz. ObjectOutputStream sınıfı olabilecek ya da org.apache.mina.filter.codec.serialization.ObjectSerializationOutputStream gibi başka bir nesne olabilen bir ObjectOutput uygulaması sağlayın
Haricilaştırılabilir arayüz durumunda
@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();
}
Daha iyi açıklamak için örnek kod ekledim. Lütfen Haricileştirilebilir nesne giriş / çıkış nesnesini kontrol edin. Bunlar doğrudan herhangi bir uygulamaya bağlı değildir.
Outstream / Instream olarak sınıflara sıkıca bağlanır. ObjectOutputStream / ObjectInputStream öğesini genişletebiliriz, ancak kullanımı biraz zor olacaktır.
Temel olarak, Serializable
bir sınıfın serileştirme için güvenli olduğunu ve JVM'nin serileştirileceğini nasıl belirlediğini gösteren bir işaretleyici arabirimidir. Externalizable
2 yöntem içerir readExternal
ve writeExternal
. Externalizable
gibi bir nesne seri hale nasıl karar uygulayıcısı, izin verir Serializable
serializes varsayılan yolu nesneleri.
Bazı farklılıklar:
Serileştirme için, bu sınıfın varsayılan yapıcısına gerek yoktur çünkü Object JVM, Reflection API'sinin yardımıyla aynı şeyi yapılandırır. Herhangi bir arg olmayan dışsallaştırma yapıcısı gerektiğinde, kontrol programmar'ın elindedir ve daha sonra, serileştirilmiş verileri ayarlayıcılar aracılığıyla nesneye atar.
Serileştirmede, kullanıcı serileştirilecek belirli özellikleri atlamak istiyorsa, bu özellikleri geçici olarak işaretlemek zorundaysa, Haricilaştırma için bunun tersi gerekli değildir.
Herhangi bir sınıf için geriye dönük uyumluluk desteği beklendiğinde, Dışsallaştırılabilir ile devam etmeniz önerilir. Serileştirme defaultObject sürekliliğini destekler ve nesne yapısı bozulursa, serileştirmeyi kaldırırken soruna neden olur.