Статьи

Externalizable в Java

Прежде чем разбираться с интерфейсом Externalizable, вам необходимо иметь представление о сериализации. Вы можете прочитать больше о сериализации в сериализации в Java .

Java предоставляет механизм, называемый сериализацией, для сохранения Java-объектов в форме упорядоченных или последовательных байтов, которые включают в себя данные объекта, а также информацию о типе объекта и типах данных, хранящихся в объекте.

Externalizable:

Как следует из названия, он выполняет внешнюю сериализацию. Если вы хотите настроить механизм сериализации, вы можете использовать его. Он использует собственный письменный механизм для выполнения маршалинга и демаршаллинга объектов. Интерфейс Externalizable расширяет интерфейс Serializable. Если вы реализуете этот интерфейс, вам нужно переопределить следующие методы.

01
02
03
04
05
06
07
08
09
10
11
@Override
    public void readExternal(ObjectInput arg0) throws IOException,
 
            ClassNotFoundException {
 
    }
 
    @Override
    public void writeExternal(ObjectOutput arg0) throws IOException {
 
    }

Теперь давайте посмотрим, как происходит сериализация:

На стороне отправителя:

JVM проверяет, реализует ли класс externalizable или нет. Если он затем сериализует объект с помощью метода writeExternal (). Если он не реализует externalizable, но реализует сериализуемый, объект сериализуется с помощью ObjectOutputStream.

На стороне получателя:

Когда объект восстанавливается и он доступен для внешнего использования, экземпляр создается без конструктора args и вызывается readExternal. Если это не внешний объект, а сериализуемый, объект восстанавливается с помощью ObjectInputStream.

Давайте начнем с примера, такого же, как мы использовали в сериализации в Java .

Создайте Employee.java в src-> org.arpit.javapostsforlearning

Employee.java:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package org.arpit.javapostsforlearning;
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, если вы реализуете externalizable.

Создайте ExternalizableMain.java в org.arpit.javapostsforlearning.

ExternalizableMain.java:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package org.arpit.javapostsforlearning;
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. Вы получите следующий вывод

1
2
3
Deserialized Employee...
Emp id: 101
Name: Arpit

Если у вас уже есть сериализуемый, зачем вам вообще нужен внешний доступ !!

  • Когда вы сериализуете любой объект, используя serializable, кроме полей, все объекты, которые принадлежат карте объектов и могут быть достигнуты с помощью переменной экземпляра, также будут сериализованы. Например:
    • Если у вас есть класс Employee, а его суперкласс — person, он будет сериализовать все объекты суперкласса (например, person), пока не достигнет класса «Object».
    • Точно так же, если у Employee есть переменная экземпляра класса адреса, он также сериализует всю карту объекта адреса.

Вы действительно хотите столько накладных расходов, когда все, что вы хотите сериализовать, это employeeId и employeeName

  • JVM использует отражение, когда вы используете serializable, что довольно медленно.
  • При сериализации информация о описании класса, которая включает описание его суперкласса и переменную экземпляра, связанную с этим классом, также сохраняется в потоке. Снова это также проблема производительности

Наследование в экстернализации:

Теперь мы увидим, как наследование влияет на экстернализацию. Так что может быть несколько случаев, вне зависимости от того, является ли суперкласс экстернализуемым или нет. Если нет, то как вы с этим справитесь и как это работает.

Мы создадим Person.java, который будет суперклассом Employee.

PersonEmployeeSerialization

Случай 1. Что если суперкласс не реализует Externalizable:

Если суперкласс не реализует externalizable, вам нужно сериализовать поля суперкласса в подклассе, который реализует Externalizable.

Person.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package org.arpit.javapostsforlearning;
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;
 }
 
}

Создать Employee.java в org.arpit.javapostsforlearning

Employee.java:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package org.arpit.javapostsforlearning;
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();
 
}
}

Создайте ExternalizableMain.java в org.arpit.javapostsforlearning.

ExternalizableMain.java:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package org.arpit.javapostsforlearning;
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","Indian");
  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. Вы получите следующий вывод:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Employee:Constructor
Before serializing
Emp id: 101
Name: Arpit
Department: CS
Nationality: Indian
************
Serializing
************
Deserializing
Person:Constructor
After serializing
Emp id: 101
Name: Arpit
Department: CS
Nationality: Indian

Случай 2. Что если суперкласс реализует Externalizable:

Если суперкласс реализует externalizable, он также будет иметь методы readExternal () и writeExternal (), поэтому он будет сериализовать свои собственные поля в этих методах.

Person.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package org.arpit.javapostsforlearning;
 
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();
 
 }
 
}

Создать Employee.java в org.arpit.javapostsforlearning

Employee.java:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package org.arpit.javapostsforlearning;
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();
 
 }
}

Создайте ExternalizableMain.java в org.arpit.javapostsforlearning.

ExternalizableMain.java:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package org.arpit.javapostsforlearning;
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","Indian");
  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. Вы получите следующий вывод:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Employee:Constructor
Before serializing
Emp id: 101
Name: Arpit
Department: CS
Nationality: Indian
************
Serializing
************
Deserializing
Person:Constructor
After serializing
Emp id: 101
Name: Arpit
Department: CS
Nationality: Indian

В этом примере, поскольку класс Person хранит и восстанавливает свои поля в своих собственных методах writeExternal и readExternal, вам не нужно сохранять / восстанавливать поля суперкласса в подклассе, но если вы внимательно наблюдаете методы writeExternal и readExternal класса Employee, вы будете обнаружите, что вам все еще нужно сначала вызвать методы super.xxxx (), которые подтверждают оператор, который внешний объект должен также координировать со своим супертипом, чтобы сохранить и восстановить его состояние.

Недостатки Externalizable:

  • Если вы вносите какие-либо изменения в определение своего класса, вам необходимо поддерживать writeExternal () и readExternal соответственно.
  • Как мы видели в примере, объект Sub-класса должен координироваться со своим суперклассом, чтобы сохранить и сохранить его состояние (путем вызова метода super.xxxx () из подкласса)