What does Serializable mean?
在Java中,一个类是什么样的EDOCX1?0是什么意思?或者一般来说,就这一点而言…
序列化将对象从内存持久化为一系列位,例如保存到磁盘上。反序列化是相反的-从磁盘读取数据以水合物/创建对象。
在您的问题上下文中,它是一个接口,如果在一个类中实现,这个类可以由不同的序列化程序自动序列化和反序列化。
虽然大多数用户都已经给出了答案,但我想为那些需要它的人添加一个示例,以便解释这个想法:
假设你有一个像下面这样的班主任:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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...... First Name = %s Last Name = %s", firstName, lastName); } } |
然后创建这样的对象:
1 2 3 4 5 | Person william = new Person(); william.firstName ="William"; william.lastName ="Kinaan"; william.age = 26; william.address ="Lisbon, Portugal"; |
号
可以将该对象序列化为多个流。我要对两条小溪这样做:
标准输出序列化:
1 2 3 4 5 6 7 8 | public static void serializeToStandardOutput(Person person) throws IOException { OutputStream outStream = System.out; ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream); stdObjectOut.writeObject(person); stdObjectOut.close(); outStream.close(); } |
对文件的序列化:
1 2 3 4 5 6 7 | 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(); } |
。
然后:
从文件反序列化:
1 2 3 4 5 6 7 8 9 | 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(); } |
这意味着类的实例可以转换为字节流(例如,保存到文件中),然后再转换回类。这种重新加载可能发生在程序的不同实例中,甚至可能发生在不同的机器上。尽管串行化(在任何语言中)涉及到各种各样的问题,特别是当在可串行化的对象中有对其他对象的引用时。
下面是对序列化的详细解释:(我自己的博客)
序列化:
序列化是序列化的过程。对象的状态以字节序列的形式表示和存储。这可以存储在一个文件中。从文件中读取对象状态并将其还原的过程称为反序列化。
序列化的需要是什么?
在现代建筑中,总是需要存储对象状态,然后检索它。例如,在Hibernate中,为了存储对象,我们应该使类可序列化。它所做的是,一旦对象状态以字节的形式保存,它就可以传输到另一个系统,该系统随后可以从状态中读取并检索类。对象状态可以来自数据库、不同的JVM或单独的组件。在序列化的帮助下,我们可以检索对象状态。
代码示例和说明:
首先,让我们看看item类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 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类实现了可序列化。
这是使类可序列化的接口。
现在我们可以看到一个名为serialversionuid的变量被初始化为long变量。这个数字是由编译器根据类的状态和类属性计算的。当JVM从文件中读取对象的状态时,这个数字将帮助它识别对象的状态。
为此,我们可以查看正式的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.
号
如果您注意到有另一个关键字,我们使用它是暂时的。
如果字段不可序列化,则必须将其标记为"瞬态"。在这里,我们将itemCostPrice标记为瞬态,不希望将其写入文件中。
现在让我们看看如何在文件中写入对象的状态,然后从中读取它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 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。我们已经使用write object方法将对象写入文件中。
对于反序列化,我们使用了从文件中读取对象的objectinputstream。它使用readObject从文件中读取对象数据。
上述代码的输出如下:
1 2 3 | 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为空,因为它没有被写入。
序列化涉及将对象的当前状态保存到流,并从该流中还原等效对象。流用作对象的容器
序列化的调用类似于接口,但更像编译器的标志。它说这个对象可以被保存。除无可序列化对象和标记为volatile的对象外,将保存所有对象实例变量。
假设您的应用程序可以作为一个选项更改颜色,而不将该设置保持在外部,您每次运行它时都需要更改颜色。
序列化是一种将对象和数据存储或写入文件的技术。使用
为了清楚地解释数字。有关详细信息,请参阅此处
序列化:将对象的状态写入文件/网络或任何位置。(JAVA对象支持的表单到文件支持的表单或网络支持表单)
反序列化:从文件/网络或任何位置读取对象的状态。(平均文件/网络支持的表单到Java对象支持的表单)
从另一个角度呈现。序列化是一种称为"标记接口"的接口。标记接口是不包含方法声明的接口,但是仅指定(或"标记")实现接口的类一些财产。如果你理解多态性,这将非常有意义。在可序列化标记接口的情况下,如果ObjectOutputStream.Write(Object)方法的参数不实现该接口,则该方法将失败。这是Java中的一个潜在错误,它可能是ObjutOutsStudio.Wrrad(可序列化)。
强烈推荐:从Joshua Bloch的有效Java阅读第37项,以了解更多。
只是为了增加其他的答案和一般性。序列化有时被称为归档,例如在Objective-C中。