Java中的Externalizable

时间:2020-02-23 14:34:09  来源:igfitidea点击:

在理解外部化接口之前,我们需要了解序列化。
我们可以在Java中序列化的序列化了解更多有关序列化的更多信息。

Java提供称为序列化的机制,以持续以订购或者字节序列的形式持续java对象,该对象包括对象数据以及有关对象类型的信息和存储在对象中的数据类型。

Externalizable:

AS名称建议它在序列化外部化。
如果我们想要自定义序列化机制,则可以使用它。
它使用自定义书面机制来执行对象的Marshalling和Unmarshalling.ExteLizable接口扩展了可序列化接口。
如果实现此界面,则需要覆盖以下方法。

@Override
    public void readExternal(ObjectInput arg0) throws IOException,
 
            ClassNotFoundException {
 
    }
 
    @Override
    public void writeExternal(ObjectOutput arg0) throws IOException {
 
    }

现在让我们看看如何序列化如何发生:

在发件人侧:JVM检查类是否实例化外部化或者否。
如果它确实使用writeexternal()方法序列化对象。
如果它不实现外部化但实现序列化,则使用ObjectOutputStream序列化。

在接收器侧:重建对象并且它是外部化时,使用NO args构造函数创建实例,并被调用readExternal。
如果它不是外部化但可序列化,则使用ObjectInputStream重建对象。

让我们从Java中的序列化中使用相同的示例开始。

在src-> org.arpit.onitread中创建employee.java.java

Employee.java:

package org.arpit.theitroad;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
 
public class Employee implements Externalizable{ 
 
 int employeeId;
 String employeeName;
 String department;
 String nationality;
 
 public Employee()
 {
 
 }
 public int getEmployeeId() {
  return employeeId;
 }
 public void setEmployeeId(int employeeId) {
  this.employeeId = employeeId;
 }
 public String getEmployeeName() {
  return employeeName;
 }
 public void setEmployeeName(String employeeName) {
  this.employeeName = employeeName;
 }
 public String getDepartment() {
  return department;
 }
 public void setDepartment(String department) {
  this.department = department;
 }
 
 
 public String getNationality() {
  return nationality;
 }
 public void setNationality(String nationality) {
  this.nationality = nationality;
 }
 @Override
 public void readExternal(ObjectInput in) throws IOException,
 ClassNotFoundException {
  employeeId=in.readInt();
  employeeName=(String) in.readObject();
  
 }
 @Override
 public void writeExternal(ObjectOutput out) throws IOException {
 
  out.writeInt(employeeId);
  out.writeObject(employeeName);
 }
}

如果我们实现了外部化,则必须没有args contructor。

在org.arpit.theitroad中创建Externalizablemain.java

Exterfactizablemain.java:

package org.arpit.theitroad;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
 
public class ExternalizableMain {
 /**
  * @author Arpit Mandliya
  */
 public static void main(String[] args) {
 
  Employee emp = new Employee();
  emp.setEmployeeId(101);
  emp.setEmployeeName("Arpit");
  emp.setDepartment("CS");
  
  //Serialize
  try
  {
   FileOutputStream fileOut = new FileOutputStream("employee.ser");
   ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
   outStream.writeObject(emp);
   outStream.close();
   fileOut.close();
  }catch(IOException i)
  {
   i.printStackTrace();
  }
 
  //Deserialize
  emp = null;
  try
  {
   FileInputStream fileIn =new FileInputStream("employee.ser");
   ObjectInputStream in = new ObjectInputStream(fileIn);
   emp = (Employee) in.readObject();
   in.close();
   fileIn.close();
  }catch(IOException i)
  {
   i.printStackTrace();
   return;
  }catch(ClassNotFoundException c)
  {
   System.out.println("Employee class not found");
   c.printStackTrace();
   return;
  }
  System.out.println("Deserialized Employee...");
  System.out.println("Emp id: " + emp.getEmployeeId());
  System.out.println("Name: " + emp.getEmployeeName());
 
 }
}

运行 :

当我们运行ExternalizableMain.java.you将获取以下输出

Deserialized Employee...
Emp id: 101
Name: Arpit

如果我们已经有序列化,为什么我们根本需要外部化!!:

  • 当我们使用Serializable序列化任何对象,除字段外,也将序列化属于Object映射的所有对象,并且可以使用实例变量达到该对象。例如:
  • 如果我们有员工程序,并且其超类是人,那么它将序列化所有超类对象(如人),直到它到达"对象"类。
  • 同样,如果员工有地址类的实例变量,那么它也将序列化地址的整个对象映射。

当我们想要序列化的所有内容都是员工和雇佣者的时,你真的想要这么多的开销吗?

  • 使用序列化时,JVM使用反射,这非常慢。
  • 在序列化时,有关类描述的信息,其中包含与该类关联的超类和实例变量的描述也将存储在Stream中.Again这也是一个性能问题

