Day 021
오늘은 드디어 자바 IO 파트를 마무리 했다!!! 벌써 네트워킹도 마무리가 코 앞이다. 점점 시간이 빨리 지나는 것 같은 느낌이다. 어제에 이어서 보조스트림 파트의 객체 입출력 보조스트림을 배웠는데, 상당히 많은 시간을 할애해서 강의하셨다. 설명을 잘 해주셔서 수업을 듣는 당시에는 이해가 잘 되었는데, 언제나 그렇듯 복습을 하지 않으면 아마 금방 까먹을 것 같다. 꼭 열심히 정리하고 복습해야지!!! 이제 내일부터 살짝 맛 봤던 TCP 네트워킹부터 다시 학습을 재개하고, Serversocket과 Socket을 이용해서 채팅 프로그램을 만들텐데 기대된다 ㅎㅎ
객체 입출력 보조 스트림
객체를 파일 또는 네트워크로 입출력할 수 있는 기능 제공
객체는 문자가 아니므로 바이트 기반 스트림으로 데이터 변경 필요 (객체 직렬화) (Serialization)
힙에 생성된 자바객체를 파일로 저장하거나
파일에 저장된 자바객체를 다시 읽어서 힙으로 복구해서
네트워크로 지구 반대면 프로그램쪽으로 보내는 것이 가능한데
위의 것을 가능하게 하는 이유는 바로 "객체의 (역)직렬화"가 있기 때문이다
Heap Area
직렬화 <Object> ---> 바이트열로 변환
역직렬화 객체로변환 <--- 바이트열
바이트 -> InputStream -> ObjectInputStream -> 객체 -> 프로그램
프로그램-> 객체 -> ObjectOutputStream -> OutputStream -> 바이트
ObjectInputStream, ObjectOutputStream
ObjectInputStream ois = new ObjectInputStream(바이트입력스트림);
ObjectOutputStream oos = new ObjectOutputStream(바이트입력스트림);
oos로 객체 직렬화하기 위해서는 writeObject() 메소드 사용
oos.writeObject(객체);
ois로 바이트를 객체로 역직렬화하기 위해서는 readObject() 메소드 사용
객체타입 변수 = (객체타입) ois.readObject();
직렬화가 가능한 클래스(Serializable)
자바에서는 Serializable 인터페이스를 구현한 클래스만 직렬화 할 수 있도록 제한
static필드와 transient 필드는 제외
객체 직렬화 할 때 private 필드 포함한 모든 필드를 바이트로 변환 가능
객체 직렬화는 힙에 있는 객체를 대상으로함
정적멤버는 메소드영역에 존재하는 clazz객체 소속이기 때문에 객체 직렬화의 대상이 아니다.
이 경우 필드3과 필드 4는 Object.data 파일에 저장되지 않음
이 경우 field3와 field4는 복원되지 않음
serialVersionUID 필드
직렬화된 객체를 역직렬화 할 때는 직렬화 했을 때와 같은 클래스 사용해야 한다
클래스의 이름이 같더라도 클래스의 내용이 변경된 경우 역직렬화 실패
serialVersionUID
같은 클래스임을 알려주는 식별자 역할
Serializable 인터페이스 구현한 클래스를
컴파일 시 자동적으로 serialVersionUID 정적 필드 추가
Serializable 인터페이스 구현한 클래스를
재컴파일하면 serialVersionUID의 값 변경
불가피한 수정 있을 경우 명시적으로 serialVersionUID 선언
직렬화 끝낸 후 새로운 필드를 추가하는 경우 serialVersionUID값이 변경되기 때문에,
개발자가 직접 명시적으로 serialVersionUID를 선언하여 필드를 추가해도 변경되지 않게 고정시켜야 한다
SerialVersionUIDExample2 (p1049)
local class incompatible:
stream classdesc serialVersionUID = -5993977944878930441,
local class serialVersionUID = -1265691405514514962
ClassC 타입의 객체를 파일에 직렬화 할 당시의 ClassC의 serialVersionUID의 값은 -5993977944878930441였는데,
이후에 field2를 ClassC에 추가하고 다시 컴파일 한 후의 ClassC의 serialVersionUID 값은 -1265691405514514962으로 바뀐다
두개의 값이 같아야 복구가 가능한데, ClassC에 필드를 추가하는 순간 두개의 값이 달라지기 때문에 복구가 불가능하다!!!
private static final long serialVersionUID = 1L; 을 추가해서 ClassC의 serialVersionUID 값을 고정해주면
필드를 추가해도 serialVersionUID가 바뀌지 않기 때문에 객체 복원이 가능해진다!!!
NonSerializableParentExample (p1050)
1. 부모/자식 모두 Serializable할 때
자식객체를 직렬화하면 자식뿐만 아니라 부모객체까지 함께 직렬화 된다 (기본 직렬화)
2. 부모만 Serializable하고 자식은 Non-Serializable할 때
자식객체를 직렬화하면 자식뿐만 아니라 부모객체까지 함께 직렬화 된다 (1과 동일)
(부모의 Serializable한 성질이 자식에게 상속됨)
3. 부모만 Non-Serializable하고 자식은 Serializable할 떄
자식객체를 직렬화해도 자식객체는 직렬화 되지만, 부모객체는 직렬화 되지 않는다.
4. 부모/자식 모두 Non-Serializable할 때
자식객체를 직렬화하면 무조건 오류발생
5. 부모만 Non-Serializable한데, 부모의 소스코드를 수정하지 못하고,
(수정가능하면 implements Serializable 하면 되잖슴)
자식은 Serializable할 떄
어떻게하면 자식 부모 모두 객체의 직렬화를 가능하게 할까? 방법을 알아보자! 이게 우리의 예제임
-> 자식 클래스에 아래의 2개의 메소드를 추가하고, ( writeObject(), readObject() )
그 안에서 직렬화/역직렬화가 애시당초 불가능한 필드에 대해서는
InputStream, OutputStream이 제공하는 메소드로 직접 입/출력을 수행하고,
나머지 Serializable한 필드는 JVM이 하듯이 동일하게 처리하자!
private void writeObject(ObjectOutputStream out) throws IOException { ... }
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { ... }
'국비학원' 카테고리의 다른 글
[국비지원] KH 정보교육원 23일차 (0) | 2022.04.26 |
---|---|
[국비지원] KH 정보교육원 22일차 (0) | 2022.04.25 |
[국비지원] KH 정보교육원 20일차 (0) | 2022.04.20 |
[국비지원] KH 정보교육원 19일차 (0) | 2022.04.19 |
[국비지원] KH 정보교육원 18일차 (0) | 2022.04.18 |