코드는 부의 아학 자바 대상 서열화와 반서열화(2)

6676 단어
우리가 프로그램에서 만든 자바 대상은 모두 JVM 메모리에 존재한다. 즉, 자바 대상의 생명주기가 JVM보다 길지 않기 때문에 사용자가 만든 대상을 어떻게 영구적인 방식으로 보존할 것인가. 이것은 대상 서열화의 지식을 사용하여 서열화된 대상을 자바 대상, 즉 반서열화라고 다시 복원해야 한다.자바 대상의 서열화와 반서열화에 대해 우리가 이해해야 할 점은 자바 대상을 이진 데이터 흐름의 방식으로 로컬 파일이나 다른 미디어에 저장할 뿐 실제적으로 저장된 것은 실례화된 대상의 상태일 뿐 정적 구성원에게는 서열화할 수 없다는 것이다.
자바 대상이 서열화를 지원하려면 이 클래스는 서열화 가능한 특성을 가지고 서열화와 반서열화 방식을 실현하는 ObjectInputStream과 ObjectOutputStream 클래스를 제공해야 한다.자바 대상의 서열화 방식은 일반 방식과 맞춤형 방식 두 가지로 나눌 수 있다. 일반 방식은serializable 인터페이스를 빌려 완성하고 사용자가 너무 많은 간섭과 수정을 하지 않아도 된다.맞춤형 방식으로 사용자는transient 키워드 수식 클래스의 어떤 속성을 사용하여 이 속성을 서열화 특성을 차단할 수 있다.transient 키워드를 사용한 후,transient 수식의 필드에 서열화된 후에 기본값을 얻을 수 있으며, 서열화 전의 실례화 대상 값이 아니라 기본값을 얻을 수 있다.이 필드를 서열화할 필요가 있다면,transient 키워드를 제거할 수도 있고, 이 클래스에서readObject와 writeObject 방법을 다시 쓸 수도 있으며, 다시 쓰는 방법에서 차단된 필드를 계속 서열화하여 차단 효과를 반사할 수도 있습니다.transient 키워드를 사용하지 않고readObject와 writeObject 방법을 사용하여 맞춤형 서열화를 실현하는 방식을 제외하고 Serializable 방식과 완전히 다른 맞춤형 서열화를 지원하는 방식도 있다. 이 종류가Externalizable 인터페이스에서 계승되도록 지정하지만 이 인터페이스를 계승하는 종류는readExternal과 writeExternal 방법을 명확하게 다시 써야 대상의 서열화와 반서열화를 실현할 수 있다.이 두 가지 방법 중 서열화와 반서열화가 필요한 속성 필드를 지정하면, 가리키지 않은 속성은 서열화되지 않습니다.
다음은 프로그램 예시를 제공한다.
import java.io.*;
public class TestObjSer{
 public static void main(String[] args) throws Exception{
  String stuFilePath = "./student.out";
  String codFilePath = "./coder.out";
  File file = new File(codFilePath);
  if(!file.exists()){
   System.out.println("The serialization file does not exist, which will be created right now!");
   file.createNewFile();
  }
     Student stu = new Student("zhangsan", 17, Gender.MALE, "CSU");
     Coder coder = new Coder("lisi", 18, Gender.FEMALE, "JAVA");
        FileInputStream fis = new FileInputStream(file);
       FileOutputStream fos = new FileOutputStream(file);
 
       //folowing two stream can not be disordered, I have no idea why is this
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        ObjectInputStream ois = new ObjectInputStream(fis);
        serObj(oos,coder);
        deSerObj(ois);
 }
 public static void serObj(ObjectOutputStream oos,Object obj) throws Exception {
  oos.writeObject(obj);
  oos.close();
 }
 public static void deSerObj(ObjectInputStream ois) throws Exception {
  Person per = (Person)ois.readObject();
  ois.close();
  System.out.println(per);
 }
}

/**
 * the enum type is a special type in Java, which is generated from 
 * class Enum by default and class Enum implements the interface Seralizable
 * so it can be serialized and all member of enum should be capital
 */
enum Gender{
 MALE,FEMALE
}
/**
 * superclass should implement Serialzable
 */
