0Pricing
Java Academy · บทเรียน

ฟิลด์ transient และ serialVersionUID

ยกเว้นฟิลด์ที่มีข้อมูลละเอียดอ่อนด้วย transient และรักษาความเข้ากันได้ระหว่างเวอร์ชันด้วย serialVersionUID

ฟิลด์ transient และ serialVersionUID เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงใช้ transient

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

public class Session implements Serializable {
    private String username;
    private transient String password;   // NOT serialized
    private transient Connection dbConn; // NOT serialized
}

ค่าของฟิลด์ transient หลังการดีซีเรียลไลซ์

หลังการดีซีเรียลไลซ์ ฟิลด์ transient จะได้รับค่าเริ่มต้นของ Java ได้แก่ null สำหรับอ็อบเจ็กต์ 0 สำหรับตัวเลข และ false สำหรับค่าบูลีน

Session s = (Session) ois.readObject();
System.out.println(s.username);  // "alice"
System.out.println(s.password);  // null  (transient)

serialVersionUID คืออะไร

serialVersionUID เป็นค่าคงที่ชนิด long ที่ทำหน้าที่เป็นตราประทับเวอร์ชัน หากคลาสมีการเปลี่ยนแปลงและ UID ไม่ตรงกับค่าในไฟล์ การดีซีเรียลไลซ์จะโยน InvalidClassException

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
}

UID ที่สร้างอัตโนมัติกับ UID ที่ระบุเอง

หากละเว้น serialVersionUID Java จะสร้างค่าหนึ่งขึ้นจากโครงสร้างของคลาส การเปลี่ยนแปลงฟิลด์ใด ๆ จะเปลี่ยน UID โดยไม่มีการแจ้งเตือน ทำให้ข้อมูลเก่าใช้ไม่ได้ ควรประกาศค่าอย่างชัดเจนเสมอ

import java.io.ObjectStreamClass;
long uid = ObjectStreamClass.lookup(User.class).getSerialVersionUID();
System.out.println(uid); // e.g. 3526749255685047947

InvalidClassException เมื่อเวอร์ชันไม่ตรงกัน

เมื่ออ่านข้อมูลที่ซีเรียลไลซ์ไว้ในอดีตด้วยคลาสที่ UID เปลี่ยนไป Java จะโยน InvalidClassException: local class incompatible: stream classdesc serialVersionUID = X, local class serialVersionUID = Y

การพัฒนาคลาสอย่างปลอดภัย

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

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private String email; // Added in v2 — safe if UID unchanged
}

transient กับการเริ่มต้นแบบเลื่อนเวลา

รูปแบบที่พบได้ทั่วไปคือ กำกับฟิลด์ที่เก็บค่าแคชหรือค่าที่คำนวณมาเป็น transient แล้วคำนวณค่าใหม่แบบเลื่อนเวลาหลังการดีซีเรียลไลซ์โดยใช้ readResolve หรือภายในเมธอดอ่านค่า

public class Document implements Serializable {
    private static final long serialVersionUID = 1L;
    private String content;
    private transient int wordCount = -1;
    public int getWordCount() {
        if (wordCount == -1) wordCount = content.split("\\s+").length;
        return wordCount;
    }
}

ฟิลด์แบบคงที่ไม่เคยถูกซีเรียลไลซ์

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

public class Counter implements Serializable {
    private static final long serialVersionUID = 1L;
    private static int instanceCount = 0; // NOT serialized
    private int value;
}

การใช้เครื่องมือ serialver

เครื่องมือ serialver ของ JDK จะแสดงค่า serialVersionUID เริ่มต้นของคลาส: serialver com.example.User ใช้เครื่องมือนี้เพื่อรับค่าก่อนนำไปประกาศอย่างชัดเจน

Externalizable เป็นทางเลือก

Externalizable ขยายความสามารถของ Serializable และให้คุณควบคุมได้อย่างเต็มที่ผ่าน writeExternal / readExternal ซึ่งมีประโยชน์เมื่อต้องการควบคุมฟิลด์อย่างชัดเจนโดยไม่ใช้ transient

public class Config implements Externalizable {
    private String host;
    private transient String secret;
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(host);
    }
    public void readExternal(ObjectInput in) throws IOException {
        host = in.readUTF();
    }
}

แนวทางปฏิบัติที่ดีที่สุด

ประกาศ serialVersionUID เสมอ กำกับรหัสผ่าน ตัวจัดการทรัพยากร และแคชด้วย transient เพิ่มค่า UID เมื่อทำการเปลี่ยนแปลงที่เข้ากันไม่ได้ และจัดทำเอกสารประวัติเวอร์ชัน

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ฟิลด์ชนิด int ที่เป็น transient มีค่าเท่าใดหลังการดีซีเรียลไลซ์

สรุปทบทวน

ใช้ transient เพื่อยกเว้นฟิลด์จากการซีเรียลไลซ์ ประกาศ serialVersionUID เสมอเพื่อควบคุมการกำหนดเวอร์ชัน ฟิลด์แบบคงที่จะไม่ถูกซีเรียลไลซ์ไม่ว่าในกรณีใด

คำถามที่พบบ่อย

บทเรียน “ฟิลด์ transient และ serialVersionUID” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ฟิลด์ transient และ serialVersionUID” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ฟิลด์ transient และ serialVersionUID”

ยกเว้นฟิลด์ที่มีข้อมูลละเอียดอ่อนด้วย transient และรักษาความเข้ากันได้ระหว่างเวอร์ชันด้วย serialVersionUID คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “ฟิลด์ transient และ serialVersionUID” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐานการทำซีเรียลไลซ์ของ Java
  2. ฟิลด์ transient และ serialVersionUID
  3. การทำซีเรียลไลซ์แบบกำหนดเอง: writeObject และ readObject
  4. ทางเลือกสมัยใหม่: JSON และ Protocol Buffers
← กลับไปที่ Java Academy