Java第四周學習日記(緒)

1.靜態導入java

做用:簡化書寫
靜態導入能夠做用一個類的全部靜態成員
靜態導入格式:import static 包名.類名
靜態導入要注意的事項:
若是靜態導入的成員與本類的成員存在同名的狀況下,那麼默認使用本類的靜態成員,若是須要制定使用靜態導入的成員,那麼須要在靜態成員前面加上類名。spring


2.加強for循環
加強for循環的做用,簡化迭代器的書寫格式
加強for循環的適用範圍:若是是實現了Iterabl接口的對象或者是數組對象,,均可以使用加強for循環
加強for循環的格式:
for(變量類型 變量名:遍歷的目標){

}
加強for循環要注意的事項:
1.加強for循環的底層仍是使用了迭代器遍歷,只不過不須要咱們去獲取這個迭代器,因此在使用加強for循環變量元素的過程當中不許使用集合對象對集合的元素個數進行修改。
2.迭代器遍歷元素與加強for循環遍歷元素的區別:使用迭代器遍歷集合的元素時能夠刪除集合的元素,而加強for循環遍歷集合的元素時,不能調用迭代器的remove方法刪除素。
3.普通for循環與加強for循環的區別:普通for循環能夠沒有遍歷的目標,而加強for循環必定要有遍歷的目標。
4.Map集合沒有實現Iterable接口,因此map集合不能直接使用加強for循環,若是須要使用加強for循環,須要藉助與collection的集合遍歷。凡是一個數組對象,內存地址都是以中括號開頭的。數組


3.可變參數
可變參數的格式是:
    數據類型...變量名
可變參數要注意的細節:
    1.若是一個函數的形參使用上了可變參數以後,那麼調用該方法的時候能夠傳遞參數也能夠不傳遞參數。
    2.可變參數其實是一個數組對象。
    3.可變參數必須位於形參中的最後一個。
    4.一個函數最多隻能有一個可變參數,由於可變參數要位於形參中的最後一個的位置

4.自動裝箱和拆箱
自動裝箱:自動把java中的基本數據類型轉換成對象類型的數據。
java是面向對象的語言,任何事物均可以使用類進行描述,sun就使用了一些類
自動拆箱:把引用類型的數據轉換成基本類型的數據。
描述java中八種基本數據類型標準。
基本數據類型    包裝類型
byte                Byte
short              Short
int                  Integer
long                Long
float                Float
double            Double
boolean           Boolean
char               Character

小知識點:Integer類內部維護了緩衝數組,該緩衝數組存儲了-127~128這些數據在一個數組中,若是你獲取的數據是落入到這個範圍以內的,那麼就直接從該緩衝區中獲取對應的數據。


5.枚舉值jvm

  問題:某些方法所接收的數據必須是在固定範圍以內的。ide

  解決方案:自定義一個類,而後私有化構造函數,在自定義類中建立本類的對象來解決。函數

JDK1.5對以上問題提出了新的解決方案,就是使用枚舉類解決。一些方法在運行時,他須要的數據不是任意的,而必須是必定範圍內的值,JDK1.5後採用枚舉類予以解決。測試

枚舉類的定義格式:this

  enum 類名{編碼

      //枚舉值spa

  }

枚舉要注意的細節:

  1.枚舉類也是一個特殊的類。

  2.枚舉值默認的修飾符是public ststic final 。

  3.枚舉值的數據類型是枚舉值所屬的類的數據類型,枚舉值是指向了本類的對象的,其實枚舉值就是枚舉類的對象。

  4.枚舉類的構造方法默認的修飾符是private。

  5.枚舉類能夠定義本身的成員變量與成員函數。

  6.枚舉類能夠自定義構造函數,可是構造函數的修飾符必須是private,不然就能夠隨意建立枚舉類的對象了,失去了枚舉類的存在乎義。

  7.枚舉類能夠存在抽象的方法,可是枚舉值必需要實現抽象的方法。

  8.枚舉值必需要位於枚舉類的第一個語句,不然報錯。

 

枚舉類的應用:

針對狀況:

