<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Head First Java學(xué)習(xí):第十四章-序列化和文件

      第十四章 序列化和文件的輸入輸出

      保存對象

       

      1、什么是序列化和反序列化

       

      在編程的世界當(dāng)中,常常有這樣的需求:我們需要將本地已經(jīng)實例化的某個對象,通過網(wǎng)絡(luò)傳遞到其他機器當(dāng)中,為了滿足這種需求,就有了所謂的序列化和反序列化。

      序列化就是,把內(nèi)存中的某個對象壓縮成字節(jié)流的形式;

      反序列化就是,把字節(jié)流轉(zhuǎn)換成內(nèi)存中的對象。

       

      2、把序列化對象寫入文件

      四部曲:

      // 創(chuàng)建出 FileOutputStream
      FileOutputStream fs = new FileOutputStream("foo.ser");
      // 創(chuàng)建ObjectOutputStream
      ObjectOutputStream os = new ObjectOutputStream(fs);
      // 寫入對象
      os.writeObject(myBox);
      // 關(guān)閉ObjectOutputStream
      os.close();

       

      說明:

      stream 串流,把stream連接起來代表源和目的地的連接,即文件和網(wǎng)絡(luò)端口的連接。串流 必須要連接到某處才能算是個串流。

       

      串流一般要倆倆連接才能做出有意義的事情,一個表示連接,一個要被調(diào)用方法。

       

      按照單一設(shè)計原則,每個類做一件事情。

      FileOutputStream 把字節(jié)寫入文件。

      ObjectOutputStream 把對象轉(zhuǎn)換成可以寫入串流的數(shù)據(jù)。

      調(diào)用ObjectOutputStream的writeObject時,對象會被打成stream 送到FileOutputStream,來寫入文件。

       

      3、對象被序列化發(fā)生了什么?

      在堆上的對象,有狀態(tài)即實例變量的值。這些值讓同一類的不同實例有不同意義。

      被序列化的對象,保存了實例變量的值因此之后可以在堆上帶回一模一樣的實例。

       

      實例變量的值和java虛擬機所需要的信息會被保存到文件中,一般是字節(jié)碼或者xml編碼格式文件。

       

      對象的狀態(tài)時什么,有什么需要保存?

      對象的狀態(tài) –—— 實例變量的值

      • 如果是 primitive 主數(shù)據(jù)類型,直接保存
      • 如果是引用其他對象,那所有對象都被保存。

       

      當(dāng)對象被序列化,該對象引用的實例變量也會被序列化。且所有被引用的對象也會被序列化。這些操作都是自動進(jìn)行的。

       

      4、類要被序列化,就要實現(xiàn) Serializable

      objectOutputStream.writeObject(myBox);

      myBox必須要實現(xiàn)序列化,否則執(zhí)行會出問題。

       

      如果序列化的類中,實例變量引用了非序列化的類,執(zhí)行會報錯。

       

      Serializable接口沒有任何方法需要實現(xiàn),唯一目的是申明有實現(xiàn)它的類是可以被序列化的。某個類被序列化,其子類自動可以序列化。

      舉例:

      package chap14;

      import java.io.FileOutputStream;
      import java.io.ObjectOutputStream;
      import java.io.Serializable;

      public class Box implements Serializable {
          private int width;
          private int heigh;

          public void setWidth(int w){
              width = w;
          }
          public void setHeigh(int h){
              heigh = h;
          }

          public static void main(String[] args) {
              Box myBox = new Box();
              myBox.setWidth(6);
              myBox.setHeigh(7);
              try{
                  // 創(chuàng)建出 FileOutputStream
                  FileOutputStream fs = new FileOutputStream("foo.ser");
                  // 創(chuàng)建ObjectOutputStream
                  ObjectOutputStream os = new ObjectOutputStream(fs);
                  // 寫入對象
                  os.writeObject(myBox);
                  // 關(guān)閉ObjectOutputStream
                  os.close();
              }catch (Exception ex){
                  ex.printStackTrace();
              }
          }
      }

       

      5、實例變量不想被序列化,標(biāo)記為 transient 。

      實例變量被標(biāo)記為 transient ,序列化會跳過;

      反序列化會設(shè)置為數(shù)據(jù)類型初始值,如primitive類型是0/0.0/false,引用類型是null。

       

      6、反序列化步驟

      舉例:

      // 1 創(chuàng)建FileInputStream

      FileInputStream fileStream = new FileInputStream("foo.ser");

       

      // 2 創(chuàng)建ObjectInputStream

      ObjectInputStream os = new ObjectInputStream(fileStream);

       

      // 3 讀取對象

      Object one = os.readObject();

      Object two = os.readObject();

       

      // 4 轉(zhuǎn)換對象類型

      GameCharacter elf = (GameCharacter) one;

      GameCharacter troll = (GameCharacter) two;

       

      // 5 關(guān)閉ObjectInputStream

      os.close();

       

      說明:

       

      • 對象從stream中讀出來
      • java虛擬機通過存儲的信息判斷出對象的class類型
      • java虛擬機嘗試尋找和加載對象的類,如果虛擬機找不到或無法加載該類,則java虛擬機會拋出異常
      • 新的對象會被分配帶堆上,但是構(gòu)造函數(shù)不會執(zhí)行。因為執(zhí)行構(gòu)造函數(shù),會把對象的狀態(tài)抹去又變成全新,而這不是我們想要的結(jié)果。我們需要的是對象回到存儲時的狀態(tài)。
      • 如果對象在繼承樹上有個不可序列化的祖先類,則該不可序列化類以及在它之上的類的構(gòu)造函數(shù)(就算是可序列化)都會執(zhí)行。一旦構(gòu)造函數(shù)連鎖啟動之后將無法停止。也就是說,從第一個不可序列化的父類開始,全部都會重新初始狀態(tài)。
      • 對象的實例變量會被還原成序列化時點的狀態(tài)值。transient變量會被賦值null的對象引用,primitive主數(shù)據(jù)類型的默認(rèn)為0/0.0/false等值。

       

      7、FileWriter 將字符串寫入文本文件

      用FileWritrer替代FileOutputStream,但是不會把它連接到 ObjectOutputStream上。

       

      FileWriter b = new FileWriter(“FOO.txt”);

      b.write(“hello foo@”);

      b.close();

       

      8、io.File class

      File 對象代表磁盤上的文件或目錄的路徑名稱,不代表讀取或代表文件中的數(shù)據(jù)

      如:/Users/Kathy/Data/GameFile.txt

       

      File對象可以做的事情

      • 創(chuàng)建出代表現(xiàn)存盤文件的File對象

      舉例:

      File f = new File(“mycode.txt”);

       

      • 建立新的目錄

      舉例:

      File dir = new File(“Chapter7”);

      dir.mkdir();

       

      • 列出目錄下的內(nèi)容

      舉例:

      if(dir.isDirectoy){

      String[] dirContents = dir.list();

      for(int i=0;i<dirContents.length;i++){

          sout(dirContents[i])

      }

      }

       

      • 取得文件或目錄的絕對路徑

      舉例:

      sout(dir.getAbsolutePath());

       

      • 刪除文件或目錄(成功會返回true)

      Boolean isDeleted = f.delete();

       

      9、緩沖區(qū)

      緩沖區(qū)的好處是同時把多個字符串寫入文件,提高效率,節(jié)省了磁盤操作的時間。

      舉例:

      BufferedWriter writer = new BufferedWriter(new FileWriter(aFile));

       

      強制刷新緩沖區(qū)數(shù)據(jù):writer.flush()

       

      10、FileReader 讀取文本文件

       

      以File對象表示文件,以FileReader來執(zhí)行實際的讀取,并用BufferedReader 來讓讀取效率更高。

      讀取以while 循環(huán)來逐行進(jìn)行,一直到readLine()的結(jié)果為null 為止。

       

      舉例:

      package chap14;

      import java.io.*;

      public class ReadFile {
          public static void main(String[] args) {
              try{
                  // File 對象
                  File myFile = new File("/Users/huqiqi/Desktop/JavaStudy/JavaStudyCode/HeadFirstJavaMaster/src/main/java/chap14/MyText.txt");
                  // FileReader 是字符的連接到文本文件的串流
                  FileReader fileReader = new FileReader(myFile);
                  // 將FileReader 鏈接到BufferedReader 以獲取更高的效率。
                  // 它只會在緩沖區(qū)讀空的時候,才會回頭區(qū)磁盤讀取
                  BufferedReader reader = new BufferedReader(fileReader);

                  // 承接所讀取的結(jié)果
                  String line = null;
                  // 讀一行列一行直到?jīng)]有東西可讀取
                  while ((line = reader.readLine())!=null){
                      System.out.println(line);
                  }
                  reader.close();

              }catch (Exception ex){
                  ex.printStackTrace();
              }
          }
      }

       

      結(jié)果:

      hello

      this is a file

      test FileReader

       

      11、String的split()

      舉例:

      String toTest = "what is blue + yellow?/green?";
      String[] result = toTest.split("/");
      for(String token:result){
          System.out.println(token);
      }

      結(jié)果:

      what is blue + yellow?

      green?

       

      說明:String的split() 可以把字符串按照指定參數(shù)拆成兩部分。

       

      12、VersionID:序列化的識別

      目的:做版本控制。

       

      13、使用serialVersionUID

          序列化是將對象的狀態(tài)信息轉(zhuǎn)換成可存儲或傳輸?shù)男问降倪^程。Java的對象保存在JVM的堆內(nèi)存中,如果JVM堆不存在了,那么對象也就跟著消失了。

          序列化提供了一種方案,可以讓你在即使JVM停機的情況下也能把對象保存下來的方案。把Java對象序列化成可存儲或傳輸?shù)男问剑ㄈ缍M(jìn)制流),比如保存到文件中。這樣,當(dāng)再次需要這個對象的時候,從文件中讀取出二進(jìn)制流,再從二進(jìn)制流中反序列化對象。

          虛擬機是否允許反序列化,不僅取決于類路徑和功能代碼是否一致,一個非常重要的一點就是 兩個類的序列化ID是否一致,這個所謂的序列化ID,就是代碼中定義的serialVersionUID。

      posted @ 2022-05-13 00:24  hqq的進(jìn)階日記  閱讀(79)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 被黑人巨大一区二区三区| 免费播放一区二区三区| 激情亚洲内射一区二区三区| 国产日产亚洲系列av| 中文字幕国产精品av| 丰满岳乱妇久久久| 青青热在线精品视频免费观看| 亚洲精品无码久久千人斩| 激情四射激情五月综合网| 国产精品普通话国语对白露脸| 甘肃省| 欧美日韩国产亚洲沙发| 国产精品一区 在线播放| www插插插无码免费视频网站 | 永久免费AV无码网站YY| 亚洲 欧美 综合 另类 中字| 久久亚洲中文字幕伊人久久大| 肉色丝袜足j视频国产| 办公室强奷漂亮少妇视频| 韩国V欧美V亚洲V日本V| 国产精品有码在线观看| 国产精品色一区二区三区| 久久国产精品老女人| 国产亚洲精品VA片在线播放| 一区二区三区AV波多野结衣| 国产老女人免费观看黄A∨片| 国产成人午夜福利院| 亚洲天堂激情av在线| 亚洲国产午夜精品福利| 乡城县| 军人粗大的内捧猛烈进出视频| 欧美色欧美亚洲高清在线视频| 东京热高清无码精品| 在线播放国产精品三级网| 免费专区丝袜调教视频| 亚洲欧美日韩综合一区二区| 成年女人片免费视频播放A| 午夜国产精品福利一二| 亚洲少妇人妻无码视频| 女人下边被添全过视频的网址| 日本国产精品第一页久久|