一、序列化
1.概述
- 對(duì)象序列化:就是將對(duì)象保存到磁盤中豺总,或者在網(wǎng)絡(luò)中傳輸對(duì)象
- 這種機(jī)制就是使用一個(gè)字節(jié)序列表示一個(gè)對(duì)象,該字節(jié)序列包含:對(duì)象的類型、對(duì)象的數(shù)據(jù)和對(duì)象中存儲(chǔ)的屬性等信息
- 字節(jié)序列寫到文件之后项鬼,相當(dāng)于文件中持久保存了一個(gè)對(duì)象的信息
- 反之,該字節(jié)序列還可以從文件中讀取回來劲阎,重構(gòu)對(duì)象绘盟,對(duì)它進(jìn)行反序列化
2.使用方法
對(duì)象序列化流: ObjectOutputStream
將Java對(duì)象的原始數(shù)據(jù)類型和圖形寫入OutputStream。 可以使用ObjectInputStream讀让跸伞(重構(gòu))對(duì)象龄毡。 可以通過使用流的文件來實(shí)現(xiàn)對(duì)象的持久存儲(chǔ)。 如果流是網(wǎng)絡(luò)套接字流锡垄,則可以在另一個(gè)主機(jī)上或另一個(gè)進(jìn)程中重構(gòu)對(duì)象
-
對(duì)象反序列化流: ObjectInputStream
- ObjectInputStream反序列化先前使用ObjectOutputStream編寫的原始數(shù)據(jù)和對(duì)象
-
注意
- 一個(gè)對(duì)象要想被序列化沦零,該對(duì)象所屬的類必須必須實(shí)現(xiàn)Serializable 接口
- Serializable是一個(gè)標(biāo)記接口,實(shí)現(xiàn)該接口货岭,不需要重寫任何方法
-
構(gòu)造方法
方法名 說明 ObjectOutputStream(OutputStream out) 創(chuàng)建一個(gè)寫入指定的OutputStream的ObjectOutputStream ObjectInputStream(InputStream in) 創(chuàng)建從指定的InputStream讀取的ObjectInputStream -
對(duì)象方法
方法名 說明 void writeObject(Object obj) 將指定的對(duì)象寫入ObjectOutputStream Object readObject() 從ObjectInputStream讀取一個(gè)對(duì)象 User類
:serialVersionUID&transient的使用
import java.io.Serializable;
//如果想要這個(gè)類的對(duì)象能被序列化,那么這個(gè)類必須要實(shí)現(xiàn)一個(gè)接口.Serializable
//Serializable 接口的意義
//稱之為是一個(gè)標(biāo)記性接口,里面沒有任何的抽象方法
//只要一個(gè)類實(shí)現(xiàn)了這個(gè)Serializable接口,那么就表示這個(gè)類的對(duì)象可以被序列化.
public class User implements Serializable {
//serialVersionUID 序列號(hào)
//如果我們自己沒有定義,那么虛擬機(jī)會(huì)根據(jù)類中的信息會(huì)自動(dòng)的計(jì)算出一個(gè)序列號(hào).
//問題:如果我們修改了類中的信息.那么虛擬機(jī)會(huì)再次計(jì)算出一個(gè)序列號(hào).
//第一步:把User對(duì)象序列化到本地. --- -5824992206458892149
//第二步:修改了javabean類. 導(dǎo)致 --- 類中的序列號(hào) 4900133124572371851
//第三步:把文件中的對(duì)象讀到內(nèi)存. 本地中的序列號(hào)和類中的序列號(hào)不一致了.
//解決?
//不讓虛擬機(jī)幫我們自動(dòng)計(jì)算,我們自己手動(dòng)給出.而且這個(gè)值不要變.
private static final long serialVersionUID = 1L;
private String username;
private transient String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
測(cè)試存取對(duì)象
static void method1() throws IOException, ClassNotFoundException {
User user = new User("zhangsan","qwer");
// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
oos.writeObject(user);
oos.close();
// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
User o = (User) ois.readObject();
System.out.println(o);
ois.close();
}
測(cè)試存取集合
static void test() throws IOException, ClassNotFoundException {
//1.創(chuàng)建集合
ArrayList<Student> arrayList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Student s = new Student("佟麗婭:"+ String.valueOf(i),30+i);
arrayList.add(s);
}
//2.將集合對(duì)象序列化到文件中
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
oos.writeObject(arrayList);
oos.close();
//3.將文件中的對(duì)象數(shù)據(jù),讀取到內(nèi)存中
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
Object obj = ois.readObject();
ois.close();
//取出集合對(duì)象
ArrayList<Student> arrayList1 = (ArrayList<Student>)obj;
for (Student s : arrayList) {
System.out.println(s.getName() + "," + s.getAge());
}
}
二路操、Properties集合
1、概述
- 是一個(gè)Map體系的集合類
- Properties可以保存到流中或從流中加載
- 屬性列表中的每個(gè)鍵及其對(duì)應(yīng)的值都是一個(gè)字符串
2千贯、常用方法
方法名 | 說明 |
---|---|
Object setProperty(String key, String value) | 設(shè)置集合的鍵和值屯仗,都是String類型,底層調(diào)用 Hashtable方法 put |
String getProperty(String key) | 使用此屬性列表中指定的鍵搜索屬性 |
Set<String> stringPropertyNames() | 從該屬性列表中返回一個(gè)不可修改的鍵集丈牢,其中鍵及其對(duì)應(yīng)的值是字符串 |
public synchronized V put(K key, V value) | 設(shè)置集合的鍵和值 |
public Set<K> keySet() | 從該屬性列表中返回一個(gè)不可修改的鍵集 |
static void test1(){
// Properties<String,String> prop = new Properties<String,String>(); //錯(cuò)誤
Properties prop = new Properties();
//設(shè)置集合的鍵和值祭钉,都是String類型
for (int i = 0; i < 3; i++) {
prop.setProperty("佟麗婭:"+ String.valueOf(i), String.valueOf("年齡" + i));
}
for (int i = 3; i < 6; i++) {
prop.put("佟麗婭:"+ String.valueOf(i),30+i);
}
//使用此屬性列表中指定的鍵搜索屬性
System.out.println(prop.getProperty("佟麗婭:3"));
System.out.println(prop);
//遍歷集合
Set<Object> keySet = prop.keySet();
for (Object key : keySet) {
Object value = prop.get(key);
System.out.println(key + "," + value);
}
//從該屬性列表中返回一個(gè)不可修改的鍵集,其中鍵及其對(duì)應(yīng)的值是字符串
Set<String> names = prop.stringPropertyNames();
for (String key : names) {
String value = prop.getProperty(key);
System.out.println(key + "," + value);
}
}
3Properties和IO流相結(jié)合
-
和IO流結(jié)合的方法
方法名 說明 void load(Reader reader) 從輸入字符流讀取屬性列表(鍵和元素對(duì)) void store(Writer writer, String comments) 將此屬性列表(鍵和元素對(duì))寫入此 Properties表中己沛,以適合使用 load(Reader)方法的格式寫入輸出字符流
private static void test2() throws IOException {
Properties prop1 = new Properties();
for (int i = 0; i < 3; i++) {
prop1.setProperty("佟麗婭:"+ String.valueOf(i), String.valueOf("年齡" + i));
}
// 創(chuàng)建文件
FileWriter fw = new FileWriter("fw.txt");
// 保存Properties對(duì)象
prop1.store(fw,null);
fw.close();
Properties prop2 = new Properties();
// 讀取文件
FileReader fr = new FileReader("fw.txt");
// 讀取Properties對(duì)象
prop2.load(fr);
fr.close();
System.out.println(prop2);
}