java如何序列化
一、序列化與反序列化
序列化:指堆記憶體中的java物件數據,透過某種方式把對儲存到磁碟檔案中,或傳遞給其他網路節點(網路傳輸)。這個過程稱為序列化,通常是指將資料結構或物件轉換成二進位的過程。
即将对象转化为二进制,用于保存,或者网络传输。
反序列化:把磁碟檔案中的物件資料或是把網路節點上的物件數據,恢復成Java物件模型的過程。也就是將在序列化過程中所產生的二進位串轉換成資料結構或物件的過程
与序列化相反,将二进制转化成对象。
二、序列化的作用
① 想把內存中的物件儲存到一個檔案或資料庫中時候;
##② 想用套接字在網路上傳送物件的時候;③ 想透過RMI傳輸物件的時候
一些应用场景,涉及到将对象转化成二进制,序列化保证了能够成功读取到保存的对象。
三、java的序列化實作
要實現物件的序列化,最直接的操作就是實作Serializable介面使用IO流中的對象流可以實現序列化操作,將物件儲存到文件,再讀取出來。 先建立一個對象,並實作Serializable介面:import java.io.Serializable; public class User implements Serializable{ private static final long serialVersionUID = 1L; private String name; private int 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; } @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } }
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializeUtil { // 保存对象,序列化 public static void saveObject(Object object) throws Exception { ObjectOutputStream out = null; FileOutputStream fout = null; try { fout = new FileOutputStream("D:/1.txt"); out = new ObjectOutputStream(fout); out.writeObject(object); } finally { fout.close(); out.close(); } } // 读取对象,反序列化 public static Object readObject() throws Exception { ObjectInputStream in = null; FileInputStream fin = null; try { fin = new FileInputStream("D:/1.txt"); in = new ObjectInputStream(fin); Object object = in.readObject(); return object; } finally { fin.close(); in.close(); } } }
public class Main { public static void main(String[] args) { User user = new User(); user.setName("旭旭宝宝"); user.setAge(33); // 保存 try { SerializeUtil.saveObject(user); } catch (Exception e) { System.out.println("保存时异常:" + e.getMessage()); } // 读取 User userObject; try { userObject = (User) SerializeUtil.readObject(); System.out.println(userObject); } catch (Exception e) { System.out.println("读取时异常:" + e.getMessage()); } } }
public class User { private String name; private int 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; } @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } }
四、序列化ID的作用
可以看到,我們在進行序列化時,加了一個serialVersionUID字段,這就是序列化IDprivate static final long serialVersionUID = 1L;
即序列化ID是为了保证成功进行反序列化
五、預設的序列化ID
當我們一個實體類別中沒有明確的定義一個名為「serialVersionUID」、類型為long的變數時,Java序列化機制會根據編譯時的class自動產生一個serialVersionUID作為序列化版本比較,這種情況下,只有同一次編譯產生的class才會產生相同的serialVersionUID。譬如,當我們寫一個類別時,隨著時間的推移,我們因為需求改動,需要在本地類別中添加其他的字段,這個時候再反序列化時便會出現serialVersionUID不一致,導致反序列化失敗。那麼如何解決呢?便是在本地類別中加入一個「serialVersionUID」變量,值保持不變,便可進行序列化和反序列化。如果没有显示指定serialVersionUID,会自动生成一个。 只有同一次编译生成的class才会生成相同的serialVersionUID。 但是如果出现需求变动,Bean类发生改变,则会导致反序列化失败。为了不出现这类的问题,所以我们最好还是显式的指定一个 serialVersionUID。
六、序列化的其他問題
1、靜態變數不會被序列化( static,transient)2、當一個父類別實作序列化,子類別自動實作序列化,不需要明確實作Serializable介面。 3、當一個對象的實例變數引用其他對象,序列化該對象時也把引用對象進行序列化。子类序列化时: 如果父类没有实现Serializable接口,没有提供默认构造函数,那么子类的序列化会出错; 如果父类没有实现Serializable接口,提供了默认的构造函数,那么子类可以序列化,父类的成员变量不会被序列化。如果父类 实现了Serializable接口,则父类和子类都可以序列化。
七、使用效率更高的序列化框架—Protostuff
<dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-core</artifactId> <version>1.5.9</version> </dependency>
<dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-core</artifactId> <version>1.5.9</version> </dependency>
import com.dyuproject.protostuff.LinkedBuffer; import com.dyuproject.protostuff.ProtobufIOUtil; import com.dyuproject.protostuff.ProtostuffIOUtil; import com.dyuproject.protostuff.Schema; import com.dyuproject.protostuff.runtime.RuntimeSchema; public class Main { public static void main(String[] args) { User user = new User(); user.setName("旭旭宝宝"); user.setAge(33); Schema<User> schema = RuntimeSchema.getSchema(User.class); // 保存对象,序列化,转化二进制数据 LinkedBuffer buffer = LinkedBuffer.allocate(512); final byte[] protostuff; try { protostuff = ProtobufIOUtil.toByteArray(user, schema, buffer); } finally { buffer.clear(); } // 读取对象,反序列化 User userObject = schema.newMessage(); ProtostuffIOUtil.mergeFrom(protostuff, userObject, schema); System.out.println(userObject); } }
public class User { private String name; private int 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; } @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } }
#
若要要整合Redis使用,也可以写成一个工具类:
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import com.dyuproject.protostuff.LinkedBuffer; import com.dyuproject.protostuff.ProtobufIOUtil; import com.dyuproject.protostuff.Schema; import com.dyuproject.protostuff.runtime.RuntimeSchema; public class SerializeUtil { private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>(); @SuppressWarnings("unchecked") public static <T> byte[] serializer(T obj) { Class<T> clazz = (Class<T>) obj.getClass(); Schema<T> schema = getSchema(clazz); return ProtobufIOUtil.toByteArray(obj, schema, LinkedBuffer.allocate(256)); } public static <T> T deSerializer(byte[] bytes, Class<T> clazz) { T message; try { message = clazz.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); } Schema<T> schema = getSchema(clazz); ProtobufIOUtil.mergeFrom(bytes, message, schema); return message; } @SuppressWarnings("unchecked") public static <T> Schema<T> getSchema(Class<T> clazz) { Schema<T> schema = (Schema<T>) cachedSchema.get(clazz); if (schema == null) { schema = RuntimeSchema.createFrom(clazz); if (schema != null) { cachedSchema.put(clazz, schema); } } return schema; } }
这样即使我们的User类就不用再实现Serialiable接口了,同样可以进行序列化,效率也更高。
php中文网,大量的免费Java入门教程,欢迎在线学习!
以上是java如何序列化的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

PHP和Python各有優勢,適合不同場景。 1.PHP適用於web開發,提供內置web服務器和豐富函數庫。 2.Python適合數據科學和機器學習,語法簡潔且有強大標準庫。選擇時應根據項目需求決定。

Java是熱門程式語言,適合初學者和經驗豐富的開發者學習。本教學從基礎概念出發,逐步深入解說進階主題。安裝Java開發工具包後,可透過建立簡單的「Hello,World!」程式來實踐程式設計。理解程式碼後,使用命令提示字元編譯並執行程序,控制台上將輸出「Hello,World!」。學習Java開啟了程式設計之旅,隨著掌握程度加深,可創建更複雜的應用程式。

PHP成為許多網站首選技術棧的原因包括其易用性、強大社區支持和廣泛應用。 1)易於學習和使用,適合初學者。 2)擁有龐大的開發者社區,資源豐富。 3)廣泛應用於WordPress、Drupal等平台。 4)與Web服務器緊密集成,簡化開發部署。
