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