전화 상으로만 강아지 A를 설명하고자 한다.
이 때,
강아지 A의 모든 특성을 가진 객체를 생성해서 직렬화한 후
통화 상대방에게 말하면 보다 간단하게 전달 가능하다.
{ "name":"Rex", "age":5, "favourite_food": pedigree_choice_cuts, "favourite_game": fetch_ball, "favourite_hobby": wagging_tail }
즉, 직렬화 & 역직렬화란?
객체(보통 인스턴스를 의미)의 속성과 데이터를 모두 파일로 저장했다가, 필요할 때 다시 객체로 되돌리는 기능
객체를 상태 그대로 저장하고, 필요할 때 다시 생성하여 사용하는 것
객체를 메모리, 데이터베이스, 파일로 옮길 때 사용
다른 서버에서 생성한 객체를 받을 수 있음
// Serializable 인터페이스를 구현한 HashMap 클래스
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
private static final long serialVersionUID = 362498820763181265L;
}
// static final long으로 선언해야 하고, 변수명도 serialVersionUID 로 선언해 주어야 자바에서 인식 가능(구현할 때와 동일하게)
static final long serialVersionUID = 1L;
Serializable 인터페이스를 구현한 후에는 위와 같이 serialVersionUID라는 값을 지정해 주는 것을 권장
(별도로 지정하지 않으면, 자바 소스가 컴파일될 때 자동으로 생성)
구현 클래스
public class SerialDTO implements Serializable {
private String booName;
private int bookOrder;
private boolean bestSeller;
private long soldPerDay;
public SerialDTO(String booName, int bookOrder, boolean bestSeller, long soldPerDay) {
this.booName = booName;
this.bookOrder = bookOrder;
this.bestSeller = bestSeller;
this.soldPerDay = soldPerDay;
}
@Override
public String toString() {
return "SerialDTO{" +
"booName='" + booName + '\'' +
", bookOrder=" + bookOrder +
", bestSeller=" + bestSeller +
", soldPerDay=" + soldPerDay +
'}';
}
}
객체 저장 클래스
public class ManageObject {
public static void main(String[] args) {
ManageObject manage = new ManageObject();
String fullPath = "/Users/choejeong-gyun/Documents/test.md";
SerialDTO dto = new SerialDTO("God of Java", 1, true, 100);
manage.saveObject(fullPath, dto);
}
public void saveObject(String fullPath, SerialDTO dto) {
FileOutputStream fos = null;
// ObjectOutputStream 클래스를 사용하면, 객체 저장
// ObjectInputStream 클래스를 사용하면, 저장해놓은 객체 읽기
ObjectOutputStream oos = null;
try {
// FileOutputStream 객체(fos)를 만든 후, ObjectOutputStream 의 매개변수로 넘겼음 → 객체 fos 는 파일에 저장됨
fos = new FileOutputStream(fullPath);
oos = new ObjectOutputStream(fos);
// writeObject 를 통해, 매개변수로 넘어온 객체를 저장
oos.writeObject(dto);
System.out.println("Write Success");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
객체 읽기 클래스
public class ManageObject {
public static void main(String[] args) {
ManageObject manage = new ManageObject();
String fullPath = "/Users/choejeong-gyun/Documents/test.md";
manage.loadObject(fullPath);
}
public void loadObject(String fullPath) {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream(fullPath);
ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
SerialDTO dto = (SerialDTO)obj;
System.out.println(dto);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (fis != null) {
try {
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
파일에 저장된 객체 정보 읽은 결과
SerialDTO{booName='God of Java', bookOrder=1, bestSeller=true, soldPerDay=100}
transient 를 사용한다면?
구현 클래스(SerialDTO)에서 transient 예약어를 추가하면,
transient private int bookOrder;
객체를 생성할 때는 bookOrder에 1을 넣었지만, 결과에는 0이 나오게 된다.
Write Success
SerialDTO{booName='God of Java', bookOrder=0, bestSeller=true, soldPerDay=100}
transient 예약어
를 사용하여 선언한 변수는 Serializable 의 대상에서 제외되기 때문이다.
따라서, 보안상 중요한 변수나 꼭 저장해야 할 필요가 없는 변수(패스워드와 같이)에 대해서는 transient를 사용할 수 있다.
public interface Serializable {
}
참고: 직렬화와 역직렬화 (Serializable)
참고: Basics: 직렬화(Serialization)란? (feat. Java)
참고: [Java] 직렬화(Serialization)란 무엇일까?
참고: JAVA의 객체 직렬화(Serialization)와 JSON 직렬화