แนวคิดของ Serialization ใน Java คืออะไร?



บทความนี้จะช่วยให้มีแนวทางที่ครอบคลุมเกี่ยวกับแนวคิดของ Serialization ใน Java พร้อมกับตัวอย่างแบบเรียลไทม์เพื่อความเข้าใจที่ดีขึ้น

Serialization ใน เป็นแนวคิดสำคัญที่เกี่ยวข้องกับการแปลงอ็อบเจ็กต์เป็นไบต์สตรีมเพื่อขนส่งอ็อบเจ็กต์ java จาก Java Virtual Machine เครื่องหนึ่งไปยังอีกเครื่องหนึ่งและสร้างขึ้นใหม่ในรูปแบบดั้งเดิม ฉันจะจัดเรียงเอกสารสำหรับบทความนี้ดังนี้:

Serialization ใน Java คืออะไร?

การทำให้เป็นอนุกรม ใน Java เป็นกระบวนการแปลงรหัส Java วัตถุ เป็น ไบต์สตรีม เพื่อถ่ายโอน Object Code จากเครื่อง Java Virtual เครื่องหนึ่งไปยังอีกเครื่องหนึ่งและสร้างขึ้นใหม่โดยใช้กระบวนการของ Deserialization





Serialization-in-Java-Edureka-Picture-1

ทำไมเราถึงต้องมี Serialization ใน Java เหรอ?

เราต้องการ Serialization ด้วยเหตุผลดังต่อไปนี้:



  • การสื่อสาร : Serialization เกี่ยวข้องกับขั้นตอนของวัตถุ การทำให้เป็นอนุกรม และ การแพร่เชื้อ. สิ่งนี้ทำให้ระบบคอมพิวเตอร์หลายระบบสามารถออกแบบแชร์และดำเนินการกับวัตถุได้พร้อมกัน

  • เก็บเอาไว้ : เวลาที่ใช้ในการสร้างออบเจ็กต์นั้นมากกว่าเมื่อเทียบกับเวลาที่ต้องใช้ในการแยกอนุกรมวัตถุ Serialization ช่วยลดการใช้เวลาโดย เก็บเอาไว้ วัตถุยักษ์

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



  • ข้าม การซิงโครไนซ์ JVM: ข้อได้เปรียบที่สำคัญของ Serialization ก็คือทำงานร่วมกับ JVM ที่แตกต่างกันซึ่งอาจทำงานบนต่างกัน สถาปัตยกรรม หรือ ระบบปฏิบัติการ

  • วิริยะ: สถานะของวัตถุใด ๆ สามารถจัดเก็บได้โดยตรงโดยใช้ Serialization กับมันและเก็บไว้ในไฟล์ ฐานข้อมูล เพื่อที่จะได้ เรียกดูในภายหลัง

เราจะทำให้วัตถุเป็นอนุกรมได้อย่างไร?

ถึง วัตถุ Java คือ ต่อเนื่องกันได้ ถ้าและเฉพาะในกรณีที่คลาสหรือคลาสพาเรนต์ใด ๆ ใช้ java . ผม . ต่อเนื่องได้ อินเทอร์เฟซหรืออินเทอร์เฟซย่อย java.io ถอดเปลี่ยนได้

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

//อินเตอร์เฟซ