一些方法在運行時,他須要的數據不是任意的,而必須是必定範圍內的值。

  好比:方向  性別  季節  星期

switch語句使用的類型:

  byte  char  short  int  String  枚舉類型

enum Season{
    spring,summer,autumn,winter;
}

enum Person2{
    student,worker;
}

public eclass Demo8 {
    public static void main(String[] args) {
        Season season = Season.summer;
        switch(season){
            case spring://只須要寫枚舉值便可,不須要再聲明是該枚舉值是屬於哪一個類的。
                System.out.println("春天...");
                break;
            case summer:
                System.out.println("夏天...");
                break;
            case autumn:
                System.out.println("秋天...");
                break;
            case winter:
                System.out.println("冬天...");
                break;        
        }
    }
}

 

IO流(input output)

 

IO技術主要的做用是用於解決設備與設備之間的數據傳輸問題。好比說:鍵盤--->內存  內存的數據--->硬盤  

IO技術的應用場景:

  導出報表,上傳大頭照,下載,解釋xml文件

數據保存到硬盤上,該數據就能夠作到永久性的保存。數據通常是以文件的形式保存到硬盤上的。

因此sun就使用了一個File類描述了文件或文件夾的屬性數據。

(1)File類的構造方法:

File(File parent, String child) (須要操做同一父文件夾下的不一樣文件時,使用此構造方法)
          根據 parent 抽象路徑名和 child 路徑名字符串建立一個新 File 實例。
File(String pathname) 指定文件或文件夾的路徑建立一個File對象。
          經過將給定路徑名字符串轉換爲抽象路徑名來建立一個新 File 實例。
File(String parent, String child)
          根據 parent 路徑名字符串和 child 路徑名字符串建立一個新 File 實例。

 目錄分隔符:

  在Windows機器上的目錄分隔符是\,在Linux機器上的目錄分隔符是/。

  使用File下的separator,該常量返回系統默認的分隔符。

  注意:在Windows上,/和\均可以使用做爲目錄分隔符。並且,若是寫/的時候,只須要寫一個便可。

public class Demo1 {
    public static void main(String[] args) {
        File file = new File("F:"+File.separator+"a.txt"); //  
        File file = new File("F:/a.txt"); 
        File parentFile = new File("F:\\");
        File file = new File("F:\\","a.txt");
        System.out.println("存在嗎 "+ file.exists());  // exists 判斷該文件是否存在,存在返回true。不然返回false
        System.out.println("目錄分隔符"+ File.separator);
    }
}

(2)File類的經常使用方法

路徑問題:

  絕對路徑:該文件在硬盤上的完整路徑,絕對路徑通常都是以盤符開頭的。

  相對路徑:資源文件相對於當前程序所在的路徑。

  .當前路徑

  ..上一級路徑

  注意:若是程序當前所在的路徑與資源文件不是在同一個盤下面,是無法寫相對路徑的。

File方法:

建立:
   createNewFile()    在指定位置建立一個空文件,成功就返回true,若是已存在就不建立而後返回false
        mkdir()            在指定位置建立目錄(單級文件夾),這隻會建立最後一級目錄,若是上級目錄不存在就拋異常。
        mkdirs()        在指定位置建立目錄,這會建立路徑中全部不存在的目錄。
        renameTo(File dest)    重命名文件或文件夾,也能夠操做非空的文件夾,文件不一樣時至關於文件的剪切,剪切時候不能操做非空的文件夾。移動/重命名成功則返回true,失敗則返回false。

