직렬화(Serialization)
- 직렬화란 자바 시스템 내부에서 사용되는 객체 또는 데이터를 자바 외부에서도 사용할 수 있도록 바이트(byte)단위로 변환하는 것을 말한다.
- 직렬화가 가능한 자료형 및 객체
기본형 타입 (boolean, char, byte, short, int, long, float, double)
Serializable 인터페이스를 구현한 클래스의 객체
transient가 사용된 멤버변수(null 전송), static 멤버변수, 메소드는 직렬화 대상에서 제외된다.
역 직렬화(Deserialization)
- 직렬화된 바이트(byte)단위의 데이터를 다시 원래 데이터로 복원하는 것을 말한다.
java.io.Serializable 인터페이스
- 객체를 직렬화하기 위해서는 먼저, 객체를 직렬화가 가능하도록 Serializable 인터페이스를 구현해야 한다.
- 이 인터페이스는 객체 직렬화가 제공되어야 함을 자바 가상 머신에 알려주는 역할을 한다.
- Serializable 인터페이스는 다른 인터페이스와는 달리 구현해야 할 메소드가 없으므로 단지 Serializable 인터페이스만 implements 하면 된다.
- 객체의 직렬화 대상에서 제외되는 것은 멤버 변수가 static으로 선언된 경우, 멤버 변수가 transient로 선언된 경우와 메소드이다.
형식
public class 클래스명 implements Serializable {
// 클래스 정의 부분
}
transient
- 직렬화 대상에서 제외할 멤버 변수는 transient 키워드를 사용하여 제외한다.
- transient 키워드가 붙은 멤버 변수가 복원되면, 숫자변수는 0, 객체는 null로 설정된다.
public class 클래스명 implements Serializable {
접근제어자 자료형 변수1;
접근제어자 transient 자료형 변수2;
// 클래스 구현
}
SerialVersionUID 필드
- serialVersionUID 는 직렬화에 사용되는 고유 아이디로, 선언하지 않으면 JVM에서 디폴트로 자동생성된다.
serialVersionUID는 역 직렬화 해서 읽어 들일 때 캐스팅한 클래스의 serialVersionUID와 역직렬화 한 serialVersionUID가 맞는지 확인하기 위해 사용된다.
- 선언하지 않아도 동작하는데 문제는 없지만, JVM에 의한 디폴트 serialVersionUID 계산은 클래스의 세부 사항을 매우 민감하게 반영하기 때문에 컴파일러 구현체에 따라서 달라질 수 있어 역 직렬화(deserialization) 과정에서 예상하지 못한 InvalidClassException을 유발할 수 있다.
- Java에서는 명시적으로 serialVersionUID를 선언할 것을 적극 권장하고 있다.
- 선언 예
private static final long serialVersionUID = 1L;
예시>>
Main
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Ex004_transient {
public static void main(String[] args) {
UserService ov = new UserService();
ov.saveFile();
ov.loadFile();
}
}
Class
// Serializable : 직렬화
// 직렬화에서 제외되는 것 : 메소드, static 변수, transient 변수
class UserDTO implements Serializable { // 바이트로 고쳐서 저장해줌
private static final long serialVersionUID = 1L; // 같은 클래스인지아닌지 확인용도
private String name;
private transient String tel; // 직렬화에서 제외됨. 네트워트로 전송이 되지 않음.
private int age;
public UserDTO() {
}
public UserDTO(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;
}
}
class UserService {
private String pathname = "object2.txt";
public void loadFile() {
try( ObjectInputStream ois = new ObjectInputStream(new FileInputStream(pathname))) {
System.out.println("파일 내용...");
while(true) {
UserDTO vo = (UserDTO) ois.readObject(); // 역직렬화수행
System.out.println(vo.getName()+"\t"+vo.getTel()+"\t"+vo.getAge());
}
} catch (EOFException e) {
// ObjectInputStream 스트림은 파일의 내용을 더 이상 읽을 수 없으면
// EOFException 예외가 발생한다. 따라서 EOFException 예외를 catch하고
// 아무런 코드도 작성하지 않는다. // 안잡으면 터짐
}catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public void saveFile() {
// ObjectOutputStream : Serializable 인터페이스가 구현되어 있어야 저장가능하다.
try ( ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(pathname))){
oos.writeObject(new UserDTO("다자바", "010-0000-0000", 20));
oos.writeObject(new UserDTO("너자바", "010-1111-0000", 20));
oos.writeObject(new UserDTO("구자바", "010-2222-0000", 20));
System.out.println("파일 저장 완료...");
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}

'쌍용강북교육센터 > 8월' 카테고리의 다른 글
0826_Java : JDBC : DriverManager 클래스 Connection 인터페이스 (0) | 2021.08.26 |
---|---|
0826_Java : JDBC (Java Database Connectivity) (0) | 2021.08.26 |
0825_Java : ObjectStream 활용 예제 (0) | 2021.08.25 |
0825_Java : ObjectOutputStream, ObjectInputStream 클래스 (0) | 2021.08.25 |
0825_Java : DataStream 활용 예제 (0) | 2021.08.25 |