직렬화가 가능한 클래스 만들기 - Serializable, transient (2)

2022. 4. 29. 11:23·자바/입출력 IO

참고) 아래의 예제에서 사용될 UserInfo 클래스는 아래와 같다.

package Serialization;

public class UserInfo implements java.io.Serializable {
	String name;
	String password;
	int age;

	public UserInfo() {
		this("Unknown", "1111", 0);
	}

	public UserInfo(String name, String password, int age) {
		this.name = name;	
		this.password = password;	
		this.age = age;	
	}

	public String toString() {
		return "("+ name + "," + password + "," + age + ")";
	}
}

 

 

 

 

1-1. 직렬화를 이해하기 위한 예제(1)

: 직렬화를 통해 UserInfo.ser를 만들어 객체를 저장후 파일로 출력하는 예제이다.

 

package Serialization;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;

public class Exercise001 {	
	public static void main(String[] args) {
		try {
			String fileName = "UserInfo.ser";
			FileOutputStream     fos = new FileOutputStream(fileName);
			BufferedOutputStream bos = new BufferedOutputStream(fos);

			ObjectOutputStream out = new ObjectOutputStream(bos);
			
			UserInfo u1 = new UserInfo("JavaMan","1234",30);
			UserInfo u2 = new UserInfo("JavaWoman","4321",26);

			ArrayList<UserInfo> list = new ArrayList<>();
			list.add(u1);
			list.add(u2);

			// 객체를 직렬화한다.
			out.writeObject(u1);
			out.writeObject(u2);
			out.writeObject(list);
			out.close();
			System.out.println("직렬화가 잘 끝났습니다.");
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}

 

( 이 예제만 보면 직렬화는 간단하게 보이지만, 실제로는 상당히 복잡하고 시간도 오래걸린다. )

( ArrayList<UserInfo>만 봐도 저장된 모든 객체들과 각 객체의 인스턴스 변수가 참조하고 있는 객체들까지

모두 직렬화된다. )

 

 

 

 

1-2. 역직렬화를 이해하기 위한 예제(2)

: 1-1 예제(1)에서 했던 직렬화를 다시 역직렬화하는 예제이다.

 

package Serialization;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;

public class Exercise002 {
	public static void main(String[] args) {
		try {
			String fileName = "UserInfo.ser";
			FileInputStream     fis = new FileInputStream(fileName);
			BufferedInputStream bis = new BufferedInputStream(fis);

			ObjectInputStream in = new ObjectInputStream(bis);

			// 객체를 읽을 때는 출력한 순서와 일치해야한다.
			UserInfo u1 = (UserInfo)in.readObject();
			UserInfo u2 = (UserInfo)in.readObject();
			ArrayList list = (ArrayList)in.readObject();

			System.out.println(u1);
			System.out.println(u2);
			System.out.println(list);
			in.close();
		} catch(Exception e) {
			e.printStackTrace();
		}
	} // main
} // class

 

( 주의할 점은 직렬화했던 순서대로 역직렬화해야 한다는 것이다. )

( 그러므로, ArrayList와 같은 컬렉션에 저장해서 직렬화하는 것을 추천한다. )

( 직렬화/역직렬화할 때 ArrayList만 하면 되므로, 순서는 상관 없다. )

 

 

 

 

1-3. 직렬화를 이해하기 위한 예제(3)

: 직렬화되지 않는 조상의 인스턴스 변수를 직렬화할 수 있게 구현한 예제이다.

 

package Serialization;

import java.io.*;

class SuperUserInfo {
	String name;
	String password;

	SuperUserInfo() {
		this("Unknown","1111");
	}

	SuperUserInfo(String name, String password) {
		this.name = name;
		this.password = password;
	}
} // class SuperUserInfo

public class UserInfo2 extends SuperUserInfo implements java.io.Serializable {
	int age;

	public UserInfo2() {
		this("Unknown", "1111", 0);
	}

	public UserInfo2(String name, String password, int age) {
		super(name, password);
		this.age = age;	
	}

	public String toString() {
		return "("+ name + "," + password + "," + age + ")";		
	}

	private void writeObject(ObjectOutputStream out)
		throws IOException {
		out.writeUTF(name);	
		out.writeUTF(password);	
		out.defaultWriteObject();
	}

	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
		name = in.readUTF();
		password = in.readUTF();
		in.defaultReadObject();
	
	}
} // class UserInfo2

 

( name과 password를 위해 writeObject()와 readObject()를 추가해서 직접 직렬화하도록 구현해야 한다. )

( writeObject()와 readObject()는 직렬화와 역직렬화 작업시에 자동적으로 호출된다. )

( 접근 제어자는 private으로 단순히 정해진 규칙이다. )

 

( name과 password는 String이기 때문에, writeUTF()와 readUTF()를 사용했다. )

( 이외에도 writeInt()와 readInt() 등이 있기 때문에, 각 인스턴스 변수에 맞는 것을 잘 사용하면 된다. )

 

( 마지막으로 defaultWriteObject()는 인스턴스 변수 age의 직렬화를 수행한다. )

 

 

 

 

2. 직렬화가능한 클래스의 버전관리

- 직렬화된 객체를 역직렬화할 때는 직렬화 했을 때와 같은 클래스를 사용해야 한다.

 

- 그러나, 이름이 같더라도 클래스의 내용이 변경된 경우 역직렬화는 실패한다.

 

- static 변수나 상수 또는 transient가 붙은 인스턴스 변수가 추가되는 경우에는 직렬화에 영향을

미치지 않기 때문에 클래스의 버전을 다르게 인식하도록 할 필요 없다.

 

 

- 네트웍으로 객체를 직렬화하여 전송하는 경우, 보내는 쪽과 받는 쪽이 모두 같은 버전의 클래스를

가지고 있어야 하는데 클래스가 조금만 변경되어도 해당 클래스를 재배포하는 것은 프로그램 관리를

어렵게 만들어버린다. 

 

- 이럴때, 아래의 코드처럼 클래스의 버전을 수동으로 관리해줄 필요가 있다.

class MyData implements java.io.Serializable{
	static final long serialVersionUID = 3518646845468468889L;
	int value1;
}

 

 

( serialVersionUID를 정의해준다면, 클래스의 내용이 바뀌어도 클래스의 버전이 자동생성된 값으로 변경되지

않는다. )

( serialVersionUID의 값은 정수값이면 어떠한 값으로 지정할 수 있지만, 서로 다른 클래스간에 같은 값을 갖지

않도록 serialver.exe를 사용해서 생성된 값을 사용하는 것이 보통이다. )

( serialver.exe은 cmd에서 자신의 클래스를 seialver 뒤에 써 주면 된다. )

 

> serialver <클래스이름>

 

( serialVersionUID의 값이 정의되어 있다면 그 값을 출력하고, 그렇치 않으면 자동 생성하여 출력한다. )

저작자표시 (새창열림)

'자바 > 입출력 IO' 카테고리의 다른 글

직렬화가 가능한 클래스 만들기 - Serializable, transient (1)  (0) 2022.04.29
직렬화(Serializtion): Object 입출력 스트림  (0) 2022.04.29
표준 입출력과 File: File(4)  (0) 2022.04.28
표준 입출력과 File: File(3)  (0) 2022.04.28
표준 입출력과 File: File(2)  (0) 2022.04.28
'자바/입출력 IO' 카테고리의 다른 글
  • 직렬화가 가능한 클래스 만들기 - Serializable, transient (1)
  • 직렬화(Serializtion): Object 입출력 스트림
  • 표준 입출력과 File: File(4)
  • 표준 입출력과 File: File(3)
백_곰
백_곰
  • 백_곰
    친절한 코딩
    백_곰
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 알고리즘 (with JAVA)
        • 기본 알고리즘
        • 완전 탐색
        • 분할 정복 알고리즘
        • 동적 계획법
        • 탐욕법
        • 코딩 테스트 기출 문제
        • 코드트리 조별과제
      • 백준 (with JAVA)
        • 완전 탐색
        • 분할 정복
        • 그 외
      • 자바
        • 개발 환경 구축하기
        • 팁
        • 기본적인 개념
        • 컬렉션 프레임워크
        • 프로세스와 쓰레드
        • 지네릭스
        • 람다식
        • 스트림
        • 입출력 IO
        • 네트워킹
        • 열거형(enums)
        • java.lang 패키지
        • java.time 패키지
        • 유용한 클래스들
        • 형식화 클래스들
      • 안드로이드 with 자바
        • 응용 문제들
        • 자잘한 문제들
        • 오류 보고서
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      선택 정렬
      역직렬화
      serializable
      제자리 정렬
      file
      자바 개념
      유용한 클래스
      코딩테스트
      알고스팟
      코드트리
      소켓 프로그래밍
      불안정 정렬
      TCP 소켓 프로그래밍
      다형성
      java.lang패키지
      스트림
      InputStream
      안정 정렬
      java.time 패키지
      코딩트리조별과제
      중간연산
      outputstream
      안드로이드 스튜디오
      Arrays
      문자 기반 스트림
      ServerSocket
      Collections Framework
      map()
      람다식
      snail
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    백_곰
    직렬화가 가능한 클래스 만들기 - Serializable, transient (2)
    상단으로

    티스토리툴바