Externalization中继承:

现在我们将看到继承的影响如何影响外部化。
所以可以有多种程序是否是外部类别的。
如果不是,我们将如何处理它以及如何处理它。
我们将创建Person.java,这将是员工的超类。

案例1:如果超级类没有实现Externalizable:

如果超类不实现外部化,则需要在子类中序列化外包类的外包类,该字段实现外部化。

person.java.

package org.arpit.theitroad;
public class Person {
 
 String name="default";
 String nationality;
 
 public Person()
 {
  System.out.println("Person:Constructor");
 }
 
 public Person(String name, String nationality) {
  super();
  this.name = name;
  this.nationality = nationality;
 }
 
 public String getName() {
  return name;
 }
 
 public void setName(String name) {
  this.name = name;
 }
 
 public String getNationality() {
  return nationality;
 }
 
 public void setNationality(String nationality) {
  this.nationality = nationality;
 }
 
}

在org.arpit.theitroad employee.java中创建employee.java.java:

package org.arpit.theitroad;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
;
 
public class Employee extends Person implements Externalizable{ 
 
 int employeeId;
 String department;
 
 public Employee()
 {
  
 }
 public Employee(int employeeId,String name,String department,String nationality)
 {
  super(name,nationality);
  this.employeeId=employeeId;
  this.department=department;
  System.out.println("Employee:Constructor");
 }
 
 public int getEmployeeId() {
  return employeeId;
 }
 public void setEmployeeId(int employeeId) {
  this.employeeId = employeeId;
 }
 
 public String getDepartment() {
  return department;
 }
 public void setDepartment(String department) {
  this.department = department;
 }
 
 
 
@Override
public void writeExternal(ObjectOutput out) throws IOException {
 
 /*since superclass does not implement externalizable, you need to serialize super class field in this class itself*/
 //superclass fields
 out.writeObject(name);
 out.writeObject(nationality);
 
 //its own fields
 out.writeInt(employeeId);
 out.writeObject(department);
}
 
@Override
public void readExternal(ObjectInput in) throws IOException,
  ClassNotFoundException {
 /*since superclass does not implement externalizable, you need to deserialize super class field in this class itself*/
 //superclass fields
 name=(String) in.readObject();
 nationality=(String) in.readObject();
 
 //its own fields
 employeeId=in.readInt();
 department=(String) in.readObject();
 
}
}

在org.arpit.theitroad中创建Externalizablemain.java

Exterfactizablemain.java:

package org.arpit.theitroad;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
 
public class ExternalizableMain {
 
 /**
  * @author Arpit Mandliya
  */
 public static void main(String[] args) {
 
  //Serialize
  Employee emp = new Employee(101,"Arpit","CS","Netherlandsn");
  System.out.println("Before serializing");
  System.out.println("Emp id: " + emp.getEmployeeId());
  System.out.println("Name: " + emp.getName());
  System.out.println("Department: " + emp.getDepartment());
  System.out.println("Nationality: " + emp.getNationality());
  System.out.println("");
  System.out.println("Serializing");
  try
  {
   FileOutputStream fileOut = new FileOutputStream("employee.ser");
   ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
   outStream.writeObject(emp);
   outStream.close();
   fileOut.close();
  }catch(IOException i)
  {
   i.printStackTrace();
  }
 
  //Deserialize
  System.out.println("");
  System.out.println("Deserializing");
  emp = null;
  try
  {
   FileInputStream fileIn =new FileInputStream("employee.ser");
   ObjectInputStream in = new ObjectInputStream(fileIn);
   emp = (Employee) in.readObject();
   in.close();
   fileIn.close();
  }catch(IOException i)
  {
   i.printStackTrace();
   return;
  }catch(ClassNotFoundException c)
  {
   System.out.println("Employee class not found");
   c.printStackTrace();
   return;
  }
  System.out.println("After serializing");
  System.out.println("Emp id: " + emp.getEmployeeId());
  System.out.println("Name: " + emp.getName());
  System.out.println("Department: " + emp.getDepartment());
  System.out.println("Nationality: " + emp.getNationality());
 }
}

运行 :

运行ExternalizableMain.java.you将获取以下输出:

Employee:Constructor
Before serializing
Emp id: 101
Name: Arpit
Department: CS
Nationality: Netherlandsn

Serializing

Deserializing
Person:Constructor
After serializing
Emp id: 101
Name: Arpit
Department: CS
Nationality: Netherlandsn

案例2:超级类实现了Externalizable的情况:

如果超类实现了外部化,那么它也将具有readExternal()和writeexternal()方法,因此它将在这些方法中序列化其自己的字段

person.java.

