序列化是什么意思?

一个类在 Java 中是 Serializable到底意味着什么? 或者一般来说,就这个问题而言..。

118001 次浏览

这意味着类的实例可以转换成字节流(例如,保存到文件中) ,然后再转换回类。这种重新加载可能发生在程序的不同实例中,甚至可能发生在不同的机器上。但是,序列化(在任何语言中)涉及到各种各样的问题,特别是当您在可序列化对象中引用了其他对象时。

序列化 是将一个对象从内存持久化到一个位序列,例如用于保存到磁盘上。反序列化与从磁盘读取数据以水合/创建对象相反。

在您的问题的上下文中,它是一个接口,如果在类中实现,该类可以由不同的序列化器自动序列化和反序列化。

序列化类似于接口,但更像是运行时序列化子系统的标志。它说这个对象可以被保存。将保存所有 Objects 实例变量,但不包括任何可序列化对象和标记可变的对象。

假设您的应用程序可以改变颜色作为一个选项,没有保持该设置外部,您将需要改变颜色每次运行它。

序列化包括将对象的当前状态保存到流中,并从该流中恢复等效的对象。该流充当对象的容器

只是为了补充其他的答案和关于一般性。序列化有时被称为归档,例如在 Objective-C 中。

序列化是一种将对象和数据存储或写入文件的技术。通过使用 ObjectOutputStreamFileOutputStream类。这些类具有用于持久化对象的特定方法。就像 writeObject();

用数字清楚解释

从另一个角度展示。序列化是一种称为“标记接口”的接口。标记接口是不包含方法声明的接口,但是 仅仅指定(或“标记”)实现接口的类具有 一些财产。如果您了解多态性,这将非常有意义。对于 Serialable 标记接口,如果 ObjectOutputStream.write (Object)方法的参数没有实现该接口,则该方法将失败。这在 java 中是一个潜在的错误,它可能是 ObjectOutputStream.write (Serializer)

强烈推荐: 阅读 作者: Joshua Bloch中的第37项以了解更多信息。

虽然大多数用户已经给出了答案,但是我想为那些需要它的人添加一个例子来解释这个想法:

假设你有一个类似下面这样的人:

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();
}

序列化: 对象到文件/网络或任何地方的写入状态。(平均 Java 对象支持表单到文件支持表单或网络支持表单)

反序列化: 从文件/网络或任何地方读取对象的状态

下面是对 Serialization 的详细解释: (我自己的博客)

序列化:

序列化是将对象的状态序列化的过程,是以字节序列的形式表示和存储的。这可以存储在一个文件中。从文件中读取对象状态并还原它的过程称为反序列化。

序列化需要什么?

在现代体系结构中,总是需要存储对象状态,然后检索它。例如,在 Hibernate 中,为了存储对象,我们应该使类 Serializer。它的作用是,一旦对象状态以字节的形式保存下来,就可以将其传输到另一个系统,该系统可以从状态读取并检索类。对象状态可以来自数据库、不同的 jvm 或单独的组件。在序列化的帮助下,我们可以检索对象状态。

代码示例和解释:

首先让我们看一下项目类:

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;
}
}

在上面的代码中可以看到,物品类实现了 可序列化

这是使类可序列化的接口。

现在我们可以看到一个名为 SerialVersionUID的变量被初始化为 Long 变量。该数字由编译器根据类的状态和类属性计算。这个数字有助于 jvm 在从文件读取对象状态时识别对象的状态。

为此,我们可以看看官方的 Oracle 文档:

序列化运行库与每个可序列化类关联 版本号,称为 seralVersionUID,在 反序列化以验证序列化的发送方和接收方 对象已经为该对象加载了与 如果接收方已加载用于 对象,该对象具有与 对应的发送方的类,则反序列化将导致 可序列化类可以声明自己的 通过声明名为 必须是静态的、最终的和长类型的“ seralVersionUID”: Any-Access-MODIFIER 静态最终长序列 VersionUID = 42L; 如果 序列化类不显式声明 seralVersionUID, 然后序列化运行时将计算默认值 属性的各个方面为该类设置 seralVersionUID 值 类,如 Java (商标)对象序列化中所述 但是,强烈建议所有 可序列化类显式声明 seralVersionUID 值,因为 默认的 serialVersionUID 计算对类高度敏感 根据编译器实现可能有所不同的详细信息,并且可以 因此,在 因此,为了保证一致的 SerialVersionUID 值,则可序列化 类必须声明一个显式的 seralVersionUID 值 强烈建议显式 seralVersionUID 声明使用 私有修饰符,因为这样的声明只适用于 立即声明的类—— seralVersionUID 字段不是 作为继承成员使用。

如果你已经注意到有另一个关键字,我们已经使用的是 暂时的

如果字段不可序列化,则必须将其标记为瞬态。在这里,我们将 价格标记为瞬态的,并且不希望它被写入文件中

现在让我们看看如何在文件中写入对象的状态,然后从那里读取它。

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]

注意,来自反序列化对象的 价格无效,因为它没有被写入。

序列化对象意味着将其状态转换为字节流,以便可以将字节流还原为对象的副本。如果 Java 对象的类或其任何超类实现了 Java.io,则该对象是可序列化的。可序列化接口或其子接口 java.io。可外化的。反序列化是将对象的序列化形式转换回对象的副本的过程

单击 给你查看更多信息。