JavaRush /จาวาบล็อก /Random-TH /การทำให้เป็นอนุกรมและดีซีเรียลไลซ์ใน Java

การทำให้เป็นอนุกรมและดีซีเรียลไลซ์ใน Java

เผยแพร่ในกลุ่ม
สวัสดี! ในการบรรยายวันนี้ เราจะพูดถึงการทำให้เป็นอนุกรมและดีซีเรียลไลเซชันในภาษา Java เริ่มต้นด้วยตัวอย่างง่ายๆ สมมติว่าคุณเป็นผู้สร้างเกมคอมพิวเตอร์ หากคุณเติบโตในยุค 90 และจำเกมคอนโซลในสมัยนั้นได้ คุณอาจรู้ว่าทุกวันนี้ยังขาดสิ่งที่ชัดเจนนั่นคือการบันทึกและโหลดเกม :) ถ้าไม่... ลองจินตนาการดูสิ! ฉันกลัวว่าวันนี้เกมที่ไม่มีโอกาสจะถึงวาระที่จะล้มเหลว! และจริงๆ แล้ว อะไรคือ "การบันทึก" และ "การโหลด" เกม? ตามความหมายปกติแล้ว เราเข้าใจว่ามันคืออะไร: เราต้องการเล่นเกมต่อจากจุดที่เราค้างไว้เมื่อครั้งที่แล้ว ในการทำเช่นนี้ เราได้สร้าง "จุดตรวจสอบ" ซึ่งเราจะใช้ในการโหลดเกม แต่สิ่งนี้หมายความว่าอย่างไร ไม่ใช่ในความหมายในชีวิตประจำวัน แต่ในความหมายของ "โปรแกรมเมอร์"? คำตอบนั้นง่าย: เราบันทึกสถานะของโปรแกรมของเรา สมมติว่าคุณกำลังเล่นเกมกลยุทธ์สำหรับสเปน เกมของคุณมีสถานะ: ใครเป็นเจ้าของดินแดนใด ใครมีทรัพยากรจำนวนเท่าใด ใครเป็นพันธมิตรกับใคร และใครที่อยู่ในภาวะสงคราม และอื่นๆ ข้อมูลนี้ซึ่งเป็นสถานะของโปรแกรมของเราต้องได้รับการบันทึกเพื่อให้สามารถกู้คืนข้อมูลและเล่นเกมต่อได้ในภายหลัง นี่คือสิ่งที่กลไกของการทำให้เป็นอนุกรมและดีซีเรียลไลซ์ ใช้ สำหรับ การทำให้เป็นอนุกรมเป็นกระบวนการจัดเก็บสถานะของวัตถุเป็นลำดับไบต์ การดีซีเรียลไลเซชันเป็นกระบวนการสร้างวัตถุขึ้นใหม่จากไบต์เหล่านี้ วัตถุ Java ใด ๆ จะถูกแปลงเป็นลำดับไบต์ มีไว้เพื่ออะไร? เราได้พูดไปแล้วหลายครั้งว่าไม่มีโปรแกรมอยู่ด้วยตัวมันเอง ส่วนใหญ่แล้วพวกเขาจะโต้ตอบกัน แลกเปลี่ยนข้อมูล ฯลฯ และรูปแบบไบต์ก็สะดวกและมีประสิทธิภาพสำหรับสิ่งนี้ ตัวอย่างเช่น เราสามารถเปลี่ยนคลาสอ็อบเจ็กต์ของเราSavedGame(เกมที่บันทึกไว้) ให้เป็นลำดับไบต์ ถ่ายโอนไบต์เหล่านั้นผ่านเครือข่ายไปยังคอมพิวเตอร์เครื่องอื่น และบนคอมพิวเตอร์เครื่องที่สองก็เปลี่ยนไบต์เหล่านั้นกลับไปเป็นอ็อบเจ็กต์ Java! มันยากที่จะได้ยินใช่ไหม? เห็นได้ชัดว่าการจัดการกระบวนการนี้ไม่ใช่เรื่องง่าย :/ โชคดีที่ไม่! :) ใน Java อินเท อ ร์เฟซ แบบอนุกรมจะรับผิดชอบกระบวนการซีเรียลไลซ์ อินเทอร์เฟซนี้เรียบง่ายมาก: คุณไม่จำเป็นต้องใช้วิธีการเดียวเพื่อใช้งาน! นี่คือลักษณะของคลาสบันทึกเกมของเรา:
import java.io.Serializable;
import java.util.Arrays;

