프로그래밍/Java

객체의 직렬화! Serialization 이야기

seungdols 2015. 9. 19. 23:01


객체를 저장 할수 있다!?

도대체 무슨 말인가...??

그건 객체를 데이터 스트림으로 만드는 것을 말하며, 데이터 스트림은 File에 저장 할수도 ! Network로 보내고 받을 수 있다.

그럼 그것은 어떻게 해야 하는가!!!?



Serialization의 경우 2가지가 가능하다.


객체를 데이터 스트림으로 만드는 직렬화.

데이터 스트림에서 다시 객체로 만드는 역직렬화.


직렬화된 객체의 내용은 인스턴스 변수의 집합만 포함 된다.

Method는 당연히 제외 된다. Why? 라고 의문을 품을지도 모르지만, 일단 그렇게 넘어가자.


UserInfo class를 보자. 사실 별것 없다.

주요한 관점 포인트는 Serializable interface를 구현한다. 이 말은 이 클래스는 직렬화 할 예정!

이런 의미를 담고 있다. 사실 저 인터페이스는 빈껍데기랑 같다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class UserInfo implements Serializable{
    private String name;
    private String password;
    int age;
 
    public UserInfo() {
        this("Unknown" , "1234" , 20);
    }
 
    public UserInfo(String name, String password, int age) {
        this.name = name;
        this.password = password;
        this.age = age;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    @Override
    public String toString() {
        return "UserInfo{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}
cs


여기서 주요 관점은 ObjectOutputStream이라는 보조스트림이다.

여기에 3가지 스트림이 존재하는데 File의 경우 File을 위해 존재하고, Buffered의 경우 버퍼를 사용하는 스트림으로,

고속을 가능하게 해준다. (저도 잘....)


* 단, 객체가 Object인 경우는 직렬화를 할 수 없으며(Object Type이지만 객체는 String으로 생성된 경우는 가능),

직렬화에서 제외 하고자 하는 인스턴스 멤버의 경우transient를 붙여주면 된다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class SerializationEx1 {
    public static void main(String[] args) {
 
        try{
            String fileName = "UserInfo.ser";
            FileOutputStream fileOutputStream = new FileOutputStream(fileName);
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
 
            ObjectOutputStream outputStream = new ObjectOutputStream(bufferedOutputStream);
            UserInfo userInfo1 = new UserInfo("JavaStudy","1234",24);
            UserInfo userInfo2 = new UserInfo("JavaProgrammer","1234",23);
 
            ArrayList list = new ArrayList();
            list.add(userInfo1);
            list.add(userInfo2);
 
            //객체를 직렬화
 
            outputStream.writeObject(userInfo1);
            outputStream.writeObject(userInfo2);
            outputStream.writeObject(list);
            outputStream.close();
            System.out.println("직렬화 성공");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
}
cs

데이터 스트림화 된 객체를 다시 객제로 읽는 역직렬화 과정을 단순하게 표현한 것이다.

사실 Collection에 담아서 직렬화 하고 , 다시 역직렬화 하는 것이 더 좋은  방법이긴 하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class SerializationEx2 {
    public static void main(String[] args) {
        try{
            String fileName = "UserInfo.ser";
            FileInputStream fileInputStream = new FileInputStream(fileName);
            BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
 
            ObjectInputStream objectInputStream = new ObjectInputStream(bufferedInputStream);
 
            UserInfo userInfo1 = (UserInfo)objectInputStream.readObject();
            UserInfo userInfo2 = (UserInfo)objectInputStream.readObject();
            ArrayList list = (ArrayList)objectInputStream.readObject();
 
            System.out.println("직렬화 객체 읽기");
            System.out.println(userInfo1);
            System.out.println(userInfo2);
            System.out.println(list);
            objectInputStream.close();
 
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
cs

개인적으로 직렬화 하는 클래스의 경우에는 직렬화 Version을 직접 명시해주는 것이 좋다.

어차피 자동적으로 추가해주는 것이지만, 그건 랜덤이라 추후 문제가 생길 수 있다.

그래서 아래와 같이 직접 명시해주는 것이 좋다.

serialver 클래스 이름으로 serialVersionUID를 자동 생성하는 것이 좋겠지만, cmd로 하는 것보단,

IDE에서 플러그인으로 사용하는 것이 더 빠르다.

private static final long serialVersionUID = -794875436981507839L;



  •  무단 수정 및 배포는 금지합니다. 
  •  모든 내용은 본 블로그 운영자가 정리한 내용입니다. 
  •  참조한 정보에 대해서는 출처를 남기고 있습니다.
  •  틀린 내용 / 오류가 포함된 내용은 댓글로 남겨주세요.
  •  choiseungho0822@gmail.com 보내주셔도 됩니다.
  •  Seungdols Wiki 운영중입니다.


반응형