자바에서 인스턴스화 된 객체를 디스크에 영속적으로 저장하거나, 네트워크를 통해 다른 서버로 보내기 위해서 직렬화라는 것을 사용한다.
다음과 같은 Plant Class가 있고, 이를 저장하려고 한다.
package com.example.SavePlant;
public class Plant {
String name;
transient Integer year; // 직렬화시 제외하고 싶은 데이터
String type;
public Plant(String name, Integer year, String type) {
this.name = name;
this.year = year;
this.type = type;
}
@Override
public String toString() {
return "[name : " + this.name + "] [year: " + this.year + "] [type : " + this.type + "]";
}
... 다른 메서드는 생략
}
package com.example.SavePlant;
import com.example.SavePlant.Plant;
import java.io.*;
import java.util.ArrayList;
public class SavePlant {
public static void main(String[] args) throws IOException, ClassNotFoundException {
String fileName = "sj.ser";
// 영속화를 위한 IO Stream 열기
FileOutputStream fo = new FileOutputStream(fileName);
BufferedOutputStream bo = new BufferedOutputStream(fo);
ObjectOutputStream out = new ObjectOutputStream(bo);
// 테스트 데이터들
Plant firstPlant = new Plant("식물1", 1, "타입1");
Plant secondPlant = new Plant("식물2", 2, "타입1");
Plant thirdPlant = new Plant("식물3", 3, "타입1");
ArrayList al = new ArrayList();
al.add(firstPlant);
al.add(secondPlant);
al.add(thirdPlant);
out.writeObject(al);
out.close();
bo.close();
fo.close();
// 역직렬화
FileInputStream fi = new FileInputStream(fileName);
BufferedInputStream bi = new BufferedInputStream(fi);
ObjectInputStream in = new ObjectInputStream(bi);
ArrayList<Plant> list = (ArrayList)in.readObject();
Plant[] array = list.toArray(new Plant[list.size()]);
for(Plant plant : array)
System.out.println(plant.toString());
in.close();
bi.close();
fi.close();
}
}
IO를 위한 스트림을 열었고, writeObject를 통해 올바르게 객체를 적었다고 생각하지만 위 코드는 아래와 같은 에러를 띄운다.
위 에러 메시지의 코드를 타고 가다보면 에러를 발생시키는 아래 코드를 볼 수 있다.
즉, Stream을 하려는 객체가 Serializable 마커 인터페이스를 붙이고있지 않아서 발생한다는 것을 알 수 있다.
에러를 해결하기 위해선 아래와 같이 Plant 클래스에 Serializable 마커 인터페이스를 붙여주면 된다.
package com.example.SavePlant;
import java.io.Serializable;
public class Plant implements Serializable {
String name;
transient Integer year; // 직렬화시 제외
String type;
public Plant(String name, Integer year, String type) {
this.name = name;
this.year = year;
this.type = type;
}
@Override
public String toString() {
return "[name : " + this.name + "] [year: " + this.year + "] [type : " + this.type + "]";
}
}
Serializable을 붙이고 난 뒤에 실행하면 아래와 같이 정상적으로 실행된다.
위와 같이 trasient를 붙인 멤버에 대해서는 직렬화를 하지 않아서, 역직렬화시 null로 출력이 되는 것을 알 수 있다.