Java-实例-序列化与反序列化(Serializable)

Java-实例-序列化与反序列化(Serializable)

理解(Serializable

序列化---将对象状态转换为字节流,以便存储或传输。
序列化是"冻结"对象,反序列化是"解冻"对象

想让一个对象可序列化,其类必须实现java.io.Serializable接口。这个接口没有任何方法,只起标记作用,告诉JVM这个类的对象允许被序列化。

在Android中,进行序列化主要有两种选择:Java原生的Serializable和Android专属的Parcelable

它们最核心的区别在于设计初衷和应用场景

  • Serializable:是Java的标准接口,使用简单,但效率较低,适合持久化存储(存文件)或网络传输-2-8-11。

  • Parcelable:是Android特有的接口,实现稍复杂,但性能极高,专为内存间的高效数据传输而设计,是Android组件间通信(如IntentBinder跨进程通信)的首选

实例

将对象person转换为字节流,存储在工程target文件夹中。

调用

Person person = new Person("九股烟", 20); byte[] bytes0 = serialize(person); // 序列化:将对象保存到文件 save(bytes0); //保存 byte[] bytes1= read(); //读出 Person p = deserialize(bytes1); // 反序列化:从文件恢复对象 System.out.println("反序列化(对象)= " + p.toString());

功能函数

// =============================================================== // 1. 序列化:对象 → 字节数组 // =============================================================== public static byte[] serialize(Person person) { try ( ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeObject(person); oos.flush(); return baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); return null; } } // =============================================================== // 2. 反序列化:字节数组 → 对象 // =============================================================== public static Person deserialize(byte[] bytes) { if (bytes == null || bytes.length == 0) {return null;} try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais)) { return (Person) ois.readObject(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); return null; } } String targetDir = "target/"; String fileName = "path_bytes.km"; // =============================================================== // 3. 保存:字节数组 → 文件 // =============================================================== public void save(byte[] data) { try { // 确保target目录存在 File file = new File(targetDir, fileName); file.getParentFile().mkdirs();// 确保target目录存在 try (FileOutputStream fos = new FileOutputStream(file)) { fos.write(data); System.out.println("保存成功: " + file.getAbsolutePath()); System.out.println("数据大小: " + data.length + " 字节"); } } catch (IOException e) { e.printStackTrace(); } } // =============================================================== // 4. 读取:文件 → 字节数组 // =============================================================== public byte[] read() { File file = new File(targetDir, fileName); file.getParentFile().mkdirs();// 确保target目录存在 if (!file.exists()) {return null;} try (FileInputStream fis = new FileInputStream(file)) { byte[] data = new byte[(int) file.length()]; fis.read(data); System.out.println("读取成功: " + file.getAbsolutePath()); System.out.println("数据大小: " + data.length + " 字节"); return data; } catch (IOException e) { e.printStackTrace(); return null; } }

Person.java 接口Serializable

import java.io.Serializable; public class Person implements Serializable{ private String name; private int age; 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; } @Override public String toString() { return "Person{" + "name ='" + name + '\'' + ", age =" + age + '}'; } }