แพคเกจ Serial1 นำเข้า java.io คลาสสาธารณะที่ปรับเปลี่ยนได้พนักงานใช้ Serial ได้ {private static final long serialVersionUID = 1L // Serial Version UID int id String name public Employee (int id, String name) {this.id = id this.name = name }}

// ต่ออนุกรม

package Serial1 import java.io. * class คงอยู่ {public static void main (String args []) {try {Employee emp1 = new Employee (20110, 'John') Employee emp2 = new Employee (22110, 'Jerry') Employee emp3 = พนักงานใหม่ (20120, 'Sam') FileOutputStream fout = new FileOutputStream ('output.txt') ObjectOutputStream out = ObjectOutputStream ใหม่ (fout) out.writeObject (emp1) out.writeObject (emp2) out.writeObject (emp3) ออก flush () out.close () System.out.println ('Serialization and Deserialization is is been done')} catch (Exception e) {System.out.println (e)}}}

เอาท์พุต:

Serialization และ Deserialization ดำเนินการสำเร็จแล้ว

Deserialization : เป็นกระบวนการย้อนกลับของ Serialization ที่ Serialized Byte Stream ของอ็อบเจ็กต์จากผู้ส่งถูกสร้างขึ้นใหม่ที่ส่วนรับ

// Deserialise

package Serial1 import java.io. * class Depersist {public static void main (String args []) {ลองใช้ {ObjectInputStream in = new ObjectInputStream (new FileInputStream ('output.txt')) Employee e1 = (Employee) in.readObject ( ) พนักงาน e2 = (พนักงาน) ใน .readObject () พนักงาน e3 = (พนักงาน) in.readObject () System.out.println (e1.id + '' + e1.name) System.out.println (e2.id + '' + e2.name) System.out.println (e3.id + '' + e3.name) in.close ()} catch (ข้อยกเว้นจ) {System.out.println (e)}}}

เอาท์พุต:

20110 ยอห์น
22110 เจอร์รี่

20120 แซม

ข้อดีและข้อเสียของ Serialization ใน Java

ข้อดี:

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

  • ขั้นตอนการทำให้เป็นอนุกรมคือ สากล และนักพัฒนาจากพื้นเพต่างกันก็คุ้นเคยกับมัน

  • ใช้งานง่ายและ ปรับแต่งได้ง่าย

  • สตรีมข้อมูลแบบอนุกรม รองรับการเข้ารหัสการบีบอัดการรับรองความถูกต้อง และ คอมพิวเตอร์ Java ที่ปลอดภัย

  • มีมากมาย เทคโนโลยีที่สำคัญ อาศัยการทำให้เป็นอนุกรม

ข้อเสีย:

  • วัตถุในขณะที่ DeSerialization กลายเป็น เปราะ และไม่แน่ใจว่าจะ DeSerialized ได้อย่างมีประสิทธิภาพ

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

  • ขั้นตอนการทำให้เป็นอนุกรมคือ ไม่มีประสิทธิภาพ ในแง่ของการใช้หน่วยความจำ

  • ไม่นิยมใช้การทำให้เป็นอนุกรมในแอปพลิเคชันที่ต้องการ การเข้าถึงพร้อมกัน ไม่มีข้อกำหนดของ API ของบุคคลที่สาม เนื่องจากการทำให้เป็นอนุกรมไม่มีกลไกควบคุมการเปลี่ยนแปลงใด ๆ ต่อทุก SE

  • ขั้นตอนการทำให้เป็นอนุกรมล้มเหลวในการนำเสนอ การควบคุมแบบละเอียด เพื่อเข้าถึง Objects

ตัวอย่างที่ใช้ได้จริงของ Serialization ใน Java

การทำให้เป็นอนุกรมโดยใช้การสืบทอด

กรณี - 1: หาก Superclass สามารถต่ออนุกรมได้ตามค่าเริ่มต้นคลาสย่อยจะสามารถต่ออนุกรมได้เช่นกัน

ในกรณีนี้ไฟล์ คลาสย่อย สามารถต่ออนุกรมได้ตามค่าเริ่มต้นหากไฟล์ superclass กำลังใช้งานไฟล์ อินเตอร์เฟซที่ต่ออนุกรมได้

package SerializationInheritance import java.io.FileInputStream import java.io.FileOutputStream import java.io.ObjectInputStream import java.io.ObjectOutputStream import java.io คลาสที่ต่อเนื่องได้ A ใช้ Serial ได้ {int i public A (int i) {this.i = i}} คลาส B ขยาย A {int j public B (int i, int j) {super (i) this.j = j}} public class Test {public static void main (String [] args) จะพ่น Exception {B b1 = new B (200,400) System.out.println ('i =' + b1.i) System.out.println ('j =' + b1.j) FileOutputStream fos = FileOutputStream ใหม่ ('abc.ser') ObjectOutputStream oos = ObjectOutputStream ใหม่ (fos) oos.writeObject (b1) oos.close () fos.close () System.out.println ('วัตถุถูกทำให้เป็นอนุกรม') FileInputStream fis = FileInputStream ใหม่ ('abc.ser') ObjectInputStream ois = ObjectInputStream ใหม่ (fis) B b2 = (B) ois.readObject () ois.close () fis.close () System.out.println ('วัตถุถูก deserialized') System.out.println ('i = '+ b2.i) System.out.println (' j = '+ b2.j)}}

เอาท์พุต:

j = 20
วัตถุได้รับการทำให้เป็นอนุกรม
อ็อบเจ็กต์ถูก deserialized
ผม = 200
j = 400

กรณี - 2: คลาสย่อยสามารถต่ออนุกรมได้หากใช้อินเทอร์เฟซที่ต่ออนุกรมได้แม้ว่า Superclass จะไม่ได้ใช้อินเตอร์เฟสแบบอนุกรม

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

แพ็กเกจ SerializationInheritance import java.io.FileInputStream import java.io.FileOutputStream import java.io.ObjectInputStream import java.io.ObjectOutputStream import java.io คลาส superclass แบบต่อเนื่อง {int i public superclass (int i) {this.i = i} public superclass () {i = 50 System.out.println ('Superclass constructor called')}} คลาสย่อยขยายการใช้งาน superclass แบบอนุกรม {int j public subclass (int i, int j) {super (i) this.j = j }} public class test2 {public static void main (String [] args) พ่น Exception {subclass b1 = new subclass (10, 20) System.out.println ('i =' + b1.i) System.out.println ( 'j =' + b1.j) FileOutputStream fos = FileOutputStream ใหม่ ('output.ser') ObjectOutputStream oos = ObjectOutputStream ใหม่ (fos) oos.writeObject (b1) oos.close () fos.close () System.out.println ('วัตถุถูกทำให้เป็นอนุกรม') FileInputStream fis = FileInputStream ใหม่ ('output.ser') ObjectInputStream ois = คลาสย่อย ObjectInputStream (fis) ใหม่ b2 = (คลาสย่อย) ois.readObject ( ) ois.close () fis.close () System.out.println ('วัตถุได้รับการ deserialized แล้ว') System.out.println ('i =' + b2.i) System.out.println ('j =' + b2.j)}}

วัตถุได้รับการทำให้เป็นอนุกรม
ตัวสร้าง Superclass เรียกว่า
อ็อบเจ็กต์ถูก deserialized
ผม = 50
j = 20

กรณี - 3: หากซูเปอร์คลาสสามารถต่ออนุกรมกันได้ แต่เราไม่จำเป็นต้องให้คลาสย่อยต่ออนุกรมกัน

ในกรณีนี้สามารถป้องกันการทำให้เป็นอนุกรมของคลาสย่อยได้โดยการใช้ writeObject () และ readObject () วิธีการในคลาสย่อยและจำเป็นต้องโยน NotSerializableException จากวิธีการเหล่านี้

package SerializationInheritance import java.io.FileInputStream import java.io.FileOutputStream import java.io.IOException import java.io.NotSerializableException import java.io.ObjectInputStream import java.io.ObjectOutputStream import java.io คลาสที่ต่อเนื่องได้ i public Parent (int i) {this.i = i}} class child ขยาย Parent {int j public child (int i, int j) {super (i) this.j = j} private void writeObject (ObjectOutputStream out) พ่น IOException {throw new NotSerializableException ()} โมฆะส่วนตัว readObject (ObjectInputStream in) พ่น IOException {throw new NotSerializableException ()}} public class test3 {public static void main (String [] args) พ่น Exception {child b1 = new child (100, 200) System.out.println ('i =' + b1.i) System.out.println ('j =' + b1.j) FileOutputStream fos = FileOutputStream ใหม่ ('abc.ser') ObjectOutputStream oos = ObjectOutputStream ใหม่ ( fos) oos.writeObject (b1) oos.close () fos.close () System.out.println ('วัตถุ ถูกทำให้เป็นอนุกรม ') FileInputStream fis = FileInputStream ใหม่ (' abc.ser ') ObjectInputStream ois = ObjectInputStream ใหม่ (fis) ลูก b2 = (ลูก) ois.readObject () ois.close () fis.close () System.out println ('Object has been deserialized') System.out.println ('i =' + b2.i) System.out.println ('j =' + b2.j)}}

