Java 可序列化是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3429921/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 00:43:16  来源:igfitidea点击:

What does Serializable mean?

javaserializable

提问by Ritwik Bose

What exactly does it mean for a class to be Serializablein Java? Or in general, for that matter...

SerializableJava 中的类究竟意味着什么?或者一般来说,就此而言......

采纳答案by Oded

Serializationis persisting an object from memory to a sequence of bits, for instance for saving onto the disk. Deserialization is the opposite - reading data from the disk to hydrate/create an object.

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

In the context of your question, it is an interface that if implemented in a class, this class can automatically be serialized and deserialized by different serializers.

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

回答by David

It means that instances of the class can be turned into a byte-stream (for example, to be saved to a file) and then converted back into classes again. This reloading could happen in a different instance of the program, or even on a different machine. Serialisation (in any language) involves all sorts of issues, though, especially when you've got references to other objects inside the serialisable one.

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

回答by AphexMunky

Serializable is called in like an interface but its more like a flag to the compiler. It says this object can be saved. All the Objects instance variables with the exception of none serializable objects and ones mark volatile will be saved.

Serializable 像接口一样被调用,但它更像是编译器的标志。它说这个对象可以保存。除了不可序列化的对象和标记为 volatile 的对象之外的所有对象实例变量都将被保存。

Imagine your application can change colour as an option, without keeping that setting external you would need to change the colour every time you ran it.

想象一下,您的应用程序可以作为一个选项更改颜色,而无需将该设置保留在外部,您每次运行时都需要更改颜色。

回答by Jigar Joshi

Serialization involves saving the current state of an object to a stream, and restoring an equivalent object from that stream. The stream functions as a container for the object

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

回答by Greg Sexton

Just to add to the other answers and with regards to generality. Serialization is sometimes known as archiving, for example in Objective-C.

只是为了添加其他答案和一般性。序列化有时也称为归档,例如在 Objective-C 中。

回答by Mdhar9e

Serialization is a technique to storing or writing the objects and data in to files. By using ObjectOutputStreamand FileOutputStreamclasses. These classes having their specific methods to persist the objects. like writeObject();

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

for clear explantaion with figures . See Here for more info

用数字清楚地解释。请参阅此处了解更多信息

回答by nanospeck

To present from another perspective. Serialization is a kind of interface called 'marker interface'. A marker interface is an interface that contains no method declarations, but merely designates (or “marks”) a class that implements the interface as having some property. If you understand polymorphism this will make very much sense. In the case of the Serializable marker interface, the ObjectOutputStream.write(Object) method will fail if its argument does not implement the interface. This is a potential mistake in java, it could have been ObjectOutputStream.write(Serializable)

从另一个角度呈现。序列化是一种称为“标记接口”的接口。标记接口是一个不包含方法声明的接口,而只是指定(或“标记”)一个实现接口的类,该类具有某些属性。如果您了解多态性,这将非常有意义。在 Serializable 标记接口的情况下,如果 ObjectOutputStream.write(Object) 方法的参数未实现该接口,则该方法将失败。这是 java 中的一个潜在错误,它可能是 ObjectOutputStream.write(Serializable)

Highly Recommended : Reading Item 37 from Effective Java by Joshua Blochto learn more.

强烈推荐:阅读Joshua Bloch 的 Effective Java 中的第 37 条以了解更多信息。

回答by William Kinaan

Though most of the users have already given the answer, but I would like to add an example for those who need it in order to explain the idea:

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

Let's say you have a class person like the following:

假设您有一个如下所示的班级人员:

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

and then you create an object like this:

然后你创建一个这样的对象:

Person william = new Person();
        william.firstName = "William";
        william.lastName = "Kinaan";
        william.age = 26;
        william.address = "Lisbon, Portugal";

You can serialise that object to many streams. I will do that to two streams:

您可以将该对象序列化为多个流。我将对两个流执行此操作:

Serialization to standard output:

序列化到标准输出:

public static void serializeToStandardOutput(Person person)
            throws IOException {
        OutputStream outStream = System.out;
        ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream);
        stdObjectOut.writeObject(person);
        stdObjectOut.close();
        outStream.close();
    }

Serialization to a file:

序列化到文件:

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

Then:

然后:

Deserialize from file:

从文件反序列化:

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