public class SavedGame implements Serializable {

   private static final long serialVersionUID = 1L;

   private String[] territoriesInfo;
   private String[] resourcesInfo;
   private String[] diplomacyInfo;

   public SavedGame(String[] territoriesInfo, String[] resourcesInfo, String[] diplomacyInfo){
       this.territoriesInfo = territoriesInfo;
       this.resourcesInfo = resourcesInfo;
       this.diplomacyInfo = diplomacyInfo;
   }

   public String[] getTerritoriesInfo() {
       return territoriesInfo;
   }

   public void setTerritoriesInfo(String[] territoriesInfo) {
       this.territoriesInfo = territoriesInfo;
   }

   public String[] getResourcesInfo() {
       return resourcesInfo;
   }

   public void setResourcesInfo(String[] resourcesInfo) {
       this.resourcesInfo = resourcesInfo;
   }

   public String[] getDiplomacyInfo() {
       return diplomacyInfo;
   }

   public void setDiplomacyInfo(String[] diplomacyInfo) {
       this.diplomacyInfo = diplomacyInfo;
   }

   @Override
   public String toString() {
       return "SavedGame{" +
               "territoriesInfo=" + Arrays.toString(territoriesInfo) +
               ", resourcesInfo=" + Arrays.toString(resourcesInfo) +
               ", diplomacyInfo=" + Arrays.toString(diplomacyInfo) +
               '}';
   }
}
ชุดข้อมูลสามชุดมีหน้าที่รับผิดชอบข้อมูลเกี่ยวกับเขตแดน เศรษฐศาสตร์ และการทูต และอินเทอร์เฟซแบบซีเรียลไลซ์ได้จะบอกเครื่อง Java ว่า: “ ทุกอย่างโอเค หากมีสิ่งใด อ็อบเจ็กต์ของคลาสนี้สามารถซีเรียลไลซ์ได้ ” อินเทอร์เฟซที่ไม่มีวิธีการใด ๆ ดูแปลก ๆ :/ ทำไมจึงต้องมี? คำตอบสำหรับคำถามนี้อยู่ด้านบน: เพื่อให้ข้อมูลที่จำเป็นแก่เครื่อง Java เท่านั้น ในการบรรยายครั้งก่อน เราได้กล่าวถึงอินเทอร์เฟซของเครื่องหมายสั้นๆ เหล่านี้เป็นอินเทอร์เฟซข้อมูลพิเศษที่ทำเครื่องหมายคลาสของเราด้วยข้อมูลเพิ่มเติมที่จะเป็นประโยชน์กับเครื่อง Java ในอนาคต พวกเขาไม่มีวิธีการใดๆ ที่จำเป็นต้องดำเนินการ ดังนั้น Serializable จึงเป็นหนึ่งในอินเทอร์เฟซดังกล่าว จุดสำคัญอีกประการหนึ่ง: ตัวแปรที่private static final long serialVersionUIDเรากำหนดไว้ในชั้นเรียน เหตุใดจึงจำเป็น? ฟิลด์นี้มีตัวระบุเวอร์ชันเฉพาะของคลาสซีเรียลไลซ์ คลาสใดๆ ที่ใช้อินเทอร์เฟซแบบอนุกรมจะมีตัวระบุเวอร์ชัน คำนวณตามเนื้อหาของคลาส - ฟิลด์, ลำดับการประกาศ, วิธีการ และหากเราเปลี่ยนประเภทฟิลด์และ/หรือจำนวนฟิลด์ในคลาส ตัวระบุเวอร์ชันจะเปลี่ยนทันที serialVersionUID ยังถูกเขียนเมื่อคลาสถูกทำให้เป็นอนุกรม เมื่อเราพยายามดีซีเรียลไลซ์ นั่นคือ กู้คืนอ็อบเจ็กต์จากชุดไบต์ ค่าserialVersionUIDจะถูกเปรียบเทียบกับค่าserialVersionUIDของคลาสในโปรแกรมของเรา หากค่าไม่ตรงกัน java.io.InvalidClassException จะถูกส่งออกไป เราจะเห็นตัวอย่างด้านล่างนี้ เพื่อหลีกเลี่ยงสถานการณ์ดังกล่าว เราเพียงตั้งค่า ID เวอร์ชันนี้สำหรับชั้นเรียนของเราด้วยตนเอง ในกรณีของเรา มันจะเท่ากับ 1 (คุณสามารถแทนที่ตัวเลขอื่น ๆ ที่คุณต้องการได้) ถึงเวลาลองซีเรียลไลซ์อ็อบเจ็กต์ของเราSavedGameแล้วดูว่าจะเกิดอะไรขึ้น!
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Main {

   public static void main(String[] args) throws IOException {

       // create our object
       String[] territoryInfo = {"Spain has 6 provinces", "Russia has 10 provinces", "France has 8 provinces"};
       String[] resourcesInfo = {"Spain has 100 gold", "Russia has 80 gold", "France has 90 gold"};
       String[] diplomacyInfo = {"France is at war with Russia, Spain has taken a position of neutrality"};

       SavedGame savedGame = new SavedGame(territoryInfo, resourcesInfo, diplomacyInfo);

       //create 2 threads to serialize the object and save it to a file
       FileOutputStream outputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);

       // save game to file
       objectOutputStream.writeObject(savedGame);

       // close the stream and release resources
       objectOutputStream.close();
   }
}
อย่างที่คุณเห็น เราได้สร้าง 2 เธรด - FileOutputStreamและObjectOutputStream. ตัวแรกสามารถเขียนข้อมูลลงในไฟล์ได้ และตัวที่สองสามารถแปลงวัตถุเป็นไบต์ได้ คุณเคยเห็นโครงสร้าง "ซ้อนกัน" ที่คล้ายกันแล้วเช่นnew BufferedReader(new InputStreamReader(...))ในการบรรยายครั้งก่อน ๆ ดังนั้นจึงไม่ควรทำให้คุณกลัว :) ด้วยการสร้าง "ลูกโซ่" ของสองเธรดดังกล่าวเราจะดำเนินการทั้งสองงาน: เราเปลี่ยนวัตถุให้SavedGameเป็นชุดไบต์ และบันทึกเป็นไฟล์โดยใช้writeObject()วิธี และอีกอย่าง เราไม่ได้ตรวจสอบด้วยซ้ำว่าเราได้อะไรมา! ได้เวลาดูไฟล์แล้ว! *หมายเหตุ: ไม่จำเป็นต้องสร้างไฟล์ล่วงหน้า หากไม่มีไฟล์ชื่อนั้น ไฟล์นั้นจะถูกสร้างขึ้นโดยอัตโนมัติ* และนี่คือเนื้อหา! ¢н sr SavedGame [ การทูตInfot [Ljava/lang/String;[ resourcesInfoq ~ [ territoriesInfoq ~ xpur [Ljava.lang.String;ТVзй{G xp t pФѕанцвоюет SЃ R оссией, Р˜С ЃРёР° РЅРёСЏ Р·Р°Ряла иозицию нейтѕалитетаuq ~ t "РЈ Р˜СЃРёР°РЅРёРё 100 золотаt Р J R РѕСЃСЃРёРё 80 золотаt !РЈ Фѕанции 90 золотаuq ~ t &РЈ Р˜СЃРαании 6 РёС•РѕРІРёРЅС Р † ёР№t %РЈ РѕСЃСЃРёРё 10 РёС•РѕРІРёРЅС †РёР№t &РЈ ФѕанцРеРё 8 Реѕоввинций อ๊ะ :( ดูเหมือนว่าโปรแกรมของเราใช้งานไม่ได้ :( จริงๆ แล้ว มันใช้งานได้ คุณจำได้ว่าเราถ่ายโอนชุดไบต์ไปยังไฟล์ทุกประการ และ ไม่ใช่แค่วัตถุหรือข้อความ เอาละ นี่คือลักษณะของชุดนี้ :) นี่คือเกมที่เราบันทึกไว้ หากเราต้องการคืนค่าวัตถุดั้งเดิมของเรา นั่นก็คือ โหลดและเล่นเกมต่อจากจุดที่เราค้างไว้ เราต้องการ กระบวนการย้อนกลับ , การดีซีเรียลไลซ์ ... นี่คือลักษณะในกรณีของเรา:
import java.io.*;

public class Main {

   public static void main(String[] args) throws IOException, ClassNotFoundException {

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

       SavedGame savedGame = (SavedGame) objectInputStream.readObject();

       System.out.println(savedGame);
   }
}
และนี่คือผลลัพธ์! SavedGame{territoriesInfo=[สเปนมี 6 จังหวัด รัสเซียมี 10 จังหวัด ฝรั่งเศสมี 8 จังหวัด], resourcesInfo=[สเปนมี 100 เหรียญทอง รัสเซียมี 80 เหรียญทอง ฝรั่งเศสมี 90 เหรียญทอง] DiplomacyInfo=[ฝรั่งเศสกำลังทำสงครามกับรัสเซีย สเปนได้ครอบครองตำแหน่งที่เป็นกลาง]} เยี่ยมมาก! ขั้นแรกเราจัดการเพื่อบันทึกสถานะของเกมของเราลงในไฟล์ จากนั้นจึงกู้คืนจากไฟล์ ตอนนี้เรามาลองทำแบบเดียวกัน แต่ลบSavedGameตัวระบุเวอร์ชันออกจากคลาสของเรา เราจะไม่เขียนคลาสของเราทั้งสองใหม่ โค้ดในนั้นจะเหมือนกัน เราจะSavedGameลบprivate static final long serialVersionUID. นี่คือออบเจ็กต์ของเราหลังจากการทำให้เป็นอนุกรม: ¢н sr SavedGameі€MіuОm‰ [ การทูตInfot [Ljava/lang/String;[ resourcesInfoq ~ [ territoriesInfoq ~ xpur [Ljava.lang.String;ТВзй{G xp t pФѕанция РІРѕСЋРµС] ‚ СЃ Россией, Р˜СЃРёР°РЅРЏР·Р°РЅСЏР»Р° RїРѕР·РёС†РёСЋ нейтѕалитетаuq ~ t "РЈ Р˜СЃРэ ан РёРё 100 Р · олотаt РЈ Р ѕСЃСЃРёРё 80 золотаt !РЈ Фѕанции 90 золотаuq ~ t &РЈ Р˜СЃРёР°РЅРёРё 6 R їС•РѕРІРёРЅС† РёР№t %РЈ РѕСЃСЃРёРё 10 иѕовнинцийt &РЈ Фѕанции 8 иѕоввинцРёРЅА และเมื่อพยายามดีซีเรียลไลซ์ นี่คือสิ่งที่เกิดขึ้น: InvalidClassException: local class inเข้ากันได้กับ : stream classdesc serialVersionUID = - 196410440475012755, local class serialVersionUID = -6675950253085108747 นี่เป็นข้อยกเว้นเดียวกับที่กล่าวไว้ข้างต้น คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ในบทความของนักเรียนคนหนึ่งของเรา อย่างไรก็ตาม เราพลาดจุดสำคัญจุดหนึ่ง เป็นที่ชัดเจนว่าสตริงและพื้นฐาน ทำให้เป็นอนุกรมได้อย่างง่ายดาย: Java มีกลไกบางอย่างในตัวสำหรับสิ่งนี้อย่างแน่นอน แต่จะเกิดอะไรขึ้นถ้าserializable-class ของเรามีเขตข้อมูลที่ไม่แสดงออกในรูปแบบดั้งเดิม แต่เป็นการอ้างถึงวัตถุอื่น ๆ ล่ะ? ตัวอย่าง เช่น เรา มาสร้างคลาสแยกต่างหากเพื่อ TerritoriesInfoทำงานกับคลาสของเราResourcesInfoDiplomacyInfoSavedGame
public class TerritoriesInfo {

   private String info;

   public TerritoriesInfo(String info) {
       this.info = info;
   }

   public String getInfo() {
       return info;
   }

   public void setInfo(String info) {
       this.info = info;
   }

   @Override
   public String toString() {
       return "TerritoriesInfo{" +
               "info='" + info + '\'' +
               '}';
   }
}

public class ResourcesInfo {

   private String info;

   public ResourcesInfo(String info) {
       this.info = info;
   }

   public String getInfo() {
       return info;
   }

   public void setInfo(String info) {
       this.info = info;
   }

   @Override
   public String toString() {
       return "ResourcesInfo{" +
               "info='" + info + '\'' +
               '}';
   }
}

public class DiplomacyInfo {

   private String info;

   public DiplomacyInfo(String info) {
       this.info = info;
   }

   public String getInfo() {
       return info;
   }

   public void setInfo(String info) {
       this.info = info;
   }

   @Override
   public String toString() {
       return "DiplomacyInfo{" +
               "info='" + info + '\'' +
               '}';
   }
}
แต่ตอนนี้เรามีคำถาม: คลาสทั้งหมดเหล่านี้ควรจะเป็น Serializable ถ้าเราต้องการซีเรียลไลซ์คลาสที่เปลี่ยนแปลงไปSavedGame?
import java.io.Serializable;
import java.util.Arrays;

public class SavedGame implements Serializable {

   private TerritoriesInfo territoriesInfo;
   private ResourcesInfo resourcesInfo;
   private DiplomacyInfo diplomacyInfo;

   public SavedGame(TerritoriesInfo territoriesInfo, ResourcesInfo resourcesInfo, DiplomacyInfo diplomacyInfo) {
       this.territoriesInfo = territoriesInfo;
       this.resourcesInfo = resourcesInfo;
       this.diplomacyInfo = diplomacyInfo;
   }

   public TerritoriesInfo getTerritoriesInfo() {
       return territoriesInfo;
   }

   public void setTerritoriesInfo(TerritoriesInfo territoriesInfo) {
       this.territoriesInfo = territoriesInfo;
   }

   public ResourcesInfo getResourcesInfo() {
       return resourcesInfo;
   }

   public void setResourcesInfo(ResourcesInfo resourcesInfo) {
       this.resourcesInfo = resourcesInfo;
   }

   public DiplomacyInfo getDiplomacyInfo() {
       return diplomacyInfo;
   }

   public void setDiplomacyInfo(DiplomacyInfo diplomacyInfo) {
       this.diplomacyInfo = diplomacyInfo;
   }

   @Override
   public String toString() {
       return "SavedGame{" +
               "territoriesInfo=" + territoriesInfo +
               ", resourcesInfo=" + resourcesInfo +
               ", diplomacyInfo=" + diplomacyInfo +
               '}';
   }
}
เรามาตรวจสอบสิ่งนี้ในทางปฏิบัติกันดีกว่า! ปล่อยให้ทุกอย่างเหมือนเดิมในตอนนี้แล้วลองทำให้วัตถุเป็นอนุกรมSavedGame:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Main {

   public static void main(String[] args) throws IOException {

       // create our object
       TerritoriesInfo territoriesInfo = new TerritoriesInfo("Spain has 6 provinces, Russia has 10 provinces, France has 8 provinces");
       ResourcesInfo resourcesInfo = new ResourcesInfo("Spain has 100 gold, Russia has 80 gold, France has 90 gold");
       DiplomacyInfo diplomacyInfo =  new DiplomacyInfo("France is at war with Russia, Spain has taken a position of neutrality");


       SavedGame savedGame = new SavedGame(territoriesInfo, resourcesInfo, diplomacyInfo);

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);

       objectOutputStream.writeObject(savedGame);

       objectOutputStream.close();
   }
}
ผลลัพธ์: ข้อยกเว้นในเธรด "main" java.io.NotSerializableException: DiplomacyInfo ล้มเหลว! ที่จริงแล้วนี่คือคำตอบสำหรับคำถามของเรา เมื่อคุณทำให้วัตถุเป็นอนุกรม วัตถุทั้งหมดที่อ้างอิงในตัวแปรอินสแตนซ์จะถูกทำให้เป็นอนุกรม และถ้าอ็อบเจ็กต์เหล่านั้นอ้างอิงถึงอ็อบเจ็กต์ที่สามด้วย อ็อบเจ็กต์เหล่านั้นก็จะถูกซีเรียลไลซ์ด้วย และไม่มีที่สิ้นสุด คลาสทั้งหมดในห่วงโซ่นี้จะต้องเป็นแบบอนุกรมได้ มิฉะนั้นจะไม่สามารถทำให้เป็นอนุกรมได้และข้อยกเว้นจะถูกส่งออกไป ซึ่งอาจจะสร้างปัญหาได้ในอนาคต เราควรทำอย่างไร เช่น ถ้าเราไม่ต้องการส่วนหนึ่งของคลาสในระหว่างการซีเรียลไลซ์? หรือ ตัวอย่างเช่นTerritoryInfoเราสืบทอดคลาสในโปรแกรมของเราโดยเป็นส่วนหนึ่งของห้องสมุดบางแห่ง อย่างไรก็ตาม ไม่สามารถทำให้เป็นอนุกรมได้ และด้วยเหตุนี้ เราจึงไม่สามารถเปลี่ยนแปลงได้ ปรากฎว่าเราไม่สามารถ เพิ่มฟิลด์ TerritoryInfoให้กับ class ของเราได้ เพราะจะทำให้ทั้งคลาส ไม่สามารถซีเรียลไลซ์ได้! ปัญหา:/ ปัญหาประเภทนี้ได้รับการแก้ไขใน Java โดยใช้คำหลัก หากคุณเพิ่มคีย์เวิร์ดนี้ลงในฟิลด์คลาส ค่าของฟิลด์นี้จะไม่ถูกทำให้เป็นอนุกรม เรามาลองสร้างหนึ่งในฟิลด์ของคลาสของเราหลังจากนั้นเราจะซีเรียลไลซ์และกู้คืนวัตถุหนึ่งรายการ SavedGameSavedGameการทำให้เป็นอนุกรมและดีซีเรียลไลซ์เซชันใน Java - 2transientSavedGame transient
import java.io.Serializable;

public class SavedGame implements Serializable {

   private transient TerritoriesInfo territoriesInfo;
   private ResourcesInfo resourcesInfo;
   private DiplomacyInfo diplomacyInfo;

   public SavedGame(TerritoriesInfo territoriesInfo, ResourcesInfo resourcesInfo, DiplomacyInfo diplomacyInfo) {
       this.territoriesInfo = territoriesInfo;
       this.resourcesInfo = resourcesInfo;
       this.diplomacyInfo = diplomacyInfo;
   }

   //...getters, setters, toString()...
}



import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Main {

   public static void main(String[] args) throws IOException {

       // create our object
       TerritoriesInfo territoriesInfo = new TerritoriesInfo("Spain has 6 provinces, Russia has 10 provinces, France has 8 provinces");
       ResourcesInfo resourcesInfo = new ResourcesInfo("Spain has 100 gold, Russia has 80 gold, France has 90 gold");
       DiplomacyInfo diplomacyInfo =  new DiplomacyInfo("France is at war with Russia, Spain has taken a position of neutrality");


       SavedGame savedGame = new SavedGame(territoriesInfo, resourcesInfo, diplomacyInfo);

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);

       objectOutputStream.writeObject(savedGame);

       objectOutputStream.close();
   }
}


import java.io.*;

public class Main {

   public static void main(String[] args) throws IOException, ClassNotFoundException {

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

       SavedGame savedGame = (SavedGame) objectInputStream.readObject();

       System.out.println(savedGame);

       objectInputStream.close();


   }
}
และนี่คือผลลัพธ์: SavedGame{territoriesInfo=null, resourcesInfo=ResourcesInfo{info='Spain has 100 gold, Russia has 80 gold, France has 90 gold'}, DiplomacyInfo=DiplomacyInfo{info='ฝรั่งเศสกำลังทำสงครามกับรัสเซีย สเปนยึดตำแหน่งที่เป็นกลาง'}} ในเวลาเดียวกัน เราได้รับคำตอบสำหรับคำถามว่าค่าใดที่จะถูกกำหนดให้transientกับฟิลด์ - มันถูกกำหนดค่าเริ่มต้น ในกรณีของวัตถุนี่nullคือ ในยามว่าง คุณสามารถอ่านบทความที่ยอดเยี่ยมเกี่ยวกับการทำให้เป็นอนุกรมได้ นอกจากนี้ยังพูดถึงอินเทอร์เฟซExternalizableซึ่งเราจะพูดถึงในการบรรยายครั้งต่อไป นอกจากนี้ยังมีบทในหัวข้อนี้ในหนังสือ “Head-First Java” ให้ความสนใจด้วย :)
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION