Eclipse ออกคำเตือนเมื่อserialVersionUID
ไม่มีข้อมูล
คลาส Foo ที่ทำให้เป็นอนุกรมไม่ได้ประกาศฟิลด์ serialVersionUID สุดท้ายที่เป็นสแตติกชนิดยาว
อะไรserialVersionUID
และทำไมจึงสำคัญ โปรดแสดงตัวอย่างที่หายไปserialVersionUID
จะทำให้เกิดปัญหา
Eclipse ออกคำเตือนเมื่อserialVersionUID
ไม่มีข้อมูล
คลาส Foo ที่ทำให้เป็นอนุกรมไม่ได้ประกาศฟิลด์ serialVersionUID สุดท้ายที่เป็นสแตติกชนิดยาว
อะไรserialVersionUID
และทำไมจึงสำคัญ โปรดแสดงตัวอย่างที่หายไปserialVersionUID
จะทำให้เกิดปัญหา
คำตอบ:
เอกสารสำหรับjava.io.Serializable
อาจเป็นคำอธิบายที่ดีเกี่ยวกับ:
ความสัมพันธ์รันไทม์ของการทำให้เป็นอนุกรมเชื่อมโยงกับหมายเลขเวอร์ชันของคลาสที่เรียกว่า a
serialVersionUID
ซึ่งถูกใช้ในระหว่างการดีซีเรียลไลเซชันเพื่อตรวจสอบว่าผู้ส่งและผู้รับของวัตถุที่เป็นอนุกรมนั้นได้โหลดคลาสสำหรับวัตถุนั้น หากผู้รับโหลดคลาสสำหรับวัตถุที่มีความแตกต่างserialVersionUID
จากคลาสของผู้ส่งที่สอดคล้องกันการดีซีเรียลInvalidClassException
ไลซ์เซชั่นจะส่งผลให้ คลาสที่สามารถทำให้เป็นอนุกรมสามารถประกาศตัวของมันเองserialVersionUID
อย่างชัดเจนโดยการประกาศชื่อเขตข้อมูลserialVersionUID
ที่จะต้องคงที่สุดท้ายและประเภทlong
:ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
หากคลาสที่ทำให้เป็นอนุกรมไม่ได้ประกาศอย่างชัดเจน
serialVersionUID
ดังนั้นการรันไทม์ของการทำให้เป็นอนุกรมจะคำนวณค่าเริ่มต้นserialVersionUID
สำหรับคลาสนั้นตามแง่มุมต่าง ๆ ของคลาสดังอธิบายใน Java (TM) Object Serialization Specification แต่ก็เป็นที่ขอแนะนำว่าการเรียน serializable ทุกอย่างชัดเจนประกาศserialVersionUID
ค่าตั้งแต่เริ่มต้นserialVersionUID
การคำนวณเป็นอย่างสูงที่มีความสำคัญกับรายละเอียดระดับที่อาจแตกต่างกันไปขึ้นอยู่กับการใช้งานคอมไพเลอร์และทำให้ได้ผลในการที่ไม่คาดคิดInvalidClassExceptions
ในช่วง deserialization ดังนั้นเพื่อรับประกันserialVersionUID
ค่าที่สอดคล้องกันระหว่างการประยุกต์ใช้คอมไพเลอร์ Java ที่แตกต่างกันคลาสที่สามารถต่ออนุกรมserialVersionUID
ได้ ขอแนะนำอย่างชัดเจนด้วยว่าserialVersionUID
การประกาศใช้โมดิฟายเออร์ส่วนตัวถ้าเป็นไปได้เนื่องจากการประกาศเช่นนั้นจะใช้กับserialVersionUID
ฟิลด์คลาสที่ประกาศทันทีเท่านั้นจึงไม่มีประโยชน์ในฐานะสมาชิกที่สืบทอด
ถ้าคุณเป็นซีเรียลไลซ์เซชันเพียงเพราะคุณต้องซีเรียลไลซ์เพื่อประโยชน์ของการใช้งาน (ใครจะสนใจถ้าคุณทำให้เป็นอันดับHTTPSession
สำหรับตัวอย่างเช่น ... ถ้ามันถูกเก็บไว้หรือไม่คุณอาจไม่สนใจde-serializing
วัตถุฟอร์ม) ไม่สนใจสิ่งนี้
หากคุณใช้ซีเรียลไลซ์เซชันจริง ๆ ก็จะเกิดขึ้นก็ต่อเมื่อคุณวางแผนที่จะเก็บและดึงข้อมูลอ็อบเจ็กต์โดยใช้การทำให้เป็นอนุกรมโดยตรง serialVersionUID
แทนรุ่นชั้นเรียนของคุณและคุณควรจะเพิ่มขึ้นถ้ารุ่นปัจจุบันของชั้นเรียนของคุณเข้ากันไม่ได้กับรุ่นก่อนหน้านี้ย้อนหลัง
ส่วนใหญ่คุณอาจไม่ได้ใช้การทำให้เป็นอนุกรมโดยตรง หากเป็นกรณีนี้ให้สร้างค่าเริ่มต้นSerialVersionUID
โดยคลิกตัวเลือกการแก้ไขด่วนและไม่ต้องกังวลกับมัน
serialVersionUID
ปกป้องคุณจากการเปลี่ยนแปลงที่เข้ากันไม่ถูกต้อง การใช้@SuppressWarnings
เอกสารแสดงเจตนาดีกว่าหากคุณไม่ต้องการใช้คลาสสำหรับการจัดเก็บถาวร
serialVersionUID
เป็นทางเลือกสุดท้ายเป็นคำแนะนำแห่งความสิ้นหวัง
ฉันไม่สามารถใช้โอกาสนี้ในการเสียบหนังสือJava Bloch ของEffective Java (2nd Edition) บทที่ 11 เป็นทรัพยากรที่ขาดไม่ได้ในการทำให้เป็นอันดับ Java
ต่อ Josh, UID ที่สร้างขึ้นโดยอัตโนมัติจะถูกสร้างขึ้นตามชื่อคลาสอินเทอร์เฟซที่นำไปใช้งานและสมาชิกสาธารณะและสมาชิกที่ได้รับการป้องกัน การเปลี่ยนแปลงใด ๆ serialVersionUID
เหล่านี้ในทางใดทางหนึ่งจะเปลี่ยน ดังนั้นคุณไม่จำเป็นต้องยุ่งกับพวกเขาก็ต่อเมื่อคุณแน่ใจว่าไม่มีคลาสใดมากกว่าหนึ่งรุ่นที่จะถูกทำให้เป็นอนุกรม
ถ้าคุณไม่สนใจพวกเขาในขณะนี้และพบในภายหลังว่าคุณจำเป็นต้องเปลี่ยนชั้นในบางวิธี แต่ยังคงเข้ากันได้ w / รุ่นเก่าของชั้นที่คุณสามารถใช้เครื่องมือ JDK serialverเพื่อสร้างserialVersionUID
บนเก่าชั้นเรียนและกำหนดอย่างชัดเจนว่า ในชั้นเรียนใหม่ (ขึ้นอยู่กับการเปลี่ยนแปลงของคุณคุณอาจต้องใช้การทำให้เป็นอันดับที่กำหนดเองโดยการเพิ่มwriteObject
และreadObject
วิธีการ - ดูSerializable
javadoc หรือบทที่ 11 ดังกล่าวข้างต้น)
คุณสามารถบอกให้ Eclipse ละเว้นคำเตือน serialVersionUID เหล่านี้:
หน้าต่าง> การตั้งค่า> Java> คอมไพเลอร์> ข้อผิดพลาด / คำเตือน> ปัญหาการเขียนโปรแกรมที่อาจเกิดขึ้น
ในกรณีที่คุณไม่ทราบมีคำเตือนอื่น ๆ อีกมากมายที่คุณสามารถเปิดใช้งานในส่วนนี้ (หรือแม้กระทั่งมีรายงานว่าเป็นข้อผิดพลาด) มีหลายคำเตือนที่มีประโยชน์มาก:
และอื่น ๆ อีกมากมาย.
serialVersionUID
อำนวยความสะดวกในการกำหนดเวอร์ชันของข้อมูลที่ต่อเนื่องกัน ค่าของมันจะถูกเก็บไว้กับข้อมูลเมื่อซีเรียลไลซ์ เมื่อยกเลิกการทำให้เป็นอนุกรมรุ่นเดียวกันจะถูกตรวจสอบเพื่อดูว่าข้อมูลที่เป็นอนุกรมตรงกับรหัสปัจจุบัน
หากคุณต้องการกำหนดรุ่นข้อมูลของคุณโดยปกติแล้วคุณจะเริ่มต้นด้วยserialVersionUID
0 และชนกับการเปลี่ยนแปลงโครงสร้างทุกครั้งในคลาสของคุณซึ่งจะเปลี่ยนแปลงข้อมูลที่เป็นอนุกรม (เพิ่มหรือลบฟิลด์ที่ไม่ใช่แบบชั่วคราว)
กลไกการยกเลิกการทำให้เป็นอนุกรม ( in.defaultReadObject()
) ในตัวจะปฏิเสธที่จะยกเลิกการทำให้เป็นอนุกรมจากข้อมูลรุ่นเก่า แต่ถ้าคุณต้องการคุณสามารถกำหนดฟังก์ชั่นreadObject ()ของคุณเองซึ่งสามารถอ่านข้อมูลเก่าได้ รหัสที่กำหนดเองนี้สามารถตรวจสอบserialVersionUID
เพื่อทราบรุ่นของข้อมูลและตัดสินใจว่าจะยกเลิกการทำให้เป็นอนุกรม เทคนิคการกำหนดเวอร์ชันนี้มีประโยชน์ถ้าคุณเก็บข้อมูลที่ต่อเนื่องกันซึ่งยังคงอยู่ในโค้ดของคุณหลายเวอร์ชัน
แต่การจัดเก็บข้อมูลแบบอนุกรมสำหรับช่วงเวลาที่ยาวนานนั้นไม่ได้เกิดขึ้นบ่อยนัก มันเป็นเรื่องธรรมดามากที่จะใช้กลไกการทำให้เป็นอนุกรมในการเขียนข้อมูลชั่วคราวเช่นแคชหรือส่งผ่านเครือข่ายไปยังโปรแกรมอื่นด้วยเวอร์ชันเดียวกันของส่วนที่เกี่ยวข้องของ codebase
ในกรณีนี้คุณไม่สนใจที่จะรักษาความเข้ากันได้ย้อนหลัง คุณมีส่วนเกี่ยวข้องกับการทำให้แน่ใจว่ารหัสพื้นฐานที่กำลังสื่อสารนั้นมีคลาสที่เกี่ยวข้องรุ่นเดียวกันเท่านั้น เพื่อความสะดวกในการตรวจสอบดังกล่าวคุณต้องดูแลserialVersionUID
เหมือนเดิมและอย่าลืมอัปเดตเมื่อทำการเปลี่ยนแปลงชั้นเรียนของคุณ
หากคุณไม่ลืมที่จะปรับปรุงสนามคุณจะจบลงด้วยสองรุ่นที่แตกต่างกันของชั้นที่มีโครงสร้างแตกต่างกัน serialVersionUID
แต่ด้วยเหมือนกัน หากสิ่งนี้เกิดขึ้นกลไกเริ่มต้น ( in.defaultReadObject()
) จะไม่ตรวจจับความแตกต่างใด ๆ และพยายามยกเลิกการทำให้เป็นอนุกรมข้อมูลที่เข้ากันไม่ได้ ตอนนี้คุณอาจจบลงด้วยข้อผิดพลาดรันไทม์ cryptic หรือความล้มเหลวเงียบ (เขตข้อมูล null) ข้อผิดพลาดประเภทนี้อาจหายาก
ดังนั้นเพื่อช่วย usecase นี้แพลตฟอร์ม Java ให้คุณเลือกที่จะไม่ตั้งค่าserialVersionUID
ด้วยตนเอง แฮชของโครงสร้างคลาสจะถูกสร้างขึ้นในเวลาคอมไพล์และใช้เป็น id กลไกนี้จะตรวจสอบให้แน่ใจว่าคุณไม่เคยมีโครงสร้างคลาสที่แตกต่างด้วย id เดียวกันและดังนั้นคุณจะไม่ได้รับความล้มเหลวของอนุกรมอนุกรมรันไทม์ยากต่อการติดตามดังกล่าวข้างต้น
แต่กลับมีกลยุทธ์การสร้างรหัสอัตโนมัติ คือรหัสที่สร้างขึ้นสำหรับคลาสเดียวกันอาจแตกต่างกันระหว่างคอมไพเลอร์ (ดังที่ Jon Skeet ด้านบน) ดังนั้นหากคุณสื่อสารข้อมูลที่เป็นอนุกรมระหว่างโค้ดที่คอมไพล์ด้วยคอมไพเลอร์ต่าง ๆ แนะนำให้รักษารหัสด้วยตนเองอยู่ดี
และถ้าคุณเข้ากันได้กับข้อมูลของคุณเช่นในกรณีการใช้งานครั้งแรกที่กล่าวถึงคุณอาจต้องการรักษารหัสด้วยตนเอง สิ่งนี้เพื่อให้ได้รหัสที่อ่านได้และมีการควบคุมที่ดีกว่าว่าจะเปลี่ยนแปลงเมื่อใดและอย่างไร
serialVersionUIDคืออะไรและทำไมฉันจึงควรใช้
SerialVersionUID
เป็นตัวระบุที่ไม่ซ้ำกันสำหรับแต่ละคลาสJVM
ใช้เพื่อเปรียบเทียบเวอร์ชันของคลาสเพื่อให้แน่ใจว่าคลาสเดียวกันนั้นถูกใช้ระหว่างการทำให้เป็นอนุกรมถูกโหลดระหว่าง Deserialization
การระบุจะให้การควบคุมมากกว่านั้นแม้ว่า JVM จะสร้างขึ้นมาหากคุณไม่ได้ระบุ ค่าที่สร้างสามารถแตกต่างกันระหว่างคอมไพเลอร์ต่าง นอกจากนี้บางครั้งคุณเพียงต้องการเหตุผลบางอย่างในการห้ามการดีซีเรียลไลเซชันของวัตถุที่เป็นอนุกรมเก่า [ backward incompatibility
] และในกรณีนี้คุณต้องเปลี่ยน serialVersionUID
javadocs สำหรับSerializable
พูด :
การคำนวณอนุกรมVersionUIDเริ่มต้นนั้นมีความไวสูงต่อรายละเอียดของคลาสที่อาจแตกต่างกันไปขึ้นอยู่กับการใช้งานคอมไพเลอร์และอาจส่งผลให้เกิดความไม่คาดคิด
InvalidClassException
ในระหว่างการดีซีเรียลไลเซชัน
ดังนั้นคุณจะต้องประกาศ serialVersionUID เพราะมันทำให้เรามีการควบคุมมากขึ้น
บทความนี้มีจุดที่ดีในหัวข้อ
serialVersionUID
โดยไม่รู้สาเหตุ ความคิดเห็นของ Tom Anderson เกี่ยวกับคำตอบของ MetroidFan2002 กล่าวถึงเรื่องนี้: "ฉันบอกว่าถ้าคุณไม่ได้ใช้ซีเรียลไลซ์เซชั่นสำหรับการจัดเก็บแบบถาวรคุณควรใช้ @SuppressWarnings แทนที่จะเพิ่มมูลค่ามัน clutters ในชั้นเรียนน้อยลง กลไก serialVersionUID เพื่อปกป้องคุณจากการเปลี่ยนแปลงที่เข้ากันไม่ได้ "
serialVersionUID
คือไม่ได้ว่า 'ระบุเฉพาะสำหรับแต่ละชั้น' ชื่อคลาสที่ผ่านการรับรองโดยสมบูรณ์คือ มันเป็นตัวบ่งชี้เวอร์ชัน
คำถามดั้งเดิมได้ถามว่า 'เพราะเหตุใดจึงสำคัญ' และ 'ตัวอย่าง' ซึ่งสิ่งนี้Serial Version ID
จะมีประโยชน์ ฉันได้พบแล้ว
สมมติว่าคุณสร้างCar
คลาสยกตัวอย่างและเขียนลงในสตรีมวัตถุ อ็อบเจ็กต์รถยนต์แบบแบนอยู่ในระบบไฟล์เป็นระยะเวลาหนึ่ง ในขณะเดียวกันถ้าCar
คลาสนั้นได้รับการแก้ไขโดยการเพิ่มฟิลด์ใหม่ ต่อมาเมื่อคุณพยายามอ่าน (เช่นการทำให้หมดเวลา) Car
วัตถุที่แบนคุณจะได้รับjava.io.InvalidClassException
- เนื่องจากคลาสที่ต่อเนื่องได้ทั้งหมดจะได้รับตัวระบุที่ไม่ซ้ำกันโดยอัตโนมัติ ข้อยกเว้นนี้ถูกส่งออกมาเมื่อตัวระบุของคลาสไม่เท่ากับตัวระบุของวัตถุแบน หากคุณคิดเกี่ยวกับมันจริงๆข้อยกเว้นจะถูกโยนเนื่องจากการเพิ่มฟิลด์ใหม่ คุณสามารถหลีกเลี่ยงข้อยกเว้นนี้ได้โดยการควบคุมเวอร์ชันด้วยตัวคุณเองโดยการประกาศ serialVersionUID อย่างชัดเจน นอกจากนี้ยังมีประโยชน์ด้านประสิทธิภาพเล็กน้อยในการประกาศของคุณอย่างชัดเจนserialVersionUID
(เพราะไม่ต้องคำนวณ) ดังนั้นจึงเป็นวิธีที่ดีที่สุดในการเพิ่ม serialVersionUID ของคุณเองในคลาส Serializable ของคุณทันทีที่คุณสร้างพวกเขาดังแสดงด้านล่าง:
public class Car {
static final long serialVersionUID = 1L; //assign a long value
}
1
และอื่น ๆ
ก่อนอื่นฉันต้องอธิบายว่าการทำให้เป็นอนุกรมคืออะไร
การทำให้เป็นอันดับช่วยให้การแปลงวัตถุเป็นกระแสสำหรับการส่งวัตถุนั้นผ่านเครือข่ายหรือบันทึกไปยังไฟล์หรือบันทึกลงในฐานข้อมูลสำหรับการใช้งานจดหมาย
มีกฎระเบียบบางอย่างสำหรับการเป็นอันดับเป็น
วัตถุนั้นสามารถทำให้เป็นอนุกรมได้ถ้าคลาสหรือซูเปอร์คลาสนั้นใช้อินเตอร์เฟสที่สามารถทำให้เป็นอนุกรมได้
วัตถุนั้นสามารถทำให้เป็นอนุกรมได้ (ตัวของมันเองนั้นใช้อินเตอร์เฟซแบบอนุกรมได้) แม้ว่ามันจะไม่ได้เป็นซุปเปอร์คลาส อย่างไรก็ตามซูเปอร์คลาสแรกในลำดับชั้นของคลาสที่ทำให้เป็นอนุกรมซึ่งไม่ได้ใช้อินเตอร์เฟสแบบอนุกรมได้ต้องมีคอนสตรัคเตอร์แบบไม่มีอาร์กิวเมนต์ หากสิ่งนี้ถูกละเมิด readObject () จะสร้าง java.io.InvalidClassException ในรันไทม์
ชนิดดั้งเดิมทั้งหมดจะต่อเนื่องกันได้
เขตข้อมูลชั่วคราว (ที่มีตัวแก้ไขชั่วคราว) จะไม่ต่อเนื่อง (เช่นไม่ได้บันทึกหรือกู้คืน) คลาสที่ใช้งานได้ Serializable ต้องทำเครื่องหมายฟิลด์ชั่วคราวของคลาสที่ไม่สนับสนุนการทำให้เป็นอนุกรม (เช่นสตรีมไฟล์)
ฟิลด์แบบสแตติก (ที่มีตัวแก้ไขแบบสแตติก) จะไม่ต่อเนื่อง
เมื่อObject
มีการต่อเนื่อง, Java Runtime serialVersionID
เชื่อมโยงหมายเลขรุ่นอนุกรมอาคาที่
ตำแหน่งที่เราต้องการ serialVersionID:
ระหว่างการดีซีเรียลไลซ์เซชั่นเพื่อตรวจสอบว่าผู้ส่งและผู้รับเข้ากันได้กับการทำซีเรียลไลเซชั่น หากผู้รับโหลดคลาสที่แตกต่างกันการดีserialVersionID
ซีเรียลInvalidClassCastException
ไลซ์เซชั่นจะจบลงด้วย
คลาสที่ต่อเนื่องกันได้สามารถประกาศตัวของมันเองserialVersionUID
อย่างชัดเจนโดยการประกาศเขตข้อมูลserialVersionUID
ที่จะต้องคงที่สุดท้ายและประเภทยาว
ลองทำตัวอย่างนี้ดู
import java.io.Serializable;
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String empname;
private byte empage;
public String getEmpName() {
return name;
}
public void setEmpName(String empname) {
this.empname = empname;
}
public byte getEmpAge() {
return empage;
}
public void setEmpAge(byte empage) {
this.empage = empage;
}
public String whoIsThis() {
StringBuffer employee = new StringBuffer();
employee.append(getEmpName()).append(" is ).append(getEmpAge()).append("
years old "));
return employee.toString();
}
}
สร้างวัตถุเป็นอันดับ
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Writer {
public static void main(String[] args) throws IOException {
Employee employee = new Employee();
employee.setEmpName("Jagdish");
employee.setEmpAge((byte) 30);
FileOutputStream fout = new
FileOutputStream("/users/Jagdish.vala/employee.obj");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(employee);
oos.close();
System.out.println("Process complete");
}
}
ยกเลิกการทำให้วัตถุเป็นวัตถุ
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Reader {
public static void main(String[] args) throws ClassNotFoundException,
IOException {
Employee employee = new Employee();
FileInputStream fin = new
FileInputStream("/users/Jagdish.vala/employee.obj");
ObjectInputStream ois = new ObjectInputStream(fin);
employee = (Employee) ois.readObject();
ois.close();
System.out.println(employee.whoIsThis());
}
}
หมายเหตุ: ตอนนี้เปลี่ยน serialVersionUID ของระดับพนักงานและบันทึก:
private static final long serialVersionUID = 4L;
และรันคลาส Reader ไม่เรียกใช้งานคลาส Writer และคุณจะได้รับการยกเว้น
Exception in thread "main" java.io.InvalidClassException:
com.jagdish.vala.java.serialVersion.Employee; local class incompatible:
stream classdesc serialVersionUID = 1, local class serialVersionUID = 4
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14)
หากคุณไม่จำเป็นต้องทำให้เป็นอันดับวัตถุของคุณไปยังอาร์เรย์ไบต์และส่ง / เก็บพวกเขาแล้วคุณไม่จำเป็นต้องกังวลเกี่ยวกับมัน หากคุณทำเช่นนั้นคุณต้องพิจารณา serialVersionUID ของคุณเนื่องจากตัว deserializer ของวัตถุจะจับคู่กับเวอร์ชันของวัตถุที่ classloader มีอยู่ อ่านเพิ่มเติมเกี่ยวกับ Java Language Specification
หากคุณได้รับคำเตือนนี้ในชั้นเรียนที่คุณไม่เคยนึกถึงเกี่ยวกับการทำให้เป็นอันดับและคุณไม่ได้ประกาศตัวเองimplements Serializable
มันก็มักจะเป็นเพราะคุณได้รับมรดกจาก Superclass ซึ่งใช้ Serializable บ่อยครั้งจะเป็นการดีกว่าถ้าจะมอบหมายให้วัตถุนั้นแทนที่จะใช้การสืบทอด
ดังนั้นแทนที่จะ
public class MyExample extends ArrayList<String> {
public MyExample() {
super();
}
...
}
ทำ
public class MyExample {
private List<String> myList;
public MyExample() {
this.myList = new ArrayList<String>();
}
...
}
และในวิธีการที่เกี่ยวข้องโทรmyList.foo()
แทนthis.foo()
(หรือsuper.foo()
) (สิ่งนี้ไม่เหมาะสมในทุกกรณี แต่ยังค่อนข้างบ่อย)
ฉันมักจะเห็นคนขยาย JFrame หรือเช่นเมื่อพวกเขาต้องการเพียงมอบหมายให้สิ่งนี้ (สิ่งนี้ยังช่วยในการเติมอัตโนมัติใน IDE เนื่องจาก JFrame มีวิธีการหลายร้อยวิธีซึ่งคุณไม่ต้องการเมื่อคุณต้องการโทรหาคนที่คุณกำหนดเองในชั้นเรียนของคุณ)
กรณีหนึ่งที่คำเตือน (หรือ serialVersionUID) หลีกเลี่ยงไม่ได้คือเมื่อคุณขยายจาก AbstractAction โดยปกติในคลาสที่ไม่ระบุชื่อโดยเพิ่ม actionPerformed-method เท่านั้น ฉันคิดว่าไม่ควรมีคำเตือนในกรณีนี้ (เนื่องจากปกติแล้วคุณไม่สามารถทำให้เป็นอันดับที่เชื่อถือได้และยกเลิกคลาสที่ไม่ระบุชื่อดังกล่าวในรุ่นที่แตกต่างกันของคลาสของคุณ) แต่ฉันไม่แน่ใจว่า
__AUTOLOAD
ซึ่งฉันไม่รู้
เพื่อให้เข้าใจถึงความสำคัญของ field serialVersionUID เราควรเข้าใจว่า Serialization / Deserialization ทำงานอย่างไร
เมื่ออ็อบเจ็กต์คลาส Serializable เป็นอนุกรม Java Runtime เชื่อมโยงกับหมายเลขอนุกรม (เรียกว่าเป็น serialVersionUID) กับอ็อบเจ็กต์ที่ทำให้เป็นอนุกรมนี้ ในขณะที่คุณ deserialize วัตถุ Java ต่อเนื่องนี้ตรงกับ serialVersionUID ของวัตถุที่เป็นอนุกรมกับ serialVersionUID ของชั้นเรียน หากทั้งสองเท่ากันเท่านั้นมันจะดำเนินการกับกระบวนการ deserialization ต่อไปมิฉะนั้นจะโยน InvalidClassException
ดังนั้นเราจึงสรุปได้ว่าการทำให้กระบวนการ Serialization / Deserialization ประสบความสำเร็จ serialVersionUID ของวัตถุที่เป็นอนุกรมจะต้องเทียบเท่ากับ serialVersionUID ของชั้นเรียน ในกรณีที่โปรแกรมเมอร์ระบุค่า serialVersionUID อย่างชัดเจนในโปรแกรมค่าเดียวกันจะเชื่อมโยงกับวัตถุที่เป็นอนุกรมและคลาสโดยไม่คำนึงถึงแพลตฟอร์มซีเรียลไลซ์เซชั่นและ deserialzation MS JVM และ Deserialization อาจอยู่ในแพลตฟอร์ม Linux อื่นโดยใช้ Zing JVM)
แต่ในกรณีที่โปรแกรมเมอร์ไม่ได้ระบุ serialVersionUID ในขณะที่ทำ Serialization \ DeSerialization ของวัตถุใด ๆ , Java runtime ใช้อัลกอริทึมของตัวเองในการคำนวณ อัลกอริทึมการคำนวณ serialVersionUID นี้แตกต่างจาก JRE หนึ่งไปยังอีก อาจเป็นไปได้ว่าสภาพแวดล้อมที่วัตถุถูกทำให้เป็นอนุกรมนั้นใช้ JRE หนึ่งตัว (เช่น JVM) และสภาพแวดล้อมที่ deserialzation เกิดขึ้นกำลังใช้ Linux Jvm (zing) ในกรณีเช่นนี้ serialVersionUID ที่เกี่ยวข้องกับวัตถุที่เป็นอนุกรมจะแตกต่างจาก serialVersionUID ของคลาสที่คำนวณที่สภาพแวดล้อม deserialzation จะไม่ประสบความสำเร็จ ดังนั้นเพื่อหลีกเลี่ยงสถานการณ์ / ปัญหาโปรแกรมเมอร์ต้องระบุ serialVersionUID ของคลาส Serializable
ไม่ต้องกังวลการคำนวณเริ่มต้นนั้นดีมากและพอเพียงสำหรับกรณี 99,9999% และหากคุณพบปัญหาคุณสามารถ - ตามที่ระบุไว้แล้ว - แนะนำ UID's เป็น arrise need (ซึ่งไม่น่าเป็นไปได้สูง)
สำหรับตัวอย่างที่ serialVersionUID ที่หายไปอาจทำให้เกิดปัญหา:
ฉันกำลังทำงานกับแอปพลิเคชัน Java EE นี้ซึ่งประกอบด้วยโมดูลเว็บที่ใช้EJB
โมดูล เว็บโมดูลเรียกใช้EJB
โมดูลจากระยะไกลและส่งผ่านอุปกรณ์POJO
นั้นSerializable
เป็นอาร์กิวเมนต์
นี้ POJO's
คลาสถูกแพ็กเกจภายใน jar EJB และภายใน jar ของมันเองใน WEB-INF / lib ของเว็บโมดูล จริง ๆ แล้วมันเป็นคลาสเดียวกัน แต่เมื่อฉันบรรจุโมดูล EJB ฉันเปิดขวดของ POJO นี้เพื่อรวมเข้ากับโมดูล EJB
การเรียกไปที่EJB
ล้มเหลวด้วยข้อยกเว้นด้านล่างเพราะฉันไม่ได้ประกาศserialVersionUID
:
Caused by: java.io.IOException: Mismatched serialization UIDs : Source
(Rep.
IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
= 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
= 6227F23FA74A9A52
ฉันมักจะใช้serialVersionUID
ในบริบทเดียว: เมื่อฉันรู้ว่ามันจะออกจากบริบทของ Java VM
ฉันจะรู้สิ่งนี้เมื่อฉันใช้ObjectInputStream
และObjectOutputStream
สำหรับแอปพลิเคชันของฉันหรือถ้าฉันรู้ว่าไลบรารี / กรอบงานที่ฉันใช้จะใช้งานได้ serialVersionID ทำให้มั่นใจได้ว่า Java VMs ที่แตกต่างกันของรุ่นที่แตกต่างกันหรือผู้ขายจะทำงานได้อย่างถูกต้องหรือถ้ามันถูกจัดเก็บและดึงข้อมูลภายนอก VM เช่นHttpSession
ข้อมูลเซสชันยังคงอยู่แม้ในระหว่างการรีสตาร์ทและอัพเกรดแอพพลิเคชันเซิร์ฟเวอร์
สำหรับกรณีอื่น ๆ ฉันใช้
@SuppressWarnings("serial")
เนื่องจากเวลาส่วนใหญ่ค่าเริ่มต้นserialVersionUID
ก็เพียงพอแล้ว ซึ่งรวมถึงException
, HttpServlet
.
ข้อมูลภาคสนามแสดงถึงข้อมูลบางอย่างที่เก็บไว้ในชั้นเรียน คลาสใช้Serializable
อินเตอร์เฟสดังนั้น eclipse ถูกเสนอให้ประกาศserialVersionUID
ฟิลด์โดยอัตโนมัติ ให้เริ่มต้นด้วยค่า 1 เซตที่นั่น
หากคุณไม่ต้องการคำเตือนนั้นให้ใช้สิ่งนี้:
@SuppressWarnings("serial")
มันจะดีถ้า CheckStyle สามารถตรวจสอบว่า serialVersionUID ในชั้นเรียนที่ดำเนินการ Serializable มีค่าที่ดีคือว่ามันตรงกับสิ่งที่กำเนิดรุ่น id อนุกรมจะผลิต หากคุณมีโครงการที่มี DTO ที่สามารถทำให้เป็นอนุกรมได้ตัวอย่างเช่นการจำเพื่อลบ serialVersionUID ที่มีอยู่และสร้างใหม่มันเป็นความเจ็บปวดและในปัจจุบันเป็นวิธีเดียว (ที่ฉันรู้) เพื่อยืนยันว่านี่คือการสร้างใหม่สำหรับแต่ละชั้นเรียนและเปรียบเทียบ อันเก่า นี่ช่างเจ็บปวดเหลือเกิน
serialver
จะผลิต -1
serialVersionUID
1 หากคลาสที่ใหม่กว่าของคลาสนั้นไม่เข้ากัน แต่ยังต้องการให้สามารถจัดการข้อมูลเก่าได้คุณต้องเพิ่มหมายเลขรุ่นและเพิ่มรหัสพิเศษ จัดการกับรูปแบบที่เก่ากว่า ฉันร้องไห้ทุกครั้งที่ฉันเห็นตัวเลขที่serialVersionUID
มากกว่า 1 หลักเพราะมันเป็นตัวเลขสุ่ม (ไร้ประโยชน์) หรือเพราะชั้นเรียนต้องจัดการกับรุ่นต่าง ๆ มากกว่า 10 รุ่น
SerialVersionUID ใช้สำหรับการควบคุมเวอร์ชันของวัตถุ คุณสามารถระบุ serialVersionUID ในไฟล์คลาสของคุณได้เช่นกัน ผลที่ตามมาของการไม่ระบุ serialVersionUID คือเมื่อคุณเพิ่มหรือแก้ไขฟิลด์ใด ๆ ในคลาสคลาสที่ต่อเนื่องกันแล้วจะไม่สามารถกู้คืนได้เนื่องจาก serialVersionUID ที่สร้างขึ้นสำหรับคลาสใหม่และสำหรับวัตถุที่เป็นอนุกรมเก่าจะแตกต่างกัน กระบวนการทำให้เป็นอันดับต่อเนื่องของ Java ขึ้นอยู่กับ serialVersionUID ที่ถูกต้องสำหรับการกู้คืนสถานะของวัตถุที่เป็นอนุกรมและพ่น java.io.InvalidClassException ในกรณีที่มีข้อผิดพลาด serialVersionUID
อ่านเพิ่มเติม: http://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ
เหตุใดจึงต้องใช้SerialVersionUID
Inside Serializable
class ใน Java
ในระหว่างserialization
รันไทม์ Java สร้างหมายเลขเวอร์ชันสำหรับคลาสเพื่อให้สามารถยกเลิกการทำให้เป็นอนุกรมในภายหลัง หมายเลขรุ่นนี้เรียกว่าSerialVersionUID
ใน Java
SerialVersionUID
ใช้สำหรับข้อมูลต่อเนื่องรุ่น คุณสามารถยกเลิกการทำให้เป็นอนุกรมคลาสได้ถ้ามันSerialVersionUID
ตรงกับอินสแตนซ์ที่ต่อเนื่องกัน เมื่อเราไม่ประกาศSerialVersionUID
ในคลาสของเราจาวารันไทม์สร้างมันขึ้นมาสำหรับเรา แต่ไม่แนะนำ ขอแนะนำให้ประกาศSerialVersionUID
เป็นprivate static final long
ตัวแปรเพื่อหลีกเลี่ยงกลไกเริ่มต้น
เมื่อคุณประกาศคลาสSerializable
ด้วยการนำอินเตอร์เฟสมาร์java.io.Serializable
กเกอร์อินสแตนซ์ Java ยังคงอินสแตนซ์ของคลาสนั้นลงในดิสก์โดยใช้กลไกการทำให้เป็นอนุกรมที่เป็นค่าเริ่มต้นหากคุณไม่ได้กำหนดกระบวนการเองโดยใช้Externalizable
อินเตอร์เฟส
ดูเพิ่มเติมเหตุใดจึงต้องใช้ SerialVersionUID ภายในคลาสที่สร้างได้ใน Java
ถ้าคุณต้องการแก้ไขคลาสจำนวนมากที่ไม่มี serialVersionUID ตั้งอยู่ในตอนแรกในขณะที่รักษาความเข้ากันได้กับคลาสเก่าเครื่องมือเช่น IntelliJ Idea, Eclipse สั้นเนื่องจากพวกเขาสร้างตัวเลขสุ่มและไม่ทำงานในกลุ่มของไฟล์ ในครั้งเดียว ฉันพบสคริปต์ทุบตีต่อไปนี้ (ฉันขอโทษสำหรับผู้ใช้ Windows พิจารณาซื้อ Mac หรือแปลงเป็น Linux) เพื่อแก้ไขปัญหา serialVersionUID ได้อย่างง่ายดาย:
base_dir=$(pwd)
src_dir=$base_dir/src/main/java
ic_api_cp=$base_dir/target/classes
while read f
do
clazz=${f//\//.}
clazz=${clazz/%.java/}
seruidstr=$(serialver -classpath $ic_api_cp $clazz | cut -d ':' -f 2 | sed -e 's/^\s\+//')
perl -ni.bak -e "print $_; printf qq{%s\n}, q{ private $seruidstr} if /public class/" $src_dir/$f
done
คุณบันทึกสคริปต์นี้พูด add_serialVersionUID.sh กับคุณ ~ / bin จากนั้นคุณเรียกใช้ในไดเรกทอรีรากของโครงการ Maven หรือ Gradle เช่น:
add_serialVersionUID.sh < myJavaToAmend.lst
.lst นี้รวมถึงรายการของไฟล์ java เพื่อเพิ่ม serialVersionUID ในรูปแบบต่อไปนี้:
com/abc/ic/api/model/domain/item/BizOrderTransDO.java
com/abc/ic/api/model/domain/item/CardPassFeature.java
com/abc/ic/api/model/domain/item/CategoryFeature.java
com/abc/ic/api/model/domain/item/GoodsFeature.java
com/abc/ic/api/model/domain/item/ItemFeature.java
com/abc/ic/api/model/domain/item/ItemPicUrls.java
com/abc/ic/api/model/domain/item/ItemSkuDO.java
com/abc/ic/api/model/domain/serve/ServeCategoryFeature.java
com/abc/ic/api/model/domain/serve/ServeFeature.java
com/abc/ic/api/model/param/depot/DepotItemDTO.java
com/abc/ic/api/model/param/depot/DepotItemQueryDTO.java
com/abc/ic/api/model/param/depot/InDepotDTO.java
com/abc/ic/api/model/param/depot/OutDepotDTO.java
สคริปต์นี้ใช้เครื่องมือ JDK serialVer ภายใต้ประทุน ดังนั้นตรวจสอบให้แน่ใจว่า $ JAVA_HOME / bin ของคุณอยู่ในเส้นทาง
คำถามนี้ได้รับการบันทึกไว้เป็นอย่างดีใน Effective Java โดย Joshua Bloch หนังสือที่ดีมากและต้องอ่าน ฉันจะสรุปเหตุผลบางประการด้านล่าง:
รันไทม์ของการทำให้เป็นอนุกรมนั้นมาพร้อมกับหมายเลขที่เรียกว่ารุ่นอนุกรมสำหรับแต่ละคลาสที่สามารถทำให้เป็นอนุกรม หมายเลขนี้เรียกว่า serialVersionUID ขณะนี้มีคณิตศาสตร์บางอย่างที่อยู่เบื้องหลังหมายเลขนี้และมันก็ออกมาตามฟิลด์ / วิธีที่กำหนดไว้ในชั้นเรียน สำหรับคลาสเดียวกันรุ่นเดียวกันจะถูกสร้างขึ้นทุกครั้ง หมายเลขนี้ถูกใช้ระหว่างการดีซีเรียลไลเซชันเพื่อตรวจสอบว่าผู้ส่งและผู้รับของวัตถุที่เป็นอนุกรมได้โหลดคลาสสำหรับวัตถุนั้นที่เข้ากันได้กับการทำซีเรียลไลซ์เซชั่น หากผู้รับโหลดคลาสสำหรับวัตถุที่มี serialVersionUID ที่แตกต่างจากคลาสของผู้ส่งที่สอดคล้องกันการดีซีเรียลไลซ์เซชั่นจะส่งผลให้เกิด InvalidClassException
หากคลาสนั้นสามารถทำให้เป็นอนุกรมคุณสามารถประกาศ serialVersionUID ของคุณเองได้อย่างชัดเจนโดยการประกาศฟิลด์ชื่อ "serialVersionUID" ที่ต้องเป็นแบบสแตติกขั้นสุดท้ายและแบบยาว Eclipse ส่วนใหญ่ของ IDE ช่วยให้คุณสร้างสตริงที่ยาว
แต่ละครั้งที่วัตถุถูกทำให้เป็นอนุกรมวัตถุจะถูกประทับด้วยหมายเลขรหัสรุ่นสำหรับคลาสของวัตถุ ID นี้เรียกว่าserialVersionUIDและคำนวณจากข้อมูลเกี่ยวกับโครงสร้างคลาส สมมติว่าคุณได้สร้างคลาส Employee และมี version id # 333 (กำหนดโดย JVM) ตอนนี้เมื่อคุณจะทำให้เป็นออบเจ็กต์ของคลาสนั้น (สมมติว่าอ็อบเจกต์ Employee) JVM จะกำหนด UID ให้เป็น # 333
พิจารณาสถานการณ์ - ในอนาคตคุณต้องแก้ไขหรือเปลี่ยนคลาสและในกรณีนั้นเมื่อคุณแก้ไข JVM จะกำหนด UID ใหม่ (สมมติว่า # 444) ตอนนี้เมื่อคุณพยายามทำการ deserialize อ็อบเจกต์พนักงาน JVM จะทำการเปรียบเทียบ ID เวอร์ชันของพนักงาน (ออบเจกต์พนักงาน) (# 333) กับของคลาสเช่น # 444 (เนื่องจากมีการเปลี่ยนแปลง) ในการเปรียบเทียบ JVM จะพบว่าทั้งสองเวอร์ชัน UID แตกต่างกันดังนั้น Deserialization จะล้มเหลว ดังนั้นถ้า serialVersionID สำหรับแต่ละคลาสนั้นถูกกำหนดโดยโปรแกรมเมอร์เอง มันจะเหมือนกันแม้ว่าคลาสจะถูกพัฒนาในอนาคตและด้วยเหตุนี้ JVM จะพบว่าคลาสนั้นเข้ากันได้กับออบเจ็กต์ต่อเนื่องแม้ว่าจะเปลี่ยนคลาสแล้วก็ตาม สำหรับข้อมูลเพิ่มเติมคุณสามารถดูบทที่ 14 ของ HEAD FIRST JAVA
serialVersionUID
จะถูกส่ง มันไม่ได้ถูกส่งไปกับทุกวัตถุ
คำอธิบายง่ายๆ:
คุณซีเรียลไลซ์ข้อมูลหรือไม่
การทำให้เป็นอนุกรมนั้นคือการเขียนข้อมูลคลาสไปยังไฟล์ / สตรีม / ฯลฯ การทำให้เป็นอนุกรมกำลังอ่านข้อมูลนั้นกลับไปที่คลาส
คุณตั้งใจจะไปผลิตหรือไม่?
หากคุณเป็นเพียงการทดสอบบางอย่างกับข้อมูลที่ไม่สำคัญ / ข้อมูลปลอมไม่ต้องกังวลเกี่ยวกับมัน (ยกเว้นกรณีที่คุณกำลังทดสอบการทำให้เป็นอนุกรมโดยตรง)
นี่เป็นรุ่นแรกหรือไม่
serialVersionUID=1L
ถ้าเป็นเช่นนั้นชุด
นี่เป็นรุ่นที่สองสามและอื่น ๆ หรือไม่
ตอนนี้คุณต้องกังวลserialVersionUID
และควรมองลึกลงไป
โดยทั่วไปหากคุณไม่อัปเดตเวอร์ชันอย่างถูกต้องเมื่อคุณอัปเดตคลาสที่คุณต้องการเขียน / อ่านคุณจะได้รับข้อผิดพลาดเมื่อคุณพยายามอ่านข้อมูลเก่า
'serialVersionUID' เป็นหมายเลข 64 บิตที่ใช้ในการระบุคลาสในระหว่างกระบวนการดีซีเรียลไลเซชัน เมื่อคุณซีเรียลไลซ์วัตถุ serialVersionUID ของคลาสจะถูกเขียนไปยังไฟล์ เมื่อใดก็ตามที่คุณ deserialize วัตถุนี้เวลารันจาวาแยกค่า serialVersionUID นี้จากข้อมูลที่เป็นอนุกรมและเปรียบเทียบค่าเดียวกันเชื่อมโยงกับชั้นเรียน หากทั้งคู่ไม่ตรงกันดังนั้น 'java.io.InvalidClassException' จะถูกส่งออกไป
ถ้าคลาสที่สามารถทำให้เป็นอนุกรมไม่ได้ประกาศอย่างชัดเจน serialVersionUID จากนั้นรันไทม์แบบอนุกรมจะคำนวณค่า serialVersionUID สำหรับคลาสนั้นตามแง่มุมต่าง ๆ ของคลาสเช่นฟิลด์เมธอดและอื่น ๆ ,, คุณสามารถอ้างอิงลิงค์นี้สำหรับแอปพลิเคชันตัวอย่าง
เพื่อบอกเล่าเรื่องราวโดยย่อฟิลด์นี้ถูกใช้เพื่อตรวจสอบว่าข้อมูลที่ต่อเนื่องกันสามารถถูกดีซีเรียลไลซ์ได้อย่างถูกต้องหรือไม่ การทำซีเรียลไลซ์เซชั่นและดีซีเรียลไลเซชันมักจะทำโดยสำเนาของโปรแกรมที่แตกต่างกัน - ตัวอย่างเช่นเซิร์ฟเวอร์แปลงวัตถุเป็นสตริงและไคลเอนต์จะแปลงสตริงที่ได้รับเป็นวัตถุ ฟิลด์นี้บอกว่าทั้งสองทำงานด้วยแนวคิดเดียวกันเกี่ยวกับวัตถุนี้ ฟิลด์นี้จะช่วยเมื่อ:
คุณมีสำเนาของโปรแกรมต่าง ๆ มากมายในที่ต่าง ๆ (เช่น 1 เซิร์ฟเวอร์และ 100 ไคลเอ็นต์) หากคุณจะเปลี่ยนวัตถุของคุณเปลี่ยนหมายเลขรุ่นของคุณและลืมที่จะอัปเดตหนึ่งไคลเอนต์นี้ก็จะรู้ว่าเขาไม่สามารถ deserialization
คุณได้เก็บข้อมูลของคุณไว้ในไฟล์บางไฟล์แล้วหลังจากนั้นให้ลองเปิดด้วยเวอร์ชันที่อัปเดตของโปรแกรมด้วยวัตถุที่ถูกดัดแปลง - คุณจะรู้ว่าไฟล์นี้เข้ากันไม่ได้หากคุณรักษาเวอร์ชันของคุณไว้อย่างถูกต้อง
มันสำคัญเมื่อไหร่?
ชัดเจนมากที่สุด - ถ้าคุณเพิ่มเขตข้อมูลบางอย่างลงในวัตถุของคุณรุ่นที่เก่ากว่าจะไม่สามารถใช้งานได้เนื่องจากไม่มีเขตข้อมูลเหล่านี้ในโครงสร้างวัตถุ
ชัดเจนน้อยลง - เมื่อคุณ deserialize วัตถุเขตข้อมูลที่ไม่มีอยู่ในสายอักขระจะถูกเก็บเป็น NULL หากคุณลบฟิลด์ออกจากวัตถุของคุณเวอร์ชันเก่าจะเก็บฟิลด์นี้เป็น allways-NULL ที่สามารถนำไปสู่การประพฤติผิดหากเวอร์ชันเก่าใช้ข้อมูลในฟิลด์นี้ (คุณได้สร้างไว้เพื่ออะไรไม่ใช่เพื่อความสนุก :-))
ชัดเจนน้อยที่สุด - บางครั้งคุณเปลี่ยนความคิดที่คุณใส่ในความหมายของบางฟิลด์ ตัวอย่างเช่นเมื่อคุณอายุ 12 ปีคุณหมายถึง "จักรยาน" ภายใต้ "จักรยาน" แต่เมื่อคุณอายุ 18 คุณหมายถึง "มอเตอร์ไซค์" - หากเพื่อนของคุณจะเชิญคุณให้ "ขี่จักรยานข้ามเมือง" และคุณจะเป็นคนเดียวที่ มากับจักรยานคุณจะแยกแยะว่ามันสำคัญแค่ไหนที่จะรักษาความหมายเดิมไว้ในทุ่งนา :-)
ประการแรกเพื่อตอบคำถามของคุณเมื่อเราไม่ประกาศ SerialVersionUID ในคลาสของเรา Java runtime จะสร้างให้เรา แต่กระบวนการนั้นมีความอ่อนไหวต่อข้อมูลเมตาของคลาสจำนวนมากรวมถึงจำนวนฟิลด์ประเภทของฟิลด์ตัวดัดแปลงการเข้าถึงฟิลด์ ตามคลาส ฯลฯ ดังนั้นจึงขอแนะนำให้ประกาศตัวเราเองและ Eclipse จะเตือนคุณเกี่ยวกับสิ่งเดียวกัน
การทำให้เป็นอันดับ: เรามักจะทำงานกับวัตถุสำคัญที่สถานะ (ข้อมูลในตัวแปรของวัตถุ) เป็นสิ่งสำคัญที่เราไม่สามารถเสี่ยงที่จะสูญเสียมันเนื่องจากความล้มเหลวของระบบไฟฟ้า / ระบบ (หรือ) ความล้มเหลวของเครือข่ายในกรณีที่ส่งวัตถุสถานะอื่น ๆ เครื่อง ทางออกสำหรับปัญหานี้มีชื่อว่า "การคงอยู่" ซึ่งหมายถึงการคงอยู่ของข้อมูล การทำให้เป็นอันดับเป็นหนึ่งในวิธีอื่น ๆ อีกหลายวิธีในการคงอยู่ (โดยการบันทึกข้อมูลลงดิสก์ / หน่วยความจำ) เมื่อบันทึกสถานะของวัตถุเป็นสิ่งสำคัญในการสร้างข้อมูลประจำตัวสำหรับวัตถุเพื่อให้สามารถอ่านได้อย่างถูกต้อง (การทำให้เป็นอนุกรม) รหัสเฉพาะนี้คือ ID คือ SerialVersionUID
SerialVersionUID คืออะไร คำตอบ: - ให้บอกว่ามีสองคนหนึ่งคนจาก HQ และอีกคนหนึ่งจาก ODC ทั้งคู่กำลังทำการซีเรียลไลซ์เซชั่นและดีซีเรียลไลเซชันตามลำดับ ในกรณีนี้เพื่อตรวจสอบว่าผู้รับที่อยู่ใน ODC เป็นบุคคลที่ผ่านการตรวจสอบแล้ว JVM สร้าง ID ที่ไม่ซ้ำซึ่งรู้จักกันในชื่อ SerialVersionUID
นี่คือคำอธิบายที่ดีตามสถานการณ์
ทำไมต้อง SerialVersionUID
การทำให้เป็นอันดับ : ในเวลาของการทำให้เป็นอนุกรมกับทุกด้านผู้ส่ง JVM จะบันทึกตัวระบุที่ไม่ซ้ำกัน JVM มีหน้าที่สร้าง ID เฉพาะนั้นตามไฟล์. class ที่เกี่ยวข้องซึ่งมีอยู่ในระบบผู้ส่ง
Deserialization : ในช่วงเวลาของการดีซีเรียลไลเซชั่นฝั่งผู้รับ JVM จะทำการเปรียบเทียบ ID เฉพาะที่เชื่อมโยงกับ Object กับ Unique ID ระดับท้องถิ่นเช่น JVM จะสร้าง Unique ID ตามไฟล์. class ที่เกี่ยวข้องซึ่งมีอยู่ในระบบรับ หาก ID ที่ไม่ซ้ำกันทั้งคู่ตรงกันจะทำการดีซีเรียลไลซ์เซชั่นเท่านั้น มิฉะนั้นเราจะได้รับ Runtime Exception แจ้งว่า InvalidClassException ตัวระบุที่ไม่ซ้ำกันนี้ไม่มีอะไรนอกจาก SerialVersionUID