การทำซีเรียลไลซ์แบบกำหนดเอง: writeObject และ readObject
เขียนทับ writeObject และ readObject เพื่อเข้ารหัส บีบอัด หรือจัดการฟิลด์แบบกำหนดเอง
การทำซีเรียลไลซ์แบบกำหนดเอง: writeObject และ readObject เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
เมื่อการซีเรียลไลซ์เริ่มต้นไม่เพียงพอ
การซีเรียลไลซ์เริ่มต้นจะบันทึกฟิลด์ที่ไม่ใช่ transient ทั้งหมดตามสภาพเดิม บางครั้งคุณอาจต้องเข้ารหัส บีบอัด หรือใช้รูปแบบอื่น นั่นคือจุดที่กลไก writeObject / readObject เข้ามามีบทบาท
การประกาศ writeObject
เพิ่มเมธอด private void writeObject(ObjectOutputStream oos) Java จะเรียกใช้เมธอดนี้แทนกลไกเริ่มต้น คุณจึงควบคุมได้อย่างแม่นยำว่าข้อมูลใดจะถูกเขียน
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject(); // write non-transient fields normally
oos.writeUTF(encrypt(this.secret)); // write encrypted secret
}การประกาศ readObject
เพิ่มเมธอด private void readObject(ObjectInputStream ois) Java จะเรียกใช้เมธอดนี้ระหว่างการดีซีเรียลไลซ์ คุณต้องอ่านข้อมูลตามลำดับเดียวกับที่เขียนไว้ทุกประการ
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
ois.defaultReadObject(); // restore non-transient fields
this.secret = decrypt(ois.readUTF()); // decrypt and restore
}ลำดับมีความสำคัญ
สิ่งใดก็ตามที่เขียนใน writeObject ต้องอ่านกลับใน ลำดับเดียวกัน ใน readObject หากลำดับไม่ตรงกันจะเกิด StreamCorruptedException
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.writeInt(version);
oos.writeUTF(data);
}
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
this.version = ois.readInt(); // same order
this.data = ois.readUTF();
}การบีบอัดข้อมูลระหว่างการซีเรียลไลซ์
ห่อสตรีมด้วย GZIPOutputStream ภายใน writeObject เพื่อบีบอัดฟิลด์ขนาดใหญ่ แล้วใช้ GZIPInputStream ภายใน readObject เพื่อคลายการบีบอัด
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (GZIPOutputStream gz = new GZIPOutputStream(bos)) {
gz.write(largePayload.getBytes());
}
oos.writeObject(bos.toByteArray());
}กลไก readResolve
readResolve() จะถูกเรียกหลังการดีซีเรียลไลซ์ ให้คืนค่าอ็อบเจ็กต์ทดแทน ซึ่งมีประโยชน์สำหรับซิงเกิลตันและ enum เพื่อให้แน่ใจว่าหลังการดีซีเรียลไลซ์จะมีอินสแตนซ์อยู่เพียงหนึ่งเดียว
public class AppConfig implements Serializable {
private static final AppConfig INSTANCE = new AppConfig();
private AppConfig() {}
public static AppConfig getInstance() { return INSTANCE; }
private Object readResolve() { return INSTANCE; } // return singleton
}กลไก writeReplace
writeReplace() จะถูกเรียกก่อนการซีเรียลไลซ์ ให้คืนค่าอ็อบเจ็กต์อื่นที่จะถูกซีเรียลไลซ์แทน ซึ่งมีประโยชน์สำหรับรูปแบบพร็อกซีและอ็อบเจ็กต์ตัวแทนสำหรับการซีเรียลไลซ์
private Object writeReplace() {
return new UserProxy(this.id); // serialize a lightweight proxy
}การตรวจสอบฟิลด์ใน readObject
คุณสามารถเพิ่มตรรกะตรวจสอบความถูกต้องภายใน readObject เพื่อปฏิเสธข้อมูลที่ไม่ถูกต้องหรือถูกแก้ไขโดยมิชอบ ซึ่งเป็นส่วนหนึ่งของกลยุทธ์การป้องกันหลายชั้น
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
ois.defaultReadObject();
if (age < 0 || age > 150) {
throw new InvalidObjectException("Invalid age: " + age);
}
}การจัดการการเปลี่ยนแปลงเวอร์ชัน
ใช้ฟิลด์เวอร์ชันใน writeObject เพื่อให้ readObject รองรับทั้งรูปแบบเก่าและใหม่ได้อย่างราบรื่นระหว่างการย้ายระบบ
private static final int SERIAL_VERSION = 2;
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeInt(SERIAL_VERSION);
if (SERIAL_VERSION >= 2) oos.writeUTF(email); // new field
}
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
ois.defaultReadObject();
int v = ois.readInt();
if (v >= 2) this.email = ois.readUTF();
}รูปแบบพร็อกซีสำหรับการซีเรียลไลซ์
แนวทางที่แข็งแกร่งคือ เขียนคลาสภายในแบบ static ที่เป็น private ซึ่งเก็บสถานะเท่าที่จำเป็น จากนั้นใช้ writeReplace เพื่อเขียนพร็อกซี และใช้ readResolve ของพร็อกซีเพื่อสร้างอ็อบเจ็กต์ต้นฉบับกลับคืน
ข้อควรพิจารณาด้านประสิทธิภาพ
การซีเรียลไลซ์แบบกำหนดเองเพิ่มค่าใช้จ่ายจากการเรียกเมธอด แต่สามารถลดขนาดข้อมูลได้อย่างมาก ควรทดสอบประสิทธิภาพก่อนปรับให้เหมาะสม และใช้ Externalizable หากต้องการควบคุมสูงสุด
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ลำดับใน writeObject และ readObject ต้องเป็นอย่างไร
สรุปทบทวน
เขียนทับ writeObject / readObject เพื่อเข้ารหัส บีบอัด หรือใช้รูปแบบกำหนดเอง ใช้ readResolve สำหรับซิงเกิลตัน และอ่านข้อมูลตามลำดับเดียวกับที่เขียนเสมอ
คำถามที่พบบ่อย
บทเรียน “การทำซีเรียลไลซ์แบบกำหนดเอง: writeObject และ readObject” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การทำซีเรียลไลซ์แบบกำหนดเอง: writeObject และ readObject” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การทำซีเรียลไลซ์แบบกำหนดเอง: writeObject และ readObject”
เขียนทับ writeObject และ readObject เพื่อเข้ารหัส บีบอัด หรือจัดการฟิลด์แบบกำหนดเอง คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การทำซีเรียลไลซ์แบบกำหนดเอง: writeObject และ readObject” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พื้นฐานการทำซีเรียลไลซ์ของ Java
- ฟิลด์ transient และ serialVersionUID
- การทำซีเรียลไลซ์แบบกำหนดเอง: writeObject และ readObject
- ทางเลือกสมัยใหม่: JSON และ Protocol Buffers