Java 序列化Serializable詳解(附詳細例子)

Java 序列化Serializable詳解(附詳細例子)

1、什么是序列化和反序列化
Serialization(序列化)是一種將對象以一連串的字節描述的過程;反序列化deserialization是一種將這些字節重建成一個對象的過程。

?

2、什么情況下需要序列化?
a)當你想把的內存中的對象保存到一個文件中或者數據庫中時候;
b)當你想用套接字在網絡上傳送對象的時候;
c)當你想通過RMI傳輸對象的時候;

3、如何實現序列化

將需要序列化的類實現Serializable接口就可以了,Serializable接口中沒有任何方法,可以理解為一個標記,即表明這個類可以序列化。

?

4、序列化和反序列化例子

如果我們想要序列化一個對象,首先要創建某些OutputStream(如FileOutputStream、ByteArrayOutputStream等),然后將這些OutputStream封裝在一個ObjectOutputStream中。這時候,只需要調用writeObject()方法就可以將對象序列化,并將其發送給OutputStream記住:對象的序列化是基于字節的,不能使用Reader和Writer等基于字符的層次結構。而反序列的過程(即將一個序列還原成為一個對象),需要將一個InputStream(如FileInputstream、ByteArrayInputStream等)封裝在ObjectInputStream內,然后調用readObject()即可。

?

package com.sheepmu;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;public class MyTest implements Serializable
{private static final long serialVersionUID = 1L;private String name="SheepMu";private int age=24;public static void main(String[] args){//以下代碼實現序列化try {ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("my.out"));//輸出流保存的文件名為 my.out ;ObjectOutputStream能把Object輸出成Byte流MyTest myTest=new MyTest();oos.writeObject(myTest); oos.flush();  //緩沖流 oos.close(); //關閉流} catch (FileNotFoundException e) {		 e.printStackTrace();} catch (IOException e) {e.printStackTrace();} fan();//調用下面的  反序列化  代碼}public static void fan()//反序列的過程{	 ObjectInputStream oin = null;//局部變量必須要初始化try{oin = new ObjectInputStream(new FileInputStream("my.out"));} catch (FileNotFoundException e1){		 e1.printStackTrace();} catch (IOException e1){e1.printStackTrace();}      MyTest mts = null;try {mts = (MyTest ) oin.readObject();//由Object對象向下轉型為MyTest對象} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}     System.out.println("name="+mts.name);    System.out.println("age="+mts.age);    }
}

會在此項目的工作空間生成一個 my.out文件。序列化后的內容稍后補齊,先看反序列化后輸出如下:

?

name=SheepMu
age=24

5、序列化ID

序列化 ID 在 Eclipse 下提供了兩種生成策略,一個是固定的 1L,一個是隨機生成一個不重復的 long 類型數據(實際上是使用 JDK 工具生成),在這里有一個建議,如果沒有特殊需求,就是用默認的 1L 就可以,這樣可以確保代碼一致時反序列化成功。這也可能是造成序列化和反序列化失敗的原因,因為不同的序列化id之間不能進行序列化和反序列化。

?

6.序列化前和序列化后的對象的關系

是 "=="還是equal? or 是淺復制還是深復制??

答案:深復制,反序列化還原后的對象地址與原來的的地址不同

序列化前后對象的地址不同了,但是內容是一樣的,而且對象中包含的引用也相同。換句話說,通過序列化操作,我們可以實現對任何可Serializable對象的”深度復制(deep copy)"——這意味著我們復制的是整個對象網,而不僅僅是基本對象及其引用。對于同一流的對象,他們的地址是相同,說明他們是同一個對象,但是與其他流的對象地址卻不相同。也就說,只要將對象序列化到單一流中,就可以恢復出與我們寫出時一樣的對象網,而且只要在同一流中,對象都是同一個。

?

7.靜態變量能否序列化

若把上面的代碼中的 age變量前加上 static ,輸出任然是

name=SheepMu
age=24

但是看下面的例子:

?

package com.sheepmu;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class MyTest implements Serializable
{private static final long serialVersionUID = 1L;private String name="SheepMu";private static int age=24;public static void main(String[] args){//以下代碼實現序列化try {ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("my.out"));//輸出流保存的文件名為 my.out ;ObjectOutputStream能把Object輸出成Byte流MyTest myTest=new MyTest();oos.writeObject(myTest); oos.flush();  //緩沖流 oos.close(); //關閉流} catch (FileNotFoundException e) {		 e.printStackTrace();} catch (IOException e) {e.printStackTrace();} fan();//調用下面的  反序列化  代碼}public static void fan(){new MyTest().name="SheepMu_1";//!!!!!!!!!!!!!!!!重點看這兩行 更改部分age=1;//!!!!!!!!!!!!!!!!!!!重點看這兩行 更改部分ObjectInputStream oin = null;//局部變量必須要初始化try{oin = new ObjectInputStream(new FileInputStream("my.out"));} catch (FileNotFoundException e1){		 e1.printStackTrace();} catch (IOException e1){e1.printStackTrace();}      MyTest mts = null;try {mts = (MyTest ) oin.readObject();//由Object對象向下轉型為MyTest對象} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}     System.out.println("name="+mts.name);    System.out.println("age="+mts.age);    }
}

輸出結果為:

?

name=SheepMu
age=1
為何把最上面代碼的age變量添上static 后還是反序列化出了24呢?而新的從新對變量賦值的代碼,不是static的得到了序列化本身的值,而static的則得到的是從新附的值。原因:?序列化會忽略靜態變量,即序列化不保存靜態變量的狀態。靜態成員屬于類級別的,所以不能序列化。即 序列化的是對象的狀態不是類的狀態。這里的不能序列化的意思,是序列化信息中不包含這個靜態成員域。最上面添加了static后之所以還是輸出24是因為該值是JVM加載該類時分配的值。注:transient后的變量也不能序列化,但是情況稍復雜,稍后開篇說。

8、總結:

a)當一個父類實現序列化,子類自動實現序列化,不需要顯式實現Serializable接口;

b)當一個對象的實例變量引用其他對象,序列化該對象時也把引用對象進行序列化;

c) static,transient后的變量不能被序列化;

轉載于:https://www.cnblogs.com/cx6872/p/6049839.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/456992.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/456992.shtml
英文地址,請注明出處:http://en.pswp.cn/news/456992.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

kettle-實現每個分組的前N的數據

2019獨角獸企業重金招聘Python工程師標準>>> 第一步:創建表及數據: create table uid(uid int, --uidcate varchar(20), --類別price double --金額 ) insert into uid values(123,c1,21); insert into uid values(123,c2,23); insert into u…

重寫__repr__與__str__函數

重寫:將函數重新定義寫一遍__str__():再調用print 打印對象時自動調用,是給用戶用的是一個描述對象的方法__repr__():是給機器用的,在python解釋器里面直接敲對象名再回車調用的方法注意:在沒有str時,且有repr,str re…

linux nexus 使用問題

2019獨角獸企業重金招聘Python工程師標準>>> 問題一,啟動提示設置RUN_AS_USERroot 但是,設置export或 /etc/profile未生效。 **************************************** WARNING - NOT RECOMMENDED TO RUN AS ROOT *************************…

項目回顧-PopupWindow

右上菜單,可以通過 重寫 onCreateOptionsMenu指定 menu, 重寫 onOptionsItemSelected 來響應點擊事件 不過 這個菜單在某些手機上彈出的有點卡頓,而且如果不對主題進行設置,會從actionbar 上直接彈出,而不是下面 如果想…

android listpreference 自定義,Android ListPreference的用法一

xmlns:android"http://schemas.android.com/apk/res/android"android:key"screen_list"android:title"標題"android:summary"說明摘要">< ListPreferenceandroid:key"myListPreference"android:title"標題"…

C語言求最大公約數和最小公倍數的幾種算法

求最小公倍數算法&#xff1a; 最小公倍數兩整數的乘積最大公約數 求最大公約數算法&#xff1a; (1)輾轉相除法 有兩整數a和b&#xff1a; ① a%b得余數c ② 若c0&#xff0c;則b即為兩數的最大公約數 ③ 若c≠0&#xff0c;則ab&#xff0c;bc&#xff0c;再回去執行①…

3月15日云棲精選夜讀:雙管齊下,MaxCompute數據上云與生態

雙管齊下&#xff0c;MaxCompute數據上云與生態 作者&#xff1a;場景研讀 Go語言并發機制初探 作者&#xff1a;邴越 趣拍云短視頻SDK全面升級&#xff0c;簡單易用引開發者點贊 作者&#xff1a;sherry是雪梨 發表在&#xff1a;趣拍云團隊 阿里云機器學習平臺編程模型演…

qt android glsl,基于Qt的OpenGL學習(1)—— Hello Triangle

簡介要學習OpenGL的話&#xff0c;強烈安利這個教程JoeyDeVries的learnopengl&#xff0c;這里是中文翻譯好的版本。教程中使用OpenGL是通過GLFW這個庫&#xff0c;而在Qt中對OpenGL封裝得很好&#xff0c;并且和GUI以及IO相關的處理Qt更便捷&#xff0c;學習起來更輕松。這里就…

解決:Not Found: /favicon.ico