เอาท์พุต:

ผม = 100
j = 200
ข้อยกเว้นในเธรด 'main' java.io.NotSerializableException
ที่ SerializationInheritance.child.writeObject (test3.java:48)
ที่ sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)

การทำให้เป็นอนุกรมโดยใช้สมาชิกแบบคงที่

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

package stati import java.io. * class StaticSerial ดำเนินการต่ออนุกรมได้ {static int i = 100 public static void main (String ... ar) {StaticSerial ob = new StaticSerial () System.out.println ('ในช่วงเวลาของ Serialization, สมาชิกคงมีค่า: '+ i) ลองใช้ {FileOutputStream fos = new FileOutputStream (' F: File.ser ') ObjectOutputStream oos = new ObjectOutputStream (fos) oos.writeObject (ob) oos.close () i = 99 FileInputStream fis = ใหม่ FileInputStream ('F: File.ser') ObjectInputStream ois = ObjectInputStream ใหม่ (fis) ob = (StaticSerial) ois.readObject () ois.close () System.out.println ('หลังจาก Deserialization สมาชิกคงมีค่า:' + i)} catch (ข้อยกเว้นจ) {System.out.println (e)}}}

เอาท์พุต:

ในช่วงเวลาของการทำให้เป็นอนุกรมสมาชิกแบบคงที่มีค่า: 100
หลังจาก Deserialization สมาชิกคงมีค่า: 99

