[JAVA] 자바 - 객체 직렬화(ObjectStream, Object Serialization)
by mini_min[JAVA]
자바 - 객체 직렬화(ObjectStream, Object Serialization)
✔️ ObjectInputStream
ObjectOutputStream 클래스에 의해 파일이 저장되거나 네트워크로 전달된 객체의 직렬화를 해제하는 기능을 한다.
파일이나 네트워크로 받은 직렬화 된 데이터를 다시 원래 데이터로 복원하는 역할!!
= readObject() 메소드를 사용해 복원한다. 이후 ✨원래 데이터로 캐스팅✨하여 사용한다.
📓 스트림으로 읽을 수 있는 객체
- Serializable 인터페이스 or Externalizable 인터페이스를 구현한 클래스의 객체
public static void main(String[] args) {
String pathname = "object.txt";
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(pathname))){
@SuppressWarnings("unchecked")
Hashtable<String, String> ht = (Hashtable<String, String>)ois.readObject();
Iterator<String> it = ht.keySet().iterator();
while(it.hasNext()) {
String key = it.next();
String value = ht.get(key);
System.out.println(key + "->" + value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
💡 readObject() 메소드를 사용할 때, 원래 데이터로 캐스팅해준다.
= (Hashtable<String, String>)ois.readObject();
✔️ ObjectOutputStream
객체를 출력하는 기능을 제공하는 클래스로 출력 스트림에 출력하기 전에 직렬화를 수행한다.
파일이나 네트워크로 데이터를 전송하기 위해 직렬화를 수행하며 이때, writeObject() 메소드를 사용
📓 스트림으로 저장할 수 있는 객체
- Serializable 인터페이스를 구현한 클래스의 객체
public static void main(String[] args) {
//오브젝트 스트림은 직렬화 되어야한다.
Hashtable<String, String> ht = new Hashtable<>();
ht.put("자바", "프로그래밍");
ht.put("HTML", "웹 프로그래밍");
ht.put("오라클", "데이터베이스");
String pathname = "object.txt";
//ObjectOutputStream : 직렬화된 객체를 저장할 수 있는 스트림이다. 선두에 클래스명이 저장됨
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(pathname))) {
oos.writeObject(ht);
System.out.println("저장완료");
} catch (Exception e) {
e.printStackTrace();
}
}
✔️ 객체 직렬화란?
직렬화는 자바 시스템 내부에서 사용되는 객체 또는 데이터를 자바 외부에서도 사용할 수 있도록 바이트 단위로 변환하는 것이다.
📓 직렬화가 가능한 자료형 및 객체
- 기본형 타입들 (char, byte, int 등..)
- Serializable 인터페이스를 구현한 클래스의 객체
- transient 가 사용된 멤버변수 , static 멤버변수, 메소드는 직렬화 대상에서 제외된다.
✨ 역 직렬화
: 직렬화된 바이트 단위의 데이터를 다시 원래 데이터로 복원하는 것
✔️ 객체 직렬화 방법
1) 먼저, 객체가 직렬화되도록 Serializable 인터페이스를 구현해야한다.
2) 해당 인터페이스가 자바 가상 머신에 객체 직렬화가 필요함을 알린다.
3) 따로 구현할 메소드가 없고, 단지 Serializable 인터페이스만 implements 해주면 된다.
💡 직렬화가 가능한 객체만 ObjectoutputStream 으로 저장 가능
✨ transient
: 직렬화 대상에서 제외할 멤버 변수는 해당 키워드 붙여 제외한다.
: transient 키워드가 붙은 멤버 변수가 복원되면 숫자변수는 0, 객체는 null 로 설정된다.
public static void main(String[] args) {
String pathname = "demo.txt";
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(pathname))) {
// 주소 저장한거라서 의미 없다.
// 주소가 아니라 주소 안에 내용을 직접적으로 가져와야함. 그래서 직렬화가 필요하다.
oos.writeObject(new UserVO("가가가", "010-1111-1111", 20));;
oos.writeObject(new UserVO("나나나", "010-2222-2222", 20));;
oos.writeObject(new UserVO("다다다", "010-3333-3333", 20));;
System.out.println("파일 저장 완료!");
} catch (Exception e) {
e.printStackTrace();
}
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(pathname))) {
System.out.println("\n파일 내용 ... ");
while(true) {
UserVO vo = (UserVO)ois.readObject(); // 직렬화된 데이터를 읽어 복원
System.out.println(vo.getName()+ "," + vo.getTel() + "," + vo.getAge());
}
} catch (EOFException e) {
// ObjectInputStream 에서 더이상 읽을 자료가 없는 경우 발생하는 예외이다.
} catch (FileNotFoundException e) {
System.out.println("등록된 파일이 없습니다.");
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// Serializable : 객체를 직렬화 가능하도록 설정 작업
// 직렬화 대상에서 제외되는 것 : 메소드, static 변수, transient 변수,
class UserVO implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private transient String tel; // 전화번호는 직렬화에서 제외. 읽어오면 null
private int age;
public UserVO() {
}
public UserVO(String name, String tel, int age) {
this.name = name;
this.tel = tel;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
💡 Serializable : 객체를 직렬화 가능하도록 설정 작업
직렬화 대상에서 제외되는 것 : 메소드, static 변수, transient 변수
💡 EOFException : ObjectInputStream 에서 더이상 읽을 자료가 없는 경우 발생하는 예외이다.
✔️ serialVersionUID 필드
직렬화에 사용되는 고유 아이디!!
선언하지 않으면 JVM 이 디폴트로 자동 생성해준다. serialVersionUID 는 역 직렬화 해서 읽을 때 캐스팅한 클래스와 역 직렬화한 serialVersionUID 가 맞는지 확인하기 위해 사용한다.
✨ 꼭 선언하지 않아도 되지만, serialVersionUID 계산은 세부 사항을 민감하게 반영해서 선언해주는게 좋음 🥺
= InvalidClassException 을 유발 할 수 있다.
'Java' 카테고리의 다른 글
[JAVA] 자바 - InetAddress 클래스 / URL 클래스 (0) | 2022.09.05 |
---|---|
[JAVA] 자바 - 컴퓨터 네트워크 (프로토콜, 포트, IP) (0) | 2022.09.05 |
[JAVA] 자바 - AtomicInteger 사용, BlockingQueue<E> (0) | 2022.09.05 |
[JAVA] 자바 - 동기화 / synchronized 블럭 (0) | 2022.09.01 |
[JAVA] 자바 - TimerTask 클래스와 Timer 클래스 (0) | 2022.09.01 |
블로그의 정보
개발자 미니민의 개발로그
mini_min