자바에서 어떤 상태를 저장하기 위해 메모리에 올라간 인스턴스 그 자체를 저장할때 직렬화를 사용하는 방법이 있다.

직렬화
FileOutputStream fs = new FileOutputStream("StateSave.sav");//연결 스트림(connection stream)

ObjectOutputstream os = new ObjectOutputStream(fs);//연쇄 스트림(chain stream)

//각 클래스는 하나씩의 기능만 잘 발휘하는것이 좋다.
//ObjectOutputstream는 객체를 저장하고 FileOutputStream는 파일에 직접연결
//즉 두 스트림이 서로 연쇄(chain)하고 있다.
//파일이나 소켓과 같은 출발지 또는 목적지로의 연결을 나타내는 연결 스트림(connection stream)
//다른 스트림에 연쇄되어야만 쓸수있는 연쇄 스트림(chain stream)

os.writeObject(one);
os.writeObject(two);

os.close(); //맨 위의 os만 닫아주면 fs는 자동으로 닫힌다.
@ 객체가 직렬화되면 인스턴스 변수를 참조하는 모든 객체도 직렬화가 된다. 연관된 모든 것이 직렬화됨
@ 클래스를 직렬화 할 수 있게 하고 싶으면 Serializable 인터페이스가 구현되어야 한다.
@ Serializable 인터페이스는 이 인터페이스를 구현하는 클래스가 직렬화 할 수 있는 클래스라는 것을 나타내는 역활을 한다.
@ 상위 클래스가 Serializable를 구현하면 하위도 역시 직렬화 가능
@ 어떤 인스턴스 변수를 저장할 수 없거나 직렬화 하면 안된다면 그 변수는 transient로 지정하면 된다.
transient Dog puppy;
@ transient 로 지정되면 직렬화할때 이변수는 저장하지말고 건너 뛰어라는 표시이다.

역직렬화
FileInputStream fs = new FileInputStream("StateSave.sav");
ObjectInputStream os = new ObjectInputStream(fs);
GameCharacter one = (GameCharacter)os.readObject();//나올땐 object로 업캐스팅되어 나오니 다시 다운캐스팅 시켜준다.
GameCharacter two = (GameCharacter)os.readObject();//저장한 순서대로 꺼냄
os.close();
@ 역질렬화할때 객체의 생성자는 실행되지 않는다 => 생성자가 실행되면 객체의 상태가 원래 새로운 상태로 돌아가기 때문이다. (생성자는 객체의 초기화를 담당함을 기억!)
@ 정적변수는 저장되지않고 역직렬화시에 현재 정적변수에 들어 있는 값을 받는다.

@ 객체를 직렬화하면 그 객체에는 ID가 찍힌다.
@ serialVersionUID
 - serialver 객체  이렇게 실행하면 serialVersionUID를 확인할 수 있다.

클래스를 변경했을때 역직렬화 과정에서 문제가 일어날 수 있는 경우
- 인스턴스 변수를 삭제하는 경우
- 인스턴스 변수의 유형을 변경하는 경우
- transient 로 지정하지 않았던 인스턴스변수를 지정하는 경우
- 클래스를 상속 계층에서 위나 아래로 옮기는 경우
- Serializable이었던 클래스를 Serializable이 아닌 클래스로 변경하는 경우
- 인스턴스 변수를 정적변수로 변경하는 경우

클래스를 변경해도 역직렬화와 관련된 문제가 생기지 않는 경우
- 클래스에 새로운 인스턴스변수를 추가한느 경우(직렬화 당시에 없었던 변수에는 그냥 기본값이 대입)
- 상속 트리에 클래스를 추가하는 경우
- 상속 트리에서 클래스를 제거하는 경우
- 인스턴스 변수의 접근 레벨을 역직렬화 과정에서 변수에 갑을 대입하는데 문제가 없는 범위 내에서 변경하는 경우
- transient 로 지정되었던 인스턴스 변수를 transient가 아닌 변수로 변경하는경우(그냥 기본값이 저장)



Posted by Taoist
,