日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

JavaSE——IO(下)(Properties类、序列化与反序列化)

發布時間:2024/7/23 java 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaSE——IO(下)(Properties类、序列化与反序列化) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第3節 IO(下)

一、.properties文件與Properties類

1.1 .properties文件介紹

.properties文件一種屬性文件,以鍵值對 的格式存儲內容,在Java中可以使用Properties類來讀取這個文件,一般來說它作為一些參數的存儲,作為配置文件使用。

1.2 Properties類

它是Hashtable的子類,使用鍵值對來存儲數據。

構造方法:

方法:

1、根據鍵獲取值:

2、將鍵值對打印到指定的輸出流:

3、從輸入字節流或字符流中讀取全部內容:

4、返回所有鍵的枚舉:

5、新增鍵值對:

6、存儲到字節輸出流或字符輸出流,comment是備注,寫在存儲文件的開頭:

7、返回所有的值,以Set類型:

看個例子:

package com.kaikeba.coreclasslibrary.io;import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.util.Properties;public class properties {public static void main(String[] args) throws IOException {//.properties文件與Properties類//新建一個Properties對象Properties ppt = new Properties();//新建鍵值對ppt.setProperty("name","三體");ppt.setProperty("info","科幻小說");//要寫入的字符流FileWriter fw = new FileWriter("book.properties");//往fw中存儲該鍵值對集合的對象,備注為"存儲的圖書"ppt.store(fw, "存儲的圖書");fw.close();//從.properties文件讀取屬性Properties ppt2 = new Properties();Reader r = new FileReader("book.properties");ppt2.load(r);System.out.println(ppt.get("name"));System.out.println(ppt.get("info"));} }輸出為: 三體 科幻小說

且book.properties文件中存儲的內容為:

最上面是備注信息,使用了Unicode編碼。

二、序列化與反序列化

Java序列化是指把java對象轉換為字節序列的過程 ,Java反序列化是指把字節序列恢復為java對象的過程通過序列化和反序列化實現網絡傳輸、本地存儲的目的

2.1 Serializable實現Java序列化

要實現java對象的序列化,只要將類實現標識接口 ——Serializable接口即可,不需要我們重寫任何方法就可以實現序列化。

編寫書籍類:

package com.kaikeba.coreclasslibrary.io.serializable;import java.io.Serializable;public class Book implements Serializable {private String name;private String info;private Person user;@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", info='" + info + '\'' +", user=" + user +'}';}public Book() {}public Book(String name, String info, Person user) {this.name = name;this.info = info;this.user = user;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}public Person getUser() {return user;}public void setUser(Person user) {this.user = user;} }

編寫借書人類:注意Book中有Person類的對象屬性,所以Person類也要實現Serializable接口

package com.kaikeba.coreclasslibrary.io.serializable;import java.io.Serializable;public class Person implements Serializable {private String name;private int age;@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;} }

編寫序列化和反序列化:

