No.22 객체 흐름:객체 시리얼화/역시리얼화

3807 단어

Java 객체 서열화란 무엇입니까?

  • 자바 플랫폼은 메모리에서 재사용 가능한 자바 대상을 만들 수 있지만 일반적인 상황에서 JVM이 실행될 때만 이 대상들이 존재할 수 있다. 즉, 이 대상들의 생명주기가 JVM의 생명주기보다 길지 않다는 것이다.
  • 실제 응용에서는 JVM이 실행을 멈춘 후에 지정한 대상을 저장하고 나중에 저장된 대상을 다시 읽어야 할 수 있다.자바 대상 서열화는 우리가 이 기능을 실현하는 데 도움을 줄 수 있다.
  • 대상을 영구화할 때 대상 서열화를 사용하는 것을 제외하고 RMI(원격 방법 호출)를 사용하거나 네트워크에서 대상을 전달할 때 대상 서열화를 사용한다.
  • 자바 대상을 서열화하여 대상을 저장할 때 그 상태를 한 조의 바이트로 저장하고 미래에 이 바이트를 대상으로 조립한다.반드시 주의해야 할 것은 대상 서열화는 대상의'상태', 즉 구성원 변수를 저장하고 대상 서열화는 클래스의 정적 변수에 주목하지 않는다는 것이다.

  • 객체 정렬 방법:


    (1) 자바에서 하나의 클래스가serializable 인터페이스를 실현하면 서열화할 수 있다.(2) 만약에 한 클래스 중 일부 필드가 서열화되기를 원하지 않는다면 예를 들어 한 사용자가 민감한 정보(예를 들어 비밀번호)가 있다면 안전을 위해 파일에 기록되어 전송되고 싶지 않으면 이런 정보에 대응하는 변수에transient 키워드를 추가하면 된다.대상을 서열화할 때, 이 속성은 지정한 목적지 (file) 에 서열화되지 않습니다.

    ObjectOutputStream을 사용하여 객체를 시리얼화/ObjectInputStream을 사용하여 객체를 반시리얼화합니다.

  • java.io의 클래스 ObjectInputStream과 ObjectOutputStream은 서열화와 반서열화 대상을 포함하는 고차원 데이터 흐름입니다.그들은 InputStream/OutputStream의 직접 하위 클래스입니다.
  • 예: 우선 우리는 하나의 종류를 사용자 정의한다:
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private transient int password;
    private Gender gender;
    
    public Person(String name, int age, int password, Gender gender) {
      super();
      this.name = name;
      this.age = age;
      this.password = password;
      this.gender = gender;
    }
    
    @Override
    public String toString() {
      String str = "[" + "name : " + name + "\r
    " + "age : " + age + "\r
    " + "password :" + password + "\r
    " + "gender : " + gender + "]"; return str; }
  • 그 중에서Gender 속성은 enum(매거진)류로 API 문서를 보면 enum이serialable 인터페이스를 실현했기 때문에 이 속성도 서열화될 수 있음을 알 수 있다.enum Gender {MAIL,FEMAIL}
    다음은 Object Output Stream과 Object Input Stream을 사용하여 서열화 반서열화를 실현합니다.
    public class Test {
    public static void main(String[] args) {
        String fileName = "D://Person.ser";
        File file = new File(fileName);
    
        ObjectInputStream ois = null;
        ObjectOutputStream oos = null;
    
        Person person = new Person("lisi", 16, 1111111, Gender.MAIL);
        try {
            oos = new ObjectOutputStream(new FileOutputStream(file));
            oos.writeObject(person);
            oos.close();
            
            
            ois = new ObjectInputStream(new FileInputStream(file));
            Object p= ois.readObject();
            ois.close();
            System.out.println(p);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    
      }
    }
    

    serialVersionUID 필드 의미:


    실제 응용에서 우리는 Person 클래스를 수정해야 하는 상황에 자주 부딪힌다. Person이 이전에 Serialable 인터페이스를 실현했기 때문에 만약에 서열화된 후에 Person 클래스에 변화가 생겼다. 예를 들어 하나의 구성원 변수가 많아졌다.우리는 실험을 통해 이러한 결과를 얻을 수 있다.
    Exception in thread “main” java.io.InvalidClassException: Person; local class incompatible: stream classdesc serialVersionUID = xxxxxxxx, local class serialVersionUID = yyyyyyyyyy ;
    

    파일 흐름의class와classpath의class, 즉 수정된class가 호환되지 않고 보안 메커니즘을 고려하여 프로그램이 오류를 냈고 불러오는 것을 거부했다는 뜻이다.
    이러한 결과는 우리가 이름이 알려지지 않은 서열화된 대상의 SerialVersion UID 필드를 만들 때 자바는 우리에게 자동으로 serialVersion UID를 생성하고 변경된 후에 또 다른 serialVersion UID를 생성하여 반서열화 실패를 초래했다.
    이 때 우리는 이 클래스에 대해 자체적으로serialVersionUID 값을 지정해야 하며, 지정한 후에 다시 수정하면 상술한 문제가 발생하지 않을 것이다.(Eclipse와 같은 컴파일러를 사용하면 컴파일러가 이 필드를 생성하라고 알려주고 생성하지 않으면 경고를 보냅니다)

    참조 자료:


    transient:
    http://www.cnblogs.com/lanxuezaipiao/p/3369962.html
    개체 서열화는 왜 serialVersionUID의 경위를 정의해야 하는가
    http://lenjey.iteye.com/blog/513736)http://lenjey.iteye.com/blog/513736
    Java 객체 시리얼화 이해
    http://www.blogjava.net/jiangshachina/archive/2012/02/13/369898.html

    좋은 웹페이지 즐겨찾기