Java - การทำให้เป็นอนุกรม

Java จัดเตรียมกลไกที่เรียกว่าการทำให้เป็นอนุกรมออบเจ็กต์โดยที่อ็อบเจ็กต์สามารถแสดงเป็นลำดับของไบต์ที่มีข้อมูลของอ็อบเจ็กต์รวมทั้งข้อมูลเกี่ยวกับประเภทของอ็อบเจ็กต์และประเภทของข้อมูลที่จัดเก็บในอ็อบเจ็กต์

หลังจากที่เขียนอ็อบเจ็กต์แบบอนุกรมลงในไฟล์แล้วสามารถอ่านได้จากไฟล์และ deserialized นั่นคือข้อมูลชนิดและไบต์ที่แสดงถึงอ็อบเจ็กต์และข้อมูลของอ็อบเจ็กต์สามารถใช้เพื่อสร้างอ็อบเจ็กต์ใหม่ในหน่วยความจำ

สิ่งที่น่าประทับใจที่สุดคือกระบวนการทั้งหมดเป็นอิสระจาก JVM ซึ่งหมายความว่าออบเจ็กต์สามารถต่ออนุกรมบนแพลตฟอร์มเดียวและแยกส่วนบนแพลตฟอร์มที่แตกต่างกันโดยสิ้นเชิง

ชั้นเรียน ObjectInputStream และ ObjectOutputStream เป็นสตรีมระดับสูงที่มีวิธีการในการทำให้เป็นอนุกรมและการแยกส่วนของวัตถุ

คลาส ObjectOutputStream มีวิธีการเขียนมากมายสำหรับการเขียนข้อมูลประเภทต่างๆ แต่วิธีการหนึ่งที่โดดเด่น -

public final void writeObject(Object x) throws IOException

วิธีการข้างต้นทำให้วัตถุเป็นอนุกรมและส่งไปยังสตรีมเอาต์พุต ในทำนองเดียวกันคลาส ObjectInputStream มีวิธีการต่อไปนี้สำหรับการแยกส่วนของวัตถุ -

public final Object readObject() throws IOException, ClassNotFoundException

วิธีนี้จะดึง Object ถัดไปออกจากสตรีมและยกเลิกการกำหนดค่าเริ่มต้น ค่าที่ส่งคืนคือ Object ดังนั้นคุณจะต้องแคสต์เป็นประเภทข้อมูลที่เหมาะสม

เพื่อแสดงให้เห็นว่าการทำให้เป็นอนุกรมทำงานอย่างไรใน Java ฉันจะใช้คลาส Employee ที่เราพูดถึงในช่วงต้นของหนังสือเล่มนี้ สมมติว่าเรามีคลาสพนักงานดังต่อไปนี้ซึ่งใช้อินเทอร์เฟซที่ต่อเนื่องได้ -

ตัวอย่าง

public class Employee implements java.io.Serializable {
   public String name;
   public String address;
   public transient int SSN;
   public int number;
   
   public void mailCheck() {
      System.out.println("Mailing a check to " + name + " " + address);
   }
}

โปรดสังเกตว่าสำหรับคลาสที่จะทำให้อนุกรมสำเร็จจะต้องปฏิบัติตามเงื่อนไขสองประการ -

  • คลาสต้องใช้อินเทอร์เฟซ java.io.Serializable

  • ฟิลด์ทั้งหมดในคลาสต้องต่ออนุกรมกันได้ หากฟิลด์ไม่สามารถต่ออนุกรมกันได้จะต้องทำเครื่องหมายtransient.

หากคุณอยากรู้ว่า Java Standard Class สามารถต่ออนุกรมได้หรือไม่ให้ตรวจสอบเอกสารสำหรับคลาส การทดสอบนั้นง่ายมาก: หากชั้นเรียนใช้ java.io.Serializable จะทำให้เป็นอนุกรม มิฉะนั้นก็ไม่ใช่

การทำให้วัตถุเป็นอนุกรม

คลาส ObjectOutputStream ใช้เพื่อทำให้เป็นอนุกรมของวัตถุ โปรแกรม SerializeDemo ต่อไปนี้จะสร้างอินสแตนซ์อ็อบเจ็กต์พนักงานและทำให้เป็นอนุกรมกับไฟล์

เมื่อโปรแกรมเสร็จสิ้นการเรียกใช้ไฟล์ชื่อพนักงานผู้ใช้จะถูกสร้างขึ้น โปรแกรมไม่สร้างผลลัพธ์ใด ๆ แต่ศึกษาโค้ดและพยายามตรวจสอบว่าโปรแกรมกำลังทำอะไรอยู่

Note - เมื่อทำให้ออบเจ็กต์เป็นอนุกรมกับไฟล์แบบแผนมาตรฐานใน Java คือให้ไฟล์เป็นไฟล์ .ser ส่วนขยาย.

ตัวอย่าง

import java.io.*;
public class SerializeDemo {

   public static void main(String [] args) {
      Employee e = new Employee();
      e.name = "Reyan Ali";
      e.address = "Phokka Kuan, Ambehta Peer";
      e.SSN = 11122333;
      e.number = 101;
      
      try {
         FileOutputStream fileOut =
         new FileOutputStream("/tmp/employee.ser");
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         out.writeObject(e);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in /tmp/employee.ser");
      } catch (IOException i) {
         i.printStackTrace();
      }
   }
}

Deserializing วัตถุ

โปรแกรม DeserializeDemo ต่อไปนี้ deserializes อ็อบเจ็กต์พนักงานที่สร้างในโปรแกรม SerializeDemo ศึกษาโปรแกรมและพยายามกำหนดผลลัพธ์ -

ตัวอย่าง

import java.io.*;
public class DeserializeDemo {

   public static void main(String [] args) {
      Employee e = null;
      try {
         FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
         ObjectInputStream in = new ObjectInputStream(fileIn);
         e = (Employee) in.readObject();
         in.close();
         fileIn.close();
      } catch (IOException i) {
         i.printStackTrace();
         return;
      } catch (ClassNotFoundException c) {
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }
      
      System.out.println("Deserialized Employee...");
      System.out.println("Name: " + e.name);
      System.out.println("Address: " + e.address);
      System.out.println("SSN: " + e.SSN);
      System.out.println("Number: " + e.number);
   }
}

สิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -

เอาต์พุต

Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101

ต่อไปนี้เป็นประเด็นสำคัญที่ควรสังเกต -

  • บล็อก try / catch พยายามจับ ClassNotFoundException ซึ่งประกาศโดยเมธอด readObject () เพื่อให้ JVM สามารถ deserialize อ็อบเจ็กต์ได้นั้นต้องสามารถค้นหา bytecode สำหรับคลาสได้ หาก JVM ไม่พบคลาสในระหว่างการดีซีเรียลไลเซชันของอ็อบเจ็กต์มันจะพ่น ClassNotFoundException

  • สังเกตว่าค่าส่งคืนของ readObject () ถูกส่งไปยังการอ้างอิงของพนักงาน

  • ค่าของฟิลด์ SSN คือ 11122333 เมื่ออ็อบเจ็กต์ถูกทำให้เป็นอนุกรม แต่เนื่องจากฟิลด์เป็นแบบชั่วคราวค่านี้จึงไม่ถูกส่งไปยังเอาต์พุตสตรีม ฟิลด์ SSN ของอ็อบเจ็กต์ Deserialized Employee คือ 0