Serializable
Java中的类对什么意味着什么?或者总的来说...
Serializable
Java中的类对什么意味着什么?或者总的来说...
Answers:
序列化将一个对象从内存中持久保存到一系列位中,例如保存到磁盘上。反序列化是相反的-从磁盘读取数据以水合/创建对象。
就您的问题而言,它是一个接口,如果在一个类中实现,则该类可以由不同的序列化程序自动进行序列化和反序列化。
尽管大多数用户已经给出了答案,但是我想为需要它的人添加一个示例,以解释这个想法:
假设您有一个如下的班级人员:
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();
}
这是序列化的详细说明:(我自己的博客)
序列化:
序列化是序列化一个对象状态的过程,该状态以字节序列的形式表示和存储。可以将其存储在文件中。从文件读取对象状态并还原它的过程称为反序列化。
序列化有什么需要?
在现代体系结构中,始终需要先存储对象状态然后再检索它。例如在Hibernate中,要存储对象,我们应该使类Serializable。它的作用是,一旦对象状态以字节形式保存,就可以将其转移到另一个系统,该系统可以从状态中读取并检索类。对象状态可以来自数据库或其他jvm,也可以来自单独的组件。借助序列化,我们可以检索对象状态。
代码示例和说明:
首先让我们看一下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。
这是使类可序列化的接口。
现在我们可以看到一个名为serialVersionUID的变量被初始化为Long变量。该数字由编译器根据类的状态和类属性计算。当jvm从文件中读取对象的状态时,该数字将帮助jvm识别对象的状态。
为此,我们可以看一下正式的Oracle文档:
序列化运行时与每个可序列化的类关联一个版本号,称为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修饰符,
如果您发现有另一个关键字我们使用了transient。
如果字段不可序列化,则必须将其标记为瞬态。在这里,我们将itemCostPrice标记为瞬态,并且不希望将其写入文件中
现在让我们看一下如何在文件中写入对象的状态,然后从那里读取它。
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的调用就像一个接口,但它更像是编译器的标志。它说可以保存该对象。除无可序列化对象和标记为volatile的对象外,所有Objects实例变量都将被保存。
想象一下,您的应用程序可以更改颜色,而无需将该设置保持在外部,您每次运行时都需要更改颜色。
序列化是一种将对象和数据存储或写入文件的技术。通过使用ObjectOutputStream
和FileOutputStream
类。这些类具有特定的方法来持久化对象。喜欢writeObject();
用数字清楚地解释。有关更多信息,请参见此处
序列化:将对象的状态写入文件/网络或任何地方。(将“ Java对象支持的表单”转换为“文件支持的表单”或“网络支持的表单”)
反序列化:从文件/网络或任何地方读取对象的状态。(将“文件/网络支持的形式”转换为“ Java对象支持的形式”)
Serializable
:Serializability of a class is enabled by the class implementing the java.io.Serializable interface. Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.