在Java中,一个类被标记为Serializable
是什么意思?或者说,在一般情况下呢...
序列化是将一个对象从内存中持久化为一系列比特位,例如用于保存到磁盘上。反序列化则是相反的过程 - 从磁盘中读取数据以恢复/创建一个对象。
在您的问题背景下,这是一个接口,如果一个类实现了它,那么这个类可以被不同的序列化程序自动地进行序列化和反序列化。
public class Person implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public String firstName;
public String lastName;
public int age;
public String address;
public void play() {
System.out.println(String.format(
"If I win, send me the trophy to this address: %s", address));
}
@Override
public String toString() {
return String.format(".....Person......\nFirst Name = %s\nLast Name = %s", firstName, lastName);
}
}
然后你可以创建一个如下所示的对象:
Person william = new Person();
william.firstName = "William";
william.lastName = "Kinaan";
william.age = 26;
william.address = "Lisbon, Portugal";
你可以将该对象序列化到多个流中。我会将其序列化到两个流中:
序列化到标准输出:
public static void serializeToStandardOutput(Person person)
throws IOException {
OutputStream outStream = System.out;
ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream);
stdObjectOut.writeObject(person);
stdObjectOut.close();
outStream.close();
}
将对象序列化到文件中:
public static void serializeToFile(Person person) throws IOException {
OutputStream outStream = new FileOutputStream("person.ser");
ObjectOutputStream fileObjectOut = new ObjectOutputStream(outStream);
fileObjectOut.writeObject(person);
fileObjectOut.close();
outStream.close();
}
然后:
从文件反序列化:
public static void deserializeFromFile() throws IOException,
ClassNotFoundException {
InputStream inStream = new FileInputStream("person.ser");
ObjectInputStream fileObjectIn = new ObjectInputStream(inStream);
Person person = (Person) fileObjectIn.readObject();
System.out.println(person);
fileObjectIn.close();
inStream.close();
}
这意味着类的实例可以被转换为字节流(例如保存到文件中),然后再次转换回类。重新加载可能发生在程序的不同实例甚至不同机器上。但是,序列化(无论哪种语言)涉及各种问题,特别是当您在可序列化对象内部具有对其他对象的引用时。
这里有一个关于Serialization的详细解释:(我的博客)
什么是Serialization?
Serialization是将对象状态序列化并以一系列字节的形式表示和存储的过程。可以将其存储在文件中。从文件中读取对象状态并恢复它的过程称为反序列化。
为什么需要Serialization?
在现代架构中,总是需要存储对象状态然后检索它。例如,在Hibernate中,要存储对象,我们应该使类可序列化。它的作用是一旦对象状态以字节形式保存,就可以将其传输到另一个系统,该系统可以从状态中读取并检索类。对象状态可以来自数据库、不同的JVM或单独的组件。借助Serialization,我们可以检索对象状态。
代码示例和说明:
首先让我们看一下Item类:
public class Item implements Serializable{
/**
* This is the Serializable class
*/
private static final long serialVersionUID = 475918891428093041L;
private Long itemId;
private String itemName;
private transient Double itemCostPrice;
public Item(Long itemId, String itemName, Double itemCostPrice) {
super();
this.itemId = itemId;
this.itemName = itemName;
this.itemCostPrice = itemCostPrice;
}
public Long getItemId() {
return itemId;
}
@Override
public String toString() {
return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
}
public void setItemId(Long itemId) {
this.itemId = itemId;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public Double getItemCostPrice() {
return itemCostPrice;
}
public void setItemCostPrice(Double itemCostPrice) {
this.itemCostPrice = itemCostPrice;
}
}
在上面的代码中,可以看到Item类实现了Serializable接口。public class SerializationExample {
public static void main(String[] args){
serialize();
deserialize();
}
public static void serialize(){
Item item = new Item(1L,"Pen", 12.55);
System.out.println("Before Serialization" + item);
FileOutputStream fileOut;
try {
fileOut = new FileOutputStream("/tmp/item.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(item);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in /tmp/item.ser");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void deserialize(){
Item item;
try {
FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
item = (Item) in.readObject();
System.out.println("Serialized data is read from /tmp/item.ser");
System.out.println("After Deserialization" + item);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
以上是对象序列化和反序列化的示例。
为此,我们使用了两个类。为了序列化对象,我们使用了ObjectOutputStream。我们使用writeObject方法将对象写入文件。
为了反序列化,我们使用了ObjectInputStream,它从文件中读取对象。它使用readObject方法从文件中读取对象数据。
上述代码的输出结果如下:
Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]
需要注意的是,反序列化对象中的itemCostPrice为null,因为它没有被写入。
序列化意味着将一个对象的当前状态保存到流中,并从该流中恢复等价的对象。流作为对象的容器。
Serializable 被称为接口,但更像是在运行时对 Serialization 子系统的一个标志。它表示该对象可以被保存。除了不可序列化的对象和标记为 volatile 的对象之外,所有对象实例变量都将被保存。
想象一下,您的应用程序可以作为选项更改颜色,如果不将该设置保留在外部,则每次运行时都需要更改颜色。
序列化是一种将对象和数据存储或写入文件的技术。使用 ObjectOutputStream
和 FileOutputStream
类,这些类具有特定的方法来持久化对象,例如 writeObject();
想要更清晰地了解可以点击此处查看图示和更多信息。
序列化: 将对象的状态写入文件、网络或任何其他地方。(意味着将 Java 对象支持的形式转换为文件支持的形式或网络支持的形式)
反序列化: 从文件、网络或任何其他地方读取对象的状态。(意味着将文件/网络支持的形式转换为 Java 对象支持的形式)
仅补充其他答案并涉及普遍性。序列化有时被称为归档,例如在Objective-C中。
Serializable
类的说明:通过实现java.io.Serializable
接口,可以启用类的可序列化。未实现此接口的类将无法将其状态序列化或反序列化。所有可序列化类的子类型都是可序列化的。序列化接口没有任何方法或字段,只用于标识可序列化的语义。 - Ritwik Bose