直接說解決辦法&#xff1a; &#xff08;1&#xff09;制作一個 favicon.ico圖標放在<head></head>標簽中 <link rel"shortcut icon" href"xxxxxxxxxx.ico" type"image/x-icon" /> <!--制作的圖標&#xff0c;使用hr…

多態方法調用的解析和分派

方法調用并不等同于方法執行&#xff0c;方法調用階段唯一的任務就是確定被調用方法的版本&#xff08;即調用哪一個方法&#xff09;&#xff0c;暫時還不涉及方法內部的具體運行過程。在程序運行時&#xff0c;進行方法調用是最普遍、最頻繁的操作&#xff0c;Class文件的編譯…

ES6:Set和Map

Set Set:類似數組&#xff0c;但是成員的值都是唯一的&#xff0c;沒有重復。Set本身是一個構造函數&#xff0c;用來生成Set數據結構。他包含的方法&#xff1a;add: 添加某個值&#xff0c;返回Set結構本身。delete: 刪除某個值&#xff0c;返回一個布爾值&#xff0c;表示是…

九九乘法表[循環嵌套]

#九九乘法表 # 1*11 # 1*22 2*24 # 1*33 2*36 3*39 # ...#循環嵌套 #行數 i 1 while i < 9:# 打印每行的內容j 1while j < i:print("%d * %d %3d " % (i, j, i * j), end)j 1print() # 換行i 1while嵌套&#xff1a;w 1 while w < 10: #外層循…

關于用VS寫C程序運行時出現燙字以及亂碼的問題的原因

最近在復習C語言寫程序時&#xff0c;突然碰到標題上的這種情況&#xff0c;后來經過上網查找以及逐步調試才發現原來是在打印數組的時候“越界”導致的&#xff0c;因為程序在默認初始化char類型的數組時&#xff0c;初始化的值是“燙”字&#xff0c;一般情況下是字符串未初始…

javascript函數調用的各種方法!!

在JavaScript中一共有下面4種調用方式&#xff1a; (1) 基本函數調用 (2)方法調用 (3)構造器調用 (4)通過call()和apply()進行調用 1. 基本函數調用 普通函數調用模式&#xff0c;如&#xff1a; JavaScript code?1234function fn(o){…… }fn({x:1});在基本函數調用中&#x…

ARM TK1 安裝kinect驅動

首先安裝usb庫 $ git clone https://github.com/libusb/libusb.git 編譯libusb需要的工具 $ sudo apt-get install autoconf autogen $ sudo apt-get install libtool $ sudo apt-get install libudev* 編譯安裝 $ sudo ./autogen.sh $ sudo make $ sudo make install $ sudo l…

如何在一個html頁面中提交兩個post,如何在同一個頁面上從Django和Ajax獲得多個post請求?...

我一整天都在為這事犯愁。似乎什么都沒用。這是我的情況。在我有一個Django表單&#xff0c;有兩個字段&#xff1a;redirect_from&#xff0c;redirect_to。此表單有兩個提交按鈕&#xff1a;Validate和{}。當頁面加載時&#xff0c;Submit被隱藏&#xff0c;只顯示Validate。…

大數據入門:各種大數據技術的介紹

大數據我們都知道hadoop&#xff0c;可是還會各種各樣的技術進入我們的視野&#xff1a;Spark&#xff0c;Storm&#xff0c;impala&#xff0c;讓我們都反映不過來。為了能夠更好的架構大數據項目&#xff0c;這里整理一下&#xff0c;供技術人員&#xff0c;項目經理&#xf…

高可用與負載均衡(5)之基于客戶端的負載均衡

什么是客戶端負載均衡 基于客戶端的負載均衡&#xff0c;簡單的說就是在客戶端程序里面&#xff0c;自己設定一個調度算法&#xff0c;在向服務器發起請求的時候&#xff0c;先執行調度算法計算出向哪臺服務器發起請求&#xff0c;然后再發起請求給服務器。 基于客戶端負載均衡…

Variant 與 內存泄露

http://blog.chinaunix.net/uid-10386087-id-2959221.html 今天遇到一個內存泄露的問題。是師兄檢測出來的。Variant類型在使用后要Clear否則會造成內存泄露&#xff0c;為什么呢&#xff1f; Google一下找到下面一篇文章&#xff0c;主要介紹了Com的內存泄露&#xff0c;中間有…

安裝安全類軟件進行了android簽名漏洞修補,魅族MX3怎么升級固件體驗最新比較穩定的版本...

魅族mx3固件怎么升級?flyme os系統會持續更新&#xff0c;升級魅族MX3手機系統需先下載MX3的升級固件&#xff0c;升級固件分為體驗版和穩定版。魅族MX3固件有體驗版和穩定版兩種&#xff0c;顧名思義&#xff0c;體驗版為最新版但相比穩定版來說存在更多的漏洞&#xff0c;升…