[JAVA] Externalizable 인터페이스
Externalizable 인터페이스
Externalizable 인터페이스는 Serializable 인터페이스를 확장한 형태로 세부적인 필드를 직접 제어할 수 있는 트정이 있다. transient 키워드를 사용하여 특정 필드를 제외시키는 것도 가능하지만 좀 더 세부적인 작업이 필요할 때 Externalizable 인터페이스를 사용할 수 있다.
[JAVA/Java IO] - [JAVA] Serializable 과 transient
1. Externalizable 인터페이스
Externalizable 인터페이스를 사용하면 객체 스트림을 통하여 객체를 읽고 쓸 때 내부의 내용을 자유롭게 조작하면서 원하는 내용을 출력할 수 있도록 도와준다. 이를 위해서 이 인터페이스는 Serializable 인터페이스를 확장하고 두 가지 메소드를 추가하였다.
하나는 출력을 위한 writeExternal() 메소드이고 또 하나는 입력을 위한 readExternal() 메소드다.
2. 객체 스트림 직렬화시의 동작
(1) 출력 (직렬화)
- 객체 스트림을 통하여 객체를 출력하는 메소드가 호출되면 가장 먼저 그 객체의 클래스가 Externalizable 인터페이스를 구현했는지 확인한다. 만약 구현했다면 writeExternal() 메소드를 통해서 전송 데이터를 직렬화 한다.
- Externalizable 인터페이스를 구현하지 않았다면 Serializable 인터페이스를 구현했는지 확인한다.
Serializable 인터페이스를 구현했다면 그대로 객체 스트림에 객체 전체를 직렬화 한다.
- Externalizable, Serializable 인터페이스를 구현하지 않았다면 Exception이 발생한다.
(2) 입력 (역직렬화)
- 스트림을 통해 전송받은 객체가 Externalizable 인터페이스를 구현했는지 확인한다. 구현했다면 readExternal() 메소드를 통해서 전송받은 데이터를 순서대로 읽어온다.
- Externalizable 인터페이스를 구현하지 않았다면 Serializable 인터페이스를 통해 객체 전체를 역직렬화 한다.
(3) writeExternal(), readExternal()
- Externalizable 인터페이스를 구현할 때는 writeExtenral()과 readExternal() 메소드를 작성해야 한다.
- Serializable 인터페이스는 모든 변수(transient 제외)를 직렬화하는 반면 Externalizable 인터페이스는 직렬화할 대상을 직접 writeExternal() 메소드에 구현해야 한다. (transient 변수도 직렬화하여 전송할 수 있다.)
- out.writeObject(name); 과 같이 직렬화할 변수 하나하나 writeObject()에 써줘야 한다.
- 스트림을 통해 객체를 받아 역직렬화를 할 때에도 readExternal() 메소드에서 하나하나 받은 데이터를 변수에 넣어줘야 한다.
- in.readObject(); 를 사용하여, writeExternal() 메소드에서 writeObject()에 넣어 준 변수의 순서대로 데이터를 가져온다.
- 따라서 writeExternal()에 직렬화한 변수의 순서와 readObject() 에서 꺼내는 순서가 일치해야한다.
- 이때 형변환을 해야 한다. ex> id = (String)in.readObject();
- writeExternal(), readExternal()의 인자인 ObjectOupt, ObjectInput 객체는 JVM이 자동으로 인자를 설정하여 매핑해 준다.
3. Externalizable 사용 예제
UserClass.java
import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; // 직렬화 한다. public class UserClass implements Externalizable{ private static final long serialVersionUID = 4220461820168818967L; String name; // age 비 전송 transient int age; public UserClass() { } public UserClass(String name, int age){ this.name = name; this.age = age; } // Externalizable 구현으로 인한 직렬화 동작 메소드 public void writeExternal(ObjectOutput out) throws IOException{ out.writeObject(this.name); // 이름이 "제이슨" 이면 값을 80으로 직렬화한다. if(this.name.equals("제이슨")){ out.writeObject(80); }else{ out.writeObject(this.age); } } // Externalizable 구현으로 인한 역직렬화 동작 메소드 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException{ this.name = (String)in.readObject(); this.age = (Integer)in.readObject(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "UserClass [name=" + name + ", age=" + age + "]"; } } |
ObjectStream.java
- UserClass 객체는 Externalizable 인터페이스를 구현하여, writeExternal(), readExternal() 메소드를 통해 직렬화, 역 직렬화시 데이터를 제어할 수 있다.
- writeExternal() 에서 데이터를 writeObject()로 넣어준 순서대로 직렬화가 되며, readExternal()에서 readObject()시 순서대로 데이터를 가져온다.
- Serializable 인터페이스 구현시에는 tradient 를 선언한 변수를 제외한 모든변수를 자동으로 직렬화 하여 전송하지만, Externalizable에서는 전송 데이터를 각각 지정해줘야 하며, tradient 선언이 되어 있어도 전송 된다.
- ObjectStream.java 에서 3개의 UserClass 객체를 생성한 후에 파일에 쓰고, 읽어와 프린트 하여 테스트 한다.
출처: https://hyeonstorage.tistory.com/255?category=578560 [개발이 하고 싶어요]
'JAVA > Java IO' 카테고리의 다른 글
Tomcat에서 발생하는 ClientAbortException (0) | 2021.05.11 |
---|---|
java.io 패키지 (try-with-resources, InputStream, OutputStream, Reader, Writer, Serialization) (0) | 2021.03.19 |
[JAVA] Serializable 과 transient (0) | 2019.08.07 |
[JAVA] serialVersionUID 이란? Warning 해결하기 (0) | 2019.08.07 |
[JAVA] 객체 직렬화 ObjectInputStream / ObjectOutputStream (0) | 2019.08.07 |
[JAVA] I/O Char 와 Encoding (0) | 2019.08.07 |
[JAVA] I/O 입출력 클래스의 종류 (0) | 2019.08.07 |
[JAVA] 문자 Stream : BufferedReader / BufferedWriter (파일 복사 예제) (0) | 2019.08.07 |