package org.arpit.theitroad;
 
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
 
public class Person implements Externalizable{
 
 String name="default";
 String nationality;
 
 public Person()
 {
  System.out.println("Person:Constructor");
 }
 
 public Person(String name, String nationality) {
  super();
  this.name = name;
  this.nationality = nationality;
 }
 
 public String getName() {
  return name;
 }
 
 public void setName(String name) {
  this.name = name;
 }
 
 public String getNationality() {
  return nationality;
 }
 
 public void setNationality(String nationality) {
  this.nationality = nationality;
 }
 
 
 @Override
 public void writeExternal(ObjectOutput out) throws IOException {
 
  out.writeObject(name);
  out.writeObject(nationality);
 }
 
 @Override
 public void readExternal(ObjectInput in) throws IOException,
 ClassNotFoundException {
  name=(String) in.readObject();
  nationality=(String) in.readObject();
 
 }
 
}

在org.arpit.theitroad employee.java中创建employee.java.java:

package org.arpit.theitroad;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
;
 
public class Employee extends Person implements Externalizable{ 
 
 int employeeId;
 String department;
 
 public Employee()
 {
 
 }
 public Employee(int employeeId,String name,String department,String nationality)
 {
  super(name,nationality);
  this.employeeId=employeeId;
  this.department=department;
  System.out.println("Employee:Constructor");
 }
 
 public int getEmployeeId() {
  return employeeId;
 }
 public void setEmployeeId(int employeeId) {
  this.employeeId = employeeId;
 }
 
 public String getDepartment() {
  return department;
 }
 public void setDepartment(String department) {
  this.department = department;
 }
 
 
 
 @Override
 public void writeExternal(ObjectOutput out) throws IOException {
 
  super.writeExternal(out);
  out.writeInt(employeeId);
  out.writeObject(department);
 }
 
 @Override
 public void readExternal(ObjectInput in) throws IOException,
 ClassNotFoundException {
 
  super.readExternal(in);
  employeeId=in.readInt();
  department=(String) in.readObject();
 
 }
}

在org.arpit.theitroad中创建Externalizablemain.java

Exterfactizablemain.java:

package org.arpit.theitroad;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
 
public class ExternalizableMain {
 
 /**
  * @author Arpit Mandliya
  */
 public static void main(String[] args) {
 
  //Serialize
  Employee emp = new Employee(101,"Arpit","CS","Netherlandsn");
  System.out.println("Before serializing");
  System.out.println("Emp id: " + emp.getEmployeeId());
  System.out.println("Name: " + emp.getName());
  System.out.println("Department: " + emp.getDepartment());
  System.out.println("Nationality: " + emp.getNationality());
  System.out.println("");
  System.out.println("Serializing");
  try
  {
   FileOutputStream fileOut = new FileOutputStream("employee.ser");
   ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
   outStream.writeObject(emp);
   outStream.close();
   fileOut.close();
  }catch(IOException i)
  {
   i.printStackTrace();
  }
 
  //Deserialize
  System.out.println("");
  System.out.println("Deserializing");
  emp = null;
  try
  {
   FileInputStream fileIn =new FileInputStream("employee.ser");
   ObjectInputStream in = new ObjectInputStream(fileIn);
   emp = (Employee) in.readObject();
   in.close();
   fileIn.close();
  }catch(IOException i)
  {
   i.printStackTrace();
   return;
  }catch(ClassNotFoundException c)
  {
   System.out.println("Employee class not found");
   c.printStackTrace();
   return;
  }
  System.out.println("After serializing");
  System.out.println("Emp id: " + emp.getEmployeeId());
  System.out.println("Name: " + emp.getName());
  System.out.println("Department: " + emp.getDepartment());
  System.out.println("Nationality: " + emp.getNationality());
 }
}

运行ExternalizableMain.java.将获取以下输出:

Employee:Constructor
Before serializing
Emp id: 101
Name: Arpit
Department: CS
Nationality: Netherlandsn

Serializing

Deserializing
Person:Constructor
After serializing
Emp id: 101
Name: Arpit
Department: CS
Nationality: Netherlandsn

在此示例中,由于人类类存储并在自己的WriteExternal和ReadExternal方法中恢复其字段,因此我们不需要保存/恢复子类中的超类字段,但如果我们仔细观察员工程序的WriteExternal和ReadExternal方法,我们将发现我们仍然需要首先调用Super.xxx()方法,该方法确认语句的外部化对象还必须与其SuperType协调以保存和恢复其状态。

Externalizable其他说明

  • 如果我们对类定义进行了任何更改,则需要相应地维护Writeexternal()和readexternal。
  • 正如我们在示例中所见,子类对象必须与其超类协调以保存和存储其状态(通过Subclass调用super.xxxx()方法)