import java.io.File;
import java.io.IOException;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        File file = new File("F:\\aa");
        System.out.println("建立成功?+file.createNewFile()); //createNewFile 在指定位置建立一個空文件,成功就返回true,若是已存在就不建立而後返回false
        File dir = new  File("F:\\a.txt");
        System.out.println("建立文件夾"+dir.mkdir()); // mkdir 建立一個文件夾
        dir = new File("F:\\aa\\bb");
        System.out.println("建立多級文件夾"+ dir.mkdirs());
        //renameTo()  若是目標文件與源文件是在同一路徑下,那麼rename做用是重命名,若是目標文件與源文件不是在同一個路徑下,那麼rename的做用就是剪切!並且不能操做文件夾,只能操做文件。
        File destFile = new File("F:\\aaaaaaw");
        System.out.println("重命名成功嗎"+file.renameTo(destFile)) ; 


刪除:
   delete()        刪除文件或一個空文件夾,若是是文件夾且不爲空,則不能刪除,成功返回true,失敗返回false。
       deleteOnExit()    在虛擬機終止時,請求刪除此抽象路徑名錶示的文件或目錄,保證程序異常時建立的臨時文件也能夠被刪除通常用來刪除臨時文件,好比酷狗音樂的在線            試聽文件。
       二者區別:delete方法會立刻刪除一個文件,deleteOnExit在jvm退出時才刪除。
判斷:
   exists()        文件或文件夾是否存在。
        isFile()        是不是一個文件,若是不存在,則始終爲false。
        isDirectory()    是不是一個目錄,若是不存在,則始終爲false。
        isHidden()        是不是一個隱藏的文件或是不是隱藏的目錄。
        isAbsolute()    測試此抽象路徑名是否爲絕對路徑名。
 
獲取:
  getName()        獲取文件或文件夾的名稱,不包含上級路徑。
  getPath()       返回絕對路徑,能夠是相對路徑,可是目錄要指定
  getAbsolutePath()    獲取文件的絕對路徑,與文件是否存在不要緊
  length()        獲取文件的大小(字節數),若是文件不存在則返回0L,若是是文件夾也返回0L。
  getParent()        返回此抽象路徑名父目錄的路徑名字符串;若是此路徑名沒有指定父目錄,則返回null。
  lastModified()    獲取最後一次被修改的時間。
文件夾相關:
  staic File[] listRoots()    列出全部的根目錄(Window中就是全部系統的盤符)
  list()                        返回目錄下的文件或者目錄名,包含隱藏文件。對於文件這樣操做會返回null。
  list(FilenameFilter filter)    返回指定當前目錄中符合過濾條件的子文件或子目錄。對於文件這樣操做會返回null。
  listFiles()                    返回目錄下的文件或者目錄對象(File類實例),包含隱藏文件。對於文件這樣操做會返回null。
  listFiles(FilenameFilter filter)    返回指定當前目錄中符合過濾條件的子文件或子目錄。對於文件這樣操做會返回null。

IO流技術:

 

IO流分類:

  若是是按照數據的流向劃分:

    判斷使用輸入流仍是輸出流的依據:以當前程序做爲一個參照物,觀察數據是流入仍是流出,若是流出則使用輸出流,若是數據是流入,則使用輸入流。

    輸入流

    輸出流

  若是按照處理的單位劃分:

    字節流:讀取的都是文件中的二進制數據,讀取到的二進制數據不會通過任何的處理。

    字符流:字符流讀取的數據是以字符爲單位的,字符流也是讀取文件中的二進制數據,不過會把二進制數據轉換成咱們能識別的字符。

        字符流 = 字節流 +解碼

字節流:

輸入字節流:

————————| InputStream 全部輸入字節流的基類 抽象類

——————————|FileInputStream 讀取文件數據的輸入字節流

使用FileInputStream讀取文件數據的步驟:

  1.找到目標文件

  2.創建數據的輸入通道(FileInputStream對象)  

  3.讀取文件的數據,使用流對象的read()。

  4.關閉資源。

//讀取方式一缺點:沒法讀取完整一個文件的數據
    public static void readTest1() throws IOException{
        //1.找到目標文件
        File file = new File("F:\\a.txt");
        //創建數據的輸入通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //讀取文件中的數據
        int content = fileInputStream.read(); // read() 讀取一個字節的數據,把讀取的數據返回。
        System.out.println("讀到的內容是"+ (char)content);//若不用char強轉,返回的是ascii碼值
        //關閉資源,實際上就是釋放資源
         fileInputStream.close();
    }

//方法二:使用循環讀取文件的數據
    public static void readTest2() throws IOException{
        long startTime = System.currentTimeMillis();
        //找到目標文件
        File file = new File("F:\\1.txt");
        //創建數據的輸入通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //讀取文件的數據
        int content = 0; //
        while((content = fileInputStream.read())!=-1){
            System.out.print((char)content);
        } 
        //關閉資源
        fileInputStream.close();
    }

//方式三:使用緩衝數組讀取    缺點:沒法讀取完整一個文件的數據,由於數組容量有限。
    public static void readTest3() throws IOException{
        //找到目標文件
        File file = new File("F:\\a.txt");
        //創建數據的輸入通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //創建緩衝字節數組,讀取文件數據
        byte[] buf = new byte[1024];  //至關於超市裏面的購物車  緩衝數組的長度通常是1024的倍數,由於與計算機的處理單位相符
        int length = fileInputStream.read(buf); //若是使用read方法讀取數據傳入字節數組,那麼數據是存儲到字節數組中的,而這時候read的返回值表示的是本次讀取了幾個字節數據到字節數組中。
        System.out.println("length:"+ length);
        //使用字節數組構建字符串
        String content = new String(buf,0,length);
        System.out.println("內容"+ content);
        //關閉資源
        fileInputStream.close();
    }    

//方式四:使用緩衝數組配合循環一塊兒讀取
    public static void readTest4() throws IOException{
        long startTime = System.currentTimeMillis();
        //找到目標文件
        File file = new File("F:\1.jpg");
        //創建數據的輸入通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //創建緩衝數組配合循環讀取文件的數據
        int length = 0; //保存每次讀取到的字節個數
        byte[] buf = new byte[1024]; //每次讀取1024個,採起覆蓋的方式  
        while((length = fileInputStream.read(buf))!=-1){ 
            System.out.print(new String(buf,0,length));
        }
        //關閉資源
        fileInputStream.close();
    }

通常使用第四種。

  問題一:讀取完一個文件的數據的時候,是否須要當即釋放資源?

  答案:資源文件一旦使用完畢應該立刻釋放,不然其餘的程序沒法對該資源進行操做。

 

輸出字節流:

————————| OutputStream 是全部輸出字節流的父類。抽象類。

——————————| FileOutputStream 向文件輸出數據的輸出字節流

 

FileOutputStream使用方法:

  1.找到目標文件

  2.創建數據的輸出通道

  3.把數據寫出

  4.關閉資源

    static void writeDate() throws IOException{
        File file = new File("F://1.txt");
        FileOutputStream fileoutputstream = new FileOutputStream(file);
        String a= "abc";
        byte date[] = a.getBytes();
        fileoutputstream.write(date);
    }

FileOutputStream須要注意的細節:

  1.使用FileOutputStream的時候,若是目標文件不存在,那麼會自動建立目標文件對象。

  2.使用FileOutputStream寫數據的時候,若是目標文件已經存在,那麼會先清空目標文件中的數據,而後再寫入數據。(調用另外一構造方法便可,以下)

  3.使用FileOutputStream寫數據的時候,若是目標文件已經存在,須要在原來數據基礎上追加數據的時候應該使用newFileOutputStream(file,true)這一個構造函數

  4.使用FileOutputStream的write方法寫數據的時候,雖然接收的是一個int類型的數據,可是真正寫書的只是一個字節的數據,只是把低八位的二進制數據寫出,其餘二十四位數據所有丟棄。

 

IO異常處理

    public static void readTest() {
        FileInputStream fileInputStream = null;
        try {
            // 找到目標文件
            File file = new File("F:\\aaaaa.txt");
            // 創建數據輸入通道
            fileInputStream = new FileInputStream(file);
            // 創建緩衝數組讀取數據
            byte[] buf = new byte[1024];
            int length = 0;
            while ((length = fileInputStream.read(buf)) != -1) {
                System.out.print(new String(buf, 0, length));
            }
        } catch (IOException e) {
            /*
             * 處理的代碼。首先你要組織後面的代碼執行,並且須要通知調用者這裏出錯了
             * throw new RuntimeException(e);
             * 把IOException傳遞給RuntimeException包裝一次,而後再拋出,這樣作的目的是爲了讓調用者使用邊的更加靈活。e-cause
             */
            System.out.println("讀取文件出錯");
            throw new RuntimeException(e);
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                    System.out.println("關閉資源成功");
                }
            } catch (IOException e) {
                System.out.println("關閉資源失敗");
                throw new RuntimeException(e);
            }
        }
    }
}

 