class Person implements Serializable{
 private String name;
 private int age;
 private Gender gender;
 public Person(){
  System.out.println("Non-Arg constructor be called!");
 }
 public Person(String name, int age, Gender gender){
  System.out.println("Arg constructor be called!");
  this.name = name;
  this.age = age;
  this.gender = gender;
 }
 public String getName() {
     return this.name;
 }
 public int getAge() {
     return this.age;
 }
 public Gender getGender(){
  return this.gender;
 }
 public void setName(String name) {
     this.name = name;
 }
 public void setAge(int age) {
     this.age = age;
 }
 public void setGender(Gender gender){
  this.gender = gender;
 }
 public String toString(){
  return "Per(name = " + this.getName() + ", age = " 
  + this.getAge() + ", gender = " + this.getGender() +")";
 }
}
class Student extends Person{
 //use transient to avoid the field school be serialized
 private transient String school;
 public Student(){
  super();
 }
 public Student(String name, int age, Gender gender, String school){
  super(name, age, gender);
  this.school = school;
 }
 public String getSchool() {
     return this.school;
 }
 public void setSchool(String school) {
     this.school = school;
 }
 public String toString(){
  return "Stu(name = " + this.getName() + ", age = " + this.getAge() + 
  ", gender = " + this.getGender() + ", school = " + this.getSchool() +")";
 }
 private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject();//call super
        oos.writeObject(school);
    }
    private void readObject(ObjectInputStream ois) throws Exception{
        ois.defaultReadObject();//call super
        this.school = (String)ois.readObject();
    }
}
class Coder extends Person implements Externalizable {
 private String language;
 public Coder(){
  super();
 }
 public Coder(String name, int age, Gender gender, String language){
  super(name, age, gender);
  this.language = language;
 }
 public String getLanguage() {
     return this.language;
 }
 public void setLanguage(String language) {
     this.language = language;
 }
 public String toString(){
  return "Cod(name = " + this.getName() + ", age = " + this.getAge() + 
  ", gender = " + this.getGender() + ", language = " + this.getLanguage() +")";
 }
 /**
  * [readExternal description]serialize by this method should 
  * specify field in readExternal and writeExternal method by user,
  * it is completely different from Serialzable
  * @param  in                     [description]
  * @throws IOException            [description]
  * @throws ClassNotFoundException [description]
  */
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
     this.setName((String)in.readObject());
     this.setAge(in.readInt());
     this.setGender((Gender)in.readObject());
     this.language = (String)in.readObject();
    }
    public void writeExternal(ObjectOutput out) throws IOException {
     out.writeObject(this.getName());
     out.writeInt(this.getAge());
     out.writeObject(this.getGender());
     out.writeObject(this.language);
    }
}

위의 프로그램 예제에서는 Java 객체의 시리얼화와 역시리얼화에 대한 모든 지식과 몇 가지 관련 지식을 보여줍니다. 여기서 몇 마디 더 설명하고자 합니다.
1) enum은 자바의 특수한 유형에 속하며, 모든 enum 유형 성명의 변수는 기본적으로 Enum 클래스를 계승하고, 기본적으로 서열화 특성을 가지고 있다.
2) Java 객체 시리얼화는 객체가 다른 객체를 속성으로 참조하는 경우 시리얼화할 때 참조 객체도 시리얼화됩니다.
3) 부모 클래스로부터 계승된 구성원도 서열화하려면 부모 클래스는 서열화 특성, 즉 계승 Serializable 인터페이스를 명확하게 지원해야 한다.
4) Java 서열화의 기본 원리는 반사 메커니즘을 이용하는데 이것은 다음에 소개할 것이다.
5) 다른 블로그에서 볼 수 있는 한 가지 해결 방법은 단일 모드 단일 대상의 서열화에 대해 반서열화된 대상이 단일 대상과 같다는 것이다. 하나의 해결 방법은 서열화 과정을 대체하는 것이다. 이 클래스에readResolve 방법을 추가하는 것이다. Serializable 인터페이스를 실현하든지 Externalizable 인터페이스를 실현하든지 입출력 흐름에서 대상을 읽을 때readResolve () 방법은 모두 호출된다.실제로readResolve()에서 되돌아오는 대상은 반서열화 과정에서 만들어진 대상을 직접 대체하고, 만들어진 대상은 쓰레기로 회수된다(이 말은 남의 것이다).

좋은 웹페이지 즐겨찾기