package com.kaikeba.coreclasslibrary.io.serializable;import java.io.*;public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException {//序列化Person p = new Person("smile", 23);Book b = new Book("三體", "科幻小說", p);ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("b.txt"));oos.writeObject(b);oos.close();//反序列化ObjectInputStream ois = new ObjectInputStream(new FileInputStream("b.txt"));Book book = (Book) ois.readObject();System.out.println(book);} }

結果如下:

原始對象: Book{name='三體', info='科幻小說', user=Person{name='smile', age=23}} 反序列化之后的對象: Book{name='三體', info='科幻小說', user=Person{name='smile', age=23}}

主要是使用到了ObjectOutputStream和ObjectInputStream類,ObjectOutputStream類使用writeObject將對象寫到文件中,ObjectInputStream類使用readObject將對象從文件中讀取出來。

2.2 部分屬性的序列化

實現部分字段序列化的方式:

  • 使用transient修飾符

  • 使用static修飾符

  • 默認方法writeObject和readObject

  • Externalizable實現

2.2.1 使用transient修飾符

修改實體類,將實體類中不想被序列化的屬性添加transient修飾符。

public class Book implements Serializable {private String name;private transient String info;private Person user;... public class Person implements Serializable {private String name;private transient int age; ...

結果如下:

原始對象: Book{name='三體', info='科幻小說', user=Person{name='smile', age=23}} 反序列化之后的對象: Book{name='三體', info='null', user=Person{name='smile', age=0}}

用transient修飾的屬性都沒有被序列化,因此反序列化的結果也是默認值。

2.2.2 使用static修飾符

static修飾符修飾的屬性會參與序列化,但是如果在反序列化的時候對其進行重新賦值,反序列化后的結果會隨之改變:

public class Book implements Serializable {private String name;private static String info;private Person user;...public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException {//序列化Person p = new Person("smile", 23);Book b = new Book("三體", "科幻小說", p);System.out.println("原始對象:\n"+b);ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("b.txt"));oos.writeObject(b);oos.close();//反序列化b.setInfo("中國最牛的科幻小說");ObjectInputStream ois = new ObjectInputStream(new FileInputStream("b.txt"));Book book = (Book) ois.readObject();System.out.println("反序列化之后的對象:\n"+book);} }

結果:

原始對象: Book{name='三體', info='科幻小說', user=Person{name='smile', age=23}} 反序列化之后的對象: Book{name='三體', info='中國最牛的科幻小說', user=Person{name='smile', age=23}}

解釋:其實就是靜態屬性被修改之后,因為所有對象都是用的同一個內容,所以反序列化的靜態屬性也就變了。

2.2.3 默認方法writeObject和readObject

在Book中添加兩個方法: public class Book implements Serializable {private String name;private String info;private Person user;private void writeObject(ObjectOutputStream oos) throws IOException {System.out.println("writeObject---------------");oos.writeObject(name);oos.writeObject(user);}private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {System.out.println("readObject----------------");name = (String) ois.readObject();user = (Person) ois.readObject();}...

結果為:

原始對象: Book{name='三體', info='科幻小說', user=Person{name='smile', age=23}} writeObject--------------- readObject---------------- 反序列化之后的對象: Book{name='三體', info='null', user=Person{name='smile', age=23}}

info屬性沒有寫入兩個函數中,就沒有被序列化。

源碼分析:

注意:添加的兩個方法必須是private void修飾的,否則不生效。

首先看一下Serializable接口的描述:

ObjectStreamClass類:在序列化(反序列化)的時候,ObjectOutputStream(ObjectInputStream)會尋找目標類中私有的writeObject(readObject)方法,賦值給變量writeObjectMethod(readObjectMethod)。

通過上面這段代碼可以知道,如果writeObjectMethod ≠ null(目標類中定義了私有的writeObject方法),那么將調用目標類中的writeObject方法,如果writeObject == null,那么將調用默認的defaultWriteMethod方法來讀取目標類中的屬性。

readObject的調用邏輯和WriteObject一樣。

總結一下,如果目標類中沒有定義私有的writeObject或readObject方法,那么序列化和反序列化的時候講調用默認的方法來根據目標類中的屬性來進行序列化和反序列化,而如果目標類中定義了私有的writeObject或readObject方法,那么序列化和反序列化的時候講調用目標類指定的writeObject或readObject方法來實現。

2.3 Externalizable實現java序列化

實現部分屬性序列化的方式的第四種,通過Externalizable接口。

Externalizable繼承自Serializable接口,使用Externalizable接口需要實現readExternal方法和writeExternal方法來實現序列化和反序列化。

Externalizable接口繼承自Serializable接口,所以實現Externalizable接口也能實現序列化和反序列化。Externalizable接口中定義了writeExternal和readExternal兩個抽象方法,這兩個方法其實對應Serializable接口的writeObject和readObject方法,可以這樣理解:Externalizable接口被設計出來的目的就是為了抽象出writeObject和readObject這兩個方法,但是目前這個接口使用的并不多。

三、Serializable vs Externalizable

區別SerializableExternalizable
實現復雜度實現簡單,java對其有內建支持實現復雜,由開發人員自己完成
執行效率所有對象由java統一保存,性能較低開發人員決定哪個對象保存,可能造成速度提升
保存信息保存時占用空間大部分存儲,可能造成空間減少
使用頻率偏低

總結

以上是生活随笔為你收集整理的JavaSE——IO(下)(Properties类、序列化与反序列化)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。