อินเทอร์เฟซภายนอกได้

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

อินเทอร์เฟซภายนอกสามารถใช้งานได้ใน java.io และมีสองวิธี:

  • โมฆะสาธารณะ writeExternal (ObjectOutput out) พ่น IOException
  • โมฆะสาธารณะ readExternal (ObjectInput in) พ่น IOException

ความแตกต่างที่สำคัญระหว่าง Serialization และ Externalizeable มีดังนี้:

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

  • วิธีการ : อินเทอร์เฟซที่ปรับเปลี่ยนได้ประกอบด้วยสองวิธี ได้แก่ :

    • เขียนภายนอก ()

    • อ่านภายนอก ()

ในขณะที่การเชื่อมต่อแบบอนุกรมไม่รวมวิธีการใด ๆ

  • กระบวนการ: กระบวนการทำให้เป็นอนุกรมในอินเตอร์เฟสภายนอกได้ให้ การปรับแต่ง ไปยังกระบวนการทำให้เป็นอนุกรม แต่ Serialization Interface จะให้ไฟล์ ค่าเริ่มต้น กระบวนการทำให้เป็นอนุกรม

  • ความเข้ากันได้ย้อนหลังและการควบคุม: อินเทอร์เฟซภายนอกได้รองรับ Serialization โดยไม่คำนึงถึง การควบคุมเวอร์ชัน และปัญหาเดียวคือผู้ใช้ต้องรับผิดชอบในขณะที่ทำให้ Super Class เป็นอนุกรม ในทางกลับกัน Serialization Interface ต้องใช้ รุ่นเดียวกัน ของ JVM ที่ปลายทั้งสองข้าง แต่รวมเอาการทำให้เป็นอนุกรมอัตโนมัติของวัตถุและคลาสทั้งหมดรวมถึงซูเปอร์คลาส

  • ตัวสร้าง No-Arg สาธารณะ: ความต้องการอินเตอร์เฟสภายนอก ตัวสร้าง No-Arg สาธารณะ เพื่อสร้างวัตถุต่อเนื่องใหม่ ในขณะที่ Serialization Interface ไม่จำเป็นต้องใช้ No-Arg Constructor แต่จะใช้ การสะท้อนกลับ เพื่อสร้างวัตถุหรือคลาสที่ต่อเนื่องกันใหม่

