java 對象經(jīng)常需要在網(wǎng)絡(luò)中以 socket 傳輸或者需要保存到文件中。這時(shí)不管 java 對象是文件、數(shù)據(jù)、圖像還是其他格式,都可以轉(zhuǎn)換為一個(gè) byte[] 數(shù)組保存到文件或者通過網(wǎng)絡(luò)傳輸。這種轉(zhuǎn)換方式就叫做序列化。將文件或者網(wǎng)絡(luò)傳輸中得到的 byte[] 數(shù)組轉(zhuǎn)換為 java 對象就叫做反序列化。
怎么使用
如果一個(gè) Java 對象要能被序列化,必須實(shí)現(xiàn)一個(gè)特殊的 java.io.Serializable 接口
public interface Serializable {
}
Serializable 接口沒有定義任何的方法,是一個(gè)空接口。為什么要有一個(gè)這樣的接口?主要是因?yàn)榘踩?。如果沒有這個(gè)接口就代表著所有 java 對象都可以被序列化到磁盤上,然后通過反序列化看到所有屬性的數(shù)據(jù)。有了這個(gè) Serializable 就可以讓開發(fā)人員選擇 java 對象可以被序列化和反序列化,就增加了安全性。
序列化
下面例子是將一個(gè) java 對象序列化后保存到文件。
import java.io.Serializable;
public class Order implements Serializable {
private Long orderId;
private String orderNo;
private String consignee;//收件人
private String deliveryAddress;//收貨地址
//getter 和 setter
@Override
public String toString() {
return "OrderDTO{" +
"orderId=" + orderId +
", orderNo='" + orderNo + ''' +
", consignee='" + consignee + ''' +
", deliveryAddress='" + deliveryAddress + ''' +
'}';
}
}
把一個(gè) Java 對象變?yōu)?byte[] 數(shù)組,需要使用 ObjectOutputStream。它負(fù)責(zé)把一個(gè)Java 對象寫入一個(gè)字節(jié)流:
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws Exception {
OrderDTO orderDTO = new OrderDTO();
orderDTO.setOrderId(1L);
orderDTO.setOrderNo("123456");
orderDTO.setConsignee("李四");
orderDTO.setDeliveryAddress("xxx路xxx弄xxxx號");
OrderDTO orderDTO2 = new OrderDTO();
orderDTO2.setOrderId(2L);
orderDTO2.setOrderNo("78901");
orderDTO2.setConsignee("王五");
orderDTO2.setDeliveryAddress("yyy路yyy弄yyyy號");
List< OrderDTO > list = new ArrayList< >();
list.add(orderDTO);
list.add(orderDTO2);
FileOutputStream fos = new FileOutputStream("D:/order.txt");
try ( ObjectOutputStream os = new ObjectOutputStream(fos)){
os.writeObject(list);
}
System.out.println("序列化成功");
}
}
這個(gè)時(shí)候就將兩個(gè) OrderDTO 對象序列化到了 D:/order.txt 中。
反序列化
序列化文件在本地打開都是亂碼的,這應(yīng)該用反序列化將文件解析成對象。
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws Exception {
List< OrderDTO > list = new ArrayList< >();
FileInputStream fis = new FileInputStream("D:/order.txt");
try (ObjectInputStream is = new ObjectInputStream(fis)) {
list = (List< OrderDTO >)is.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
for (OrderDTO orderDTO : list){
System.out.println(orderDTO.toString());
}
}
}
輸出結(jié)果:
OrderDTO{orderId=1, orderNo='123456', consignee='李四', deliveryAddress='xxx路xxx弄xxxx號'}
OrderDTO{orderId=2, orderNo='78901', consignee='王五', deliveryAddress='yyy路yyy弄yyyy號'}
注意點(diǎn)
- 靜態(tài)變量和 transient 關(guān)鍵字修飾的變量不能被序列化
- 反序列化的時(shí)候,字節(jié)流中的 serialVersionUID 和實(shí)體類中的 serialVersionUID 的不一致會拋出異常。serialVersionUID 沒有寫的話,會被默認(rèn)一個(gè)。
- 序列化實(shí)現(xiàn)了深克隆,對象引用的每一個(gè)對象數(shù)據(jù)也會被序列化。
總結(jié)
- 序列化必須實(shí)現(xiàn) Serializable。
- serialVersionUID 不是必須的。
-
接口
+關(guān)注
關(guān)注
33文章
8891瀏覽量
153015 -
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7233瀏覽量
90790 -
JAVA
+關(guān)注
關(guān)注
20文章
2983瀏覽量
106568 -
網(wǎng)絡(luò)
+關(guān)注
關(guān)注
14文章
7724瀏覽量
90183
發(fā)布評論請先 登錄
如何使用Serde進(jìn)行序列化和反序列化
Java序列化的機(jī)制和原理
c語言序列化和反序列化有何區(qū)別
SpringMVC JSON框架的自定義序列化與反序列化
Java對象序列化您不知道的5件事
java序列化和反序列化范例和JDK類庫中的序列化API
java序列化的幾種方式
static屬性為什么不會被序列化
Java反序列化回顯方法
什么是序列化 為什么要序列化

評論