Прежде чем разбираться с интерфейсом 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: 101Name: Arpit |
Если у вас уже есть сериализуемый, зачем вам вообще нужен внешний доступ !!
- Когда вы сериализуете любой объект, используя serializable, кроме полей, все объекты, которые принадлежат карте объектов и могут быть достигнуты с помощью переменной экземпляра, также будут сериализованы. Например:
- Если у вас есть класс Employee, а его суперкласс — person, он будет сериализовать все объекты суперкласса (например, person), пока не достигнет класса «Object».
- Точно так же, если у Employee есть переменная экземпляра класса адреса, он также сериализует всю карту объекта адреса.
Вы действительно хотите столько накладных расходов, когда все, что вы хотите сериализовать, это employeeId и employeeName
- JVM использует отражение, когда вы используете serializable, что довольно медленно.
- При сериализации информация о описании класса, которая включает описание его суперкласса и переменную экземпляра, связанную с этим классом, также сохраняется в потоке. Снова это также проблема производительности
Наследование в экстернализации:
Теперь мы увидим, как наследование влияет на экстернализацию. Так что может быть несколько случаев, вне зависимости от того, является ли суперкласс экстернализуемым или нет. Если нет, то как вы с этим справитесь и как это работает.
Мы создадим Person.java, который будет суперклассом Employee.
Случай 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; }@Overridepublic 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);}@Overridepublic 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:ConstructorBefore serializingEmp id: 101Name: ArpitDepartment: CSNationality: Indian************Serializing************DeserializingPerson:ConstructorAfter serializingEmp id: 101Name: ArpitDepartment: CSNationality: 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:ConstructorBefore serializingEmp id: 101Name: ArpitDepartment: CSNationality: Indian************Serializing************DeserializingPerson:ConstructorAfter serializingEmp id: 101Name: ArpitDepartment: CSNationality: Indian |
В этом примере, поскольку класс Person хранит и восстанавливает свои поля в своих собственных методах writeExternal и readExternal, вам не нужно сохранять / восстанавливать поля суперкласса в подклассе, но если вы внимательно наблюдаете методы writeExternal и readExternal класса Employee, вы будете обнаружите, что вам все еще нужно сначала вызвать методы super.xxxx (), которые подтверждают оператор, который внешний объект должен также координировать со своим супертипом, чтобы сохранить и восстановить его состояние.
Недостатки Externalizable:
- Если вы вносите какие-либо изменения в определение своего класса, вам необходимо поддерживать writeExternal () и readExternal соответственно.
- Как мы видели в примере, объект Sub-класса должен координироваться со своим суперклассом, чтобы сохранить и сохранить его состояние (путем вызова метода super.xxxx () из подкласса)