package ext import java.io. * class Demo ใช้ java.io.Serializable {public int a public String b public Demo (int a, String b) {this.a = a this.b = b}} class Test {public static เป็นโมฆะ main (String [] args) {Demo object = new Demo (1, 'Welcome to Edureka') String filename = 'file.ser' ลองใช้ {FileOutputStream file = new FileOutputStream (filename) ObjectOutputStream out = new ObjectOutputStream (file) out .writeObject (object) out.close () file.close () System.out.println ('Object has been serialized')} catch (IOException ex) {System.out.println ('IOException is caught')} Demo object1 = null ลองใช้ {FileInputStream file = new FileInputStream (filename) ObjectInputStream in = new ObjectInputStream (file) object1 = (Demo) in.readObject () in.close () file.close () System.out.println ('Object has been deserialized ') System.out.println (' a = '+ object1.a) System.out.println (' b = '+ object1.b)} catch (IOException ex) {System.out.println (' IOException ถูกจับ ')} catch (ClassNotFoundException ex) {System.out .println ('ClassNotFoundException ถูกจับได้')}}

คีย์เวิร์ดชั่วคราว

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

UID เวอร์ชันอนุกรม

ก่อนที่กระบวนการของการทำให้เป็นอนุกรมจะเริ่มขึ้นคลาส / อ็อบเจ็กต์ที่ต่ออนุกรมได้ทุกตัวจะเชื่อมโยงกับ a หมายเลขประจำตัวที่ไม่ซ้ำกัน จัดทำโดย JVM ของเครื่องโฮสต์ รหัสเฉพาะนี้เรียกว่า UID เวอร์ชันอนุกรม . UID นี้ใช้เป็นการระบุโดย JVM ของจุดสิ้นสุดการรับเพื่อยืนยันว่าอ็อบเจ็กต์เดียวกันกำลังถูก DeSerialized ที่จุดสิ้นสุดการรับ

ข้อถกเถียงของ Serialization ใน Java

Oracle’s สถาปนิกตั้งใจที่จะลบ Serialization ออกจาก Java เนื่องจากถือว่าเป็นไฟล์ ความผิดพลาดที่น่ากลัวของปี 1997 . หลังจากการวิจัยที่น่าตื่นเต้นนักพัฒนาของ Oracle พบข้อบกพร่องบางประการในการออกแบบขั้นตอนการทำให้เป็นอนุกรมซึ่งเป็นภัยคุกคามต่อข้อมูล

ในปี พ.ศ. 2540Mark Reinhold รัฐ -“ เราชอบเรียกการทำให้เป็นอนุกรมว่า 'ของขวัญที่ให้กันเรื่อย ๆ ' และประเภทของของขวัญที่มอบให้ก็คือช่องโหว่ด้านความปลอดภัย อาจเป็นหนึ่งในสามของช่องโหว่ Java ทั้งหมดที่เกี่ยวข้องกับการทำให้เป็นอนุกรมซึ่งอาจเกินครึ่งหนึ่ง มันเป็นแหล่งที่มาของช่องโหว่ที่น่าอัศจรรย์ไม่ต้องพูดถึงความไม่แน่นอน”

ค้นหาจำนวนที่มากที่สุดในอาร์เรย์

มีโอกาสที่ Serialization จะถูกลบหรือแทนที่ในการอัปเดต Java ที่กำลังจะมาถึงและในทางกลับกันสำหรับผู้เริ่มต้นใน Java Serialization ไม่สามารถ เป็นตัวเลือกในอุดมคติ ในโครงการของพวกเขา

แนวทางปฏิบัติที่ดีที่สุดขณะใช้ Serialization ใน Java

ต่อไปนี้เป็นแนวทางปฏิบัติที่ดีที่สุดบางประการที่ต้องปฏิบัติตาม

  • ขอแนะนำให้ใช้ javadoc @ แท็กอนุกรมสำหรับแสดงเขตข้อมูลที่ต่ออนุกรมได้
  • .เป็น ควรใช้นามสกุลสำหรับไฟล์ที่เป็นตัวแทนของวัตถุที่ทำให้เป็นอนุกรม
  • ไม่แนะนำให้ใช้ฟิลด์สถิตหรือชั่วคราวใด ๆ การทำให้เป็นอนุกรมเริ่มต้น
  • ชั้นเรียนที่ขยายได้ ไม่ควรต่ออนุกรมเว้นแต่จะเป็น บังคับ
  • ชั้นใน ควรหลีกเลี่ยงที่จะมีส่วนร่วมใน Serialization

ด้วยเหตุนี้เราจึงมาถึงจุดสิ้นสุดของบทความนี้ ฉันหวังว่าคุณจะเข้าใจพื้นฐานของ Serialization ใน Java ประเภทและฟังก์ชันการทำงานของมัน

ตรวจสอบไฟล์ โดย Edureka บริษัท การเรียนรู้ออนไลน์ที่เชื่อถือได้ซึ่งมีเครือข่ายผู้เรียนที่พึงพอใจมากกว่า 250,000 คนกระจายอยู่ทั่วโลก หลักสูตรการฝึกอบรมและการรับรอง Java J2EE และ SOA ของ Edureka ออกแบบมาสำหรับนักเรียนและผู้เชี่ยวชาญที่ต้องการเป็น Java Developer หลักสูตรนี้ออกแบบมาเพื่อให้คุณเริ่มต้นการเขียนโปรแกรม Java และฝึกอบรมแนวคิด Java ทั้งหลักและขั้นสูงพร้อมกับกรอบงาน Java ต่างๆเช่น Hibernate & ฤดูใบไม้ผลิ .

มีคำถามสำหรับเรา? พูดถึงในส่วนความคิดเห็นของบทความ“ Serialization in Java” และเราจะติดต่อกลับโดยเร็วที่สุด