緩衝輸入字節流:

輸入字節流體系:

————————| InputStream 輸入字節流的基類,抽象。

——————————| FileInputStream 讀取文件數據的輸入字節流。

——————————| BufferedInputStream 緩衝輸入字節流(凡是緩衝字節流都以Buffer開頭)它的出現主要是爲了提升讀取文件數據的效率。

 

其實該類內部只不過是維護了一個8KB字節的數組。

背景:咱們清楚讀取文件數據使用緩衝數組讀取效率更高,sun公司也知道使用緩衝數組讀取效率更高,那麼sunge給咱們提供了一個——緩衝輸入字節流對象,,讓咱們能夠更高效率的讀取文件。

效率提升的緣由:不帶緩衝的操做,每讀一個字節就要寫入一個字節,因爲涉及磁盤的IO操做相比內存的操做要慢不少,因此不帶緩衝的流效率很低,而帶緩衝的流,能夠一次讀不少字節,但不向磁盤中寫入,只是先放到內存裏。等湊夠了緩衝區大小的時候一次性寫入磁盤,這種方式能夠減小磁盤操做次數,速度就會提升不少。

使用BufferedInputStream步驟:

  1.找到目標文件

  2.創建數據的輸入通道 FileInputStream對象

  3.創建緩衝輸入字節流 BufferedInputStream對象,並把FileInputStream傳入。

  4.讀取文件數據

  5.關閉資源

注意:凡是緩衝流,都不具有讀寫文件的能力!!!

    static void readDate() throws IOException{
        FileInputStream fileinputStream = new FileInputStream("F:\\1.txt");
        BufferedInputStream bufferedinputstream = new BufferedInputStream(fileinputStream);
        int content = 0 ;
        while((content =  bufferedinputstream.read())!=-1){
            System.out.println((char)content);
        }
        bufferedinputstream.close();
    }

 

緩衝輸出字節流

————————| OutputStream  全部輸出字節流的基類 抽象類

——————————| FileOutputStream  向文件輸出數據的輸出字節流

——————————| BufferedOutputStream  緩衝輸出字節流  內部也是維護了一個8KB的字節數組而已。

BufferedOutputStream出現的目的是爲了提升寫數據的效率

使用BufferedOutputStream的步驟:

  1.找到目標文件

  2.創建數據的輸出通道

  3.創建緩衝輸出字節流對象

  4.把數據寫出

BufferedOutputStream要注意的細節:

  使用BufferedOutputStream寫數據的時候,它的write方法是先把數據寫到它內部維護的字節數組中。若是須要把數據真正的寫到硬盤上面,如須要調用flush方法(刷新次緩衝的輸出流)或close方法,或者是內部維護的字節數組已經填滿數組的時候。

 

 

字符流

輸入字符流

字節流:字節流讀取的是文件中的二進制數據,讀到的數據並不會幫你轉換成你看得懂的字符。

字符流:字符流會把讀取到的二進制數據進行對應的編碼與解碼工做,字符流=字節流+解碼

輸入字符流:

————————|  Reader 輸入字符流的基類  抽象類

——————————|  FileReader 讀取文件的輸入字符流。

——————————|  BufferedReader 緩衝輸入字符流。緩衝後輸入字符流出現的目的是爲了提升讀取文件字符的效率和拓展了FileReader的功能。

FileReader的用法:

  1.找到目標文件。

  2.創建數據的輸入通道。

  3.讀取字符。

  4.關閉資源。

  可是效率低,使用緩衝數組,每次接受數組容量個數的字符。

    public static void readTest2() throws IOException{
        File file = new File("F:\\1208project\\day21\\src\\day21\\Demo1.java");
        FileReader fileReader = new FileReader(file);
        char[] buf = new char[1024];
        int length = 0 ; 
        while((length = fileReader.read(buf))!=-1){
            System.out.print(new String(buf,0,length));
        }
    }

    public static void readTest1() throws IOException{
        File file = new File("F:\\1208project\\day21\\src\\day21\\Demo1.java");
        FileReader fileReader = new FileReader(file);
        int content = 0 ;
        while((content = fileReader.read())!=-1){ 
            System.out.print((char)content);
        }
        fileReader.close();
    }

 

緩衝輸入字符流

BufferedReader的使用步驟:

  1.找到目標文件。

  2.創建數據的輸入通道。

  3.創建緩衝數組字符流。

  4.讀取數據。

  記住:緩衝流都不具有讀寫文件的能力。

輸出字符流

————————|  Write 輸出字符流的基類  抽象類

——————————|  FileWriter 向文件輸出數據的輸出字符流

——————————|  BufferedWriter 緩衝輸出字符流  緩衝輸出字符流的做用:提升FileWriter的寫數據效率與提升FileWriter的功能。

FileWriter的使用步驟:

  1.找到目標文件

  2.創建數據輸出通道

  3.寫出數據

  4.關閉通道

FileWriter要注意的事項:

  1.使用FileWriter寫數據的時候,FileWriter內部是維護了一個1024個字符數組的,寫數據的時候回先寫入到它內部維護的字符數組中,若是把數據真正寫到硬盤上,須要調用flush或者是close方法或者是填滿了內部的字符數組。

  2.使用FileWriter的時候,若是目標文件不存在,那麼會自動建立目標文件。

  3.使用FileWriter的時候,若是目標文件已經存在了,那麼會默認先清空文件中的數據,而後再寫入數據,;若是須要在原基礎上追加數據,須要使用new FileWriter(File boolean),其中boolean爲true。

  字符流具有了解碼功能,方便不少。

    public static void  writeTest1() throws IOException{
        File file = new File("F:\\a.txt");
        FileWriter fileWriter = new FileWriter(file,true);
        String data = "你們好";
        fileWriter.write(data);  //
//        fileWriter.flush();
        fileWriter.close();
    }

 

FileReader須要注意的事項:

  使用FileReader字符流copy圖片時,會先讀取圖片的每一個值,而後去碼錶中查找對應的字符,而後在讀取該字符,可是當碼錶中沒有改值對應的字符時,會返回一個字節的未知字符對應的數據,會出現原數據與未知字符對應的數據字節長度不對應,這樣就會形成照片損壞。

什麼時候使用字符流,什麼時候使用字節流?依據是什麼?

  1.讀寫字符數據的時候使用字符流。

  2.若是讀寫的數據都不須要轉換成字符的時候,使用字節流。

 

緩衝輸出字符流

緩衝輸出字符流的使用步驟:

  1.找到目標文件

  2.創建數據的輸出通道

  3.創建緩衝輸出流對象

  4.寫出數據

BufferedWriter內部只不過是提供了一個8192長度的字符數據做爲緩衝區而已,拓展了FileWriter功能(newLine)

雖然它的write方法形參是char,可是給字符串便可直接輸出。

模擬註冊登陸界面

 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;


public class Welcome {
    static Scanner scanner = new Scanner(System.in);
    public static void main(String[] args) throws IOException {
        while(true){
            System.out.println("請鍵入指令,a爲註冊,b爲登陸");
            String option = scanner.next();
            if("a".equalsIgnoreCase(option)){
                //System.out.println("註冊");
                reg();
            }
            else if("b".equalsIgnoreCase(option)){
                //System.out.println("登陸");
                login();
            }
            else{
                System.out.println("輸入有誤,請從新輸入");
            }
        }
    }
    
    public static void reg() throws IOException{
        System.out.println("請輸入用戶名");
        String userName = scanner.next();
        System.out.println("請輸入密碼");
        String password = scanner.next();
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("F:\\reg.txt"));
        String info = userName+ " " +password;
        bufferedWriter.write(info);
        bufferedWriter.newLine();
        bufferedWriter.close();
    }
    
    public static void login() throws IOException{
        System.out.println("請輸入用戶名");
        String loginName = scanner.next();
        System.out.println("請輸入登陸密碼");
        String loginPassword = scanner.next();
        BufferedReader bufferedReader = new BufferedReader(new FileReader("F:\\reg.txt"));
        String info = loginName+ " " +loginPassword;
        String line = null;
        boolean isLogin= false;
        while((line=bufferedReader.readLine())!=null){
            if(line.equals(info)){
                isLogin = true;
                break;
            }
        }
        if(isLogin){
            System.out.println("歡迎登錄,登錄成功");
        }
        else{
            System.out.println("該用戶名不存在,請從新註冊");
        }
    }
}

 

 

對象的輸入輸出流

做用:用於寫對象的信息和讀取對象的信息,對象信息一旦寫到文件上那麼對象的信息就能夠作到持久化了。

對象輸出流(ObjectOutputStream)

 

對象輸入輸出流要注意的細節:

  1.若是對象須要被寫出到文件上,那麼對象所屬的類必需要實現Serializable接口,Serializable接口沒有任何的方法,只不過是一個標識接口而已。

  對象的序列化:定義方法把對象的信息寫到硬盤上。注意,寫出來的文件是爲了JVM看的,不是給咱們看的。

  對象的反序列化:把文件中的對象信息讀取出來。

  2.注意:反序列化時建立對象並不會調用構造方法。(對象克隆也不會)因此,建立對象時必定會調用構造方法這句話是錯的!

  3.serialVersionUID是用於記錄class文件的版本信息打印的,serialVersionUID合格數字是經過一個類的類名,成員,包名,工程名算出的一個數字。

  4.使用ObjectInputStream反序列化的時候,ObjectInputStream會先讀取文件中的serialVersionUID,而後與本地的class文件的serialVersionUIDemo進行對比,若是兩個ID號不一致,那麼反序列化就失敗了。

  5.若是序列化與反序列化的時候可能會修改類的成員,那麼最好一開始就給這個類指定一個serialVersionUID,若是一類已經指定了UID,那麼在序列化和反序列化的時候,JVM就不會再算這個UID了。

  6.若是一個對象的某個數據不想被序列化到硬盤上,可使用關鍵字transien修飾。

  7.若是一個類維護了另一個類的引用,那麼另一個類也須要實現serialzable接口。

class Address implements Serializable{
    
    String country; 
    
    String city;
    
    public Address(String country,String city){
        this.country = country;
        this.city = city;
    }
    
}

class User implements Serializable{
    
    private static final long serialVersionUID = 1L;

    String userName ;
    
    String password;
    
    transient int age;  // transient 關鍵字
    
    Address address ;
    

    public User(String userName , String passwrod) {
        this.userName = userName;
        this.password = passwrod;
    }
    
    
    public User(String userName , String passwrod,int age,Address address) {
        this.userName = userName;
        this.password = passwrod;
        this.age = age;
        this.address = address;
    }
    
    @Override
    public String toString() {
        return "名字"+this.userName+ " 密碼"+ this.password+" 年齡"+this.age+"地址"+this.address.city;
    }
}

public class Demo3 {
    
    public static void main(String[] args) throws IOException, Exception {
        writeObj();
//        readObj();
    }
    
    //把文件中的對象信息讀取出來——>對象的反序列化
    public static void readObj() throws  IOException, ClassNotFoundException{
        //找到目標文件
        File file = new File("F:\\obj.txt");
        //創建數據的輸入通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //創建對象的輸入流對象
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        //讀取對象信息
        User user = (User) objectInputStream.readObject(); //
        System.out.println("對象的信息"+ user);
    }
    
    //對象的序列化:定義方法把對象的信息寫到硬盤上
    public static void writeObj() throws IOException{
        //
        Address address = new Address("","");
        User user = new User("admin","123",15,address);
        //找到目標文件
        File file = new File("F:\\obj.txt");
        //創建數據的輸出通道
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        //創建對象的輸入流對象
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        //寫對象信息
        objectOutputStream.writeObject(user);
        //關閉通道
        objectOutputStream.close();
    }
}
相關文章
相關標籤/搜索