回答by Asif Mushtaq

Serialization:Writing State of Object to File/Network or anywhere. ( Mean Java Object Supported form to File Supported Form or Network Supported Form )

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

Deserialization:Reading State of Object from File/Network or anywhere. ( Mean File/Network Supported form to Java Object Supported Form )

反序列化:从文件/网络或任何地方读取对象的状态。(平均文件/网络支持形式到 Java 对象支持形式)

回答by Pritam Banerjee

Here is a detailed explanation of the Serialization: (my own blog)

这里是Serialization的详细解释:(我自己的博客)

Serialization:

序列化:

Serialization is the process of serializing the state of an object is represented and stored in the form of a sequence of bytes. This can be stored in a file. The process to read the state of the object from the file and restoring it is called deserialization.

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

What is the need of Serialization?

序列化需要什么?

In modern day architecture, there is always a need to store object state and then retrieve it. For example in Hibernate, to store a object we should make the class Serializable. What it does, is that once the object state is saved in the form of bytes it can be transferred to another system which can then read from the state and retrieve the class. The object state can come from a database or a different jvm or from a separate component. With the help of Serialization we can retrieve the Object state.

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

Code Example and explanation:

代码示例和说明:

First let's have a look at the Item Class:

首先让我们看一下 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;
        }
}

In the above code it can be seen that Itemclass implements Serializable.

在上面的代码中可以看出Item类实现了Serializable

This is the interface that enables a class to be serializable.

这是使类能够序列化的接口。

Now we can see a variable called serialVersionUIDis initialized to Long variable. This number is calculated by the compiler based on the state of the class and the class attributes. This is the number that will help the jvm identify the state of an object when it reads the state of the object from file.

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

For that we can have a look at the official Oracle Documentation:

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

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long: ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members.

序列化运行时将每个可序列化类与一个称为 serialVersionUID 的版本号相关联,在反序列化期间使用它来验证序列化对象的发送方和接收方是否已为该对象加载了与序列化兼容的类。如果接收方为对象加载了一个与相应发送方类具有不同 serialVersionUID 的类,则反序列化将导致 InvalidClassException。一个可序列化的类可以通过声明一个名为“serialVersionUID”的字段来显式声明它自己的serialVersionUID,该字段必须是静态的、最终的和long类型:ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; 如果可序列化类未显式声明 serialVersionUID,然后序列化运行时将根据该类的各个方面计算该类的默认 serialVersionUID 值,如 Java(TM) 对象序列化规范中所述。但是,强烈建议所有可序列化类显式声明 serialVersionUID 值,因为默认的 serialVersionUID 计算对可能因编译器实现而异的类详细信息高度敏感,因此可能会在反序列化期间导致意外的 InvalidClassExceptions。因此,为了保证在不同的 Java 编译器实现中具有一致的 serialVersionUID 值,可序列化类必须声明一个显式的 serialVersionUID 值。还强烈建议显式的 serialVersionUID 声明在可能的情况下使用 private 修饰符,

If you have noticed there is another keyword we have used which is transient.

如果您注意到我们使用了另一个关键字,它是瞬态

If a field is not serializable, it must be marked transient. Here we marked the itemCostPriceas transient and don't want it to be written in a file

如果字段不可序列化,则必须将其标记为瞬态。这里我们将itemCostPrice标记为瞬态,不希望将其写入文件

Now let's have a look on how to write the state of an object in the file and then read it from there.

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

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

In the above we can see an example of serialization and deserialization of an object.

在上面我们可以看到一个对象的序列化和反序列化的例子。

For that we used two classes. For serializing the object we have used ObjectOutputStream. We have used the method writeObject to write the object in the file.

为此,我们使用了两个类。为了序列化对象,我们使用了 ObjectOutputStream。我们已经使用方法 writeObject 将对象写入文件。

For Deserializing we have used ObjectInputStream which reads from the object from the file. It uses readObject to read the object data from the file.

对于反序列化,我们使用了从文件中读取对象的 ObjectInputStream。它使用 readObject 从文件中读取对象数据。

The output of the above code would be like:

上面代码的输出类似于:

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]

Notice that itemCostPricefrom deserialized object is nullas it was not written.

请注意,来自反序列化对象的itemCostPrice空,因为它没有被写入。