“对象序列化”是什么意思?你能举例解释一下吗?
当前回答
将文件返回为Object: http://www.tutorialspoint.com/java/java_serialization.htm
import java.io.*;
public class SerializeDemo
{
public static void main(String [] args)
{
Employee e = new Employee();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try
{
FileOutputStream fileOut =
new FileOutputStream("/tmp/employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in /tmp/employee.ser");
}catch(IOException i)
{
i.printStackTrace();
}
}
}
import java.io.*;
public class DeserializeDemo
{
public static void main(String [] args)
{
Employee e = null;
try
{
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
}catch(IOException i)
{
i.printStackTrace();
return;
}catch(ClassNotFoundException c)
{
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
其他回答
序列化意味着在java中持久化对象。如果您希望保存对象的状态,并希望稍后重新构建该状态(可能在另一个JVM中),则可以使用序列化。
注意,对象的属性只会被保存。如果你想再次恢复对象,你应该有类文件,因为只存储成员变量而不存储成员函数。
eg:
ObjectInputStream oos = new ObjectInputStream(
new FileInputStream( new File("o.ser")) ) ;
SerializationSample SS = (SearializationSample) oos.readObject();
serializable是一个标记接口,用来标记你的类是可序列化的。标记接口意味着它只是一个空接口,使用该接口将通知JVM该类可以被序列化。
序列化是将对象转换为一系列字节,以便可以轻松地将对象保存到持久存储器或通过通信链路进行流式传输。然后可以反序列化字节流,将其转换为原始对象的副本。
序列化是将Java对象转换为字节数组,然后再将其转换为保留状态的对象的过程。适用于通过网络发送对象或将内容缓存到磁盘等各种事情。
请阅读这篇简短的文章,它很好地解释了编程过程的一部分,然后转到Serializable javadoc。你也可能对这个相关的问题感兴趣。
我在自己的博客上说:
下面是关于序列化的详细解释:(我自己的博客)
序列化:
序列化是持久化对象状态的过程。它以字节序列的形式表示和存储。这可以存储在一个文件中。从文件中读取对象状态并恢复它的过程称为反序列化。
序列化的需求是什么?
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.
代码示例及说明:
首先让我们来看看Item Class:
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在从文件中读取对象的状态时识别对象的状态。
为此,我们可以看看官方的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.
如果你注意到我们使用的另一个关键字是瞬态的。
如果字段不可序列化,则必须将其标记为transient。这里我们将itemCostPrice标记为transient,不希望将其写入文件中
现在让我们看看如何在文件中写入对象的状态,然后从那里读取它。
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是空的,因为它没有被写入。
在本文的第一部分中,我们已经讨论了Java序列化的基础知识。
现在让我们深入讨论它以及它是如何工作的。
首先让我们从serialversionuid开始。
serialVersionUID用作Serializable类中的版本控制。
如果您没有显式地声明serialVersionUID, JVM将根据Serializable类的各种属性自动为您声明。
Java的计算serialversionuid的算法(在这里阅读更多细节)
The class name. The class modifiers written as a 32-bit integer. The name of each interface sorted by name. For each field of the class sorted by field name (except private static and private transient fields: The name of the field. The modifiers of the field written as a 32-bit integer. The descriptor of the field. If a class initializer exists, write out the following: The name of the method, . The modifier of the method, java.lang.reflect.Modifier.STATIC, written as a 32-bit integer. The descriptor of the method, ()V. For each non-private constructor sorted by method name and signature: The name of the method, . The modifiers of the method written as a 32-bit integer. The descriptor of the method. For each non-private method sorted by method name and signature: The name of the method. The modifiers of the method written as a 32-bit integer. The descriptor of the method. The SHA-1 algorithm is executed on the stream of bytes produced by DataOutputStream and produces five 32-bit values sha[0..4]. The hash value is assembled from the first and second 32-bit values of the SHA-1 message digest. If the result of the message digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named sha, the hash value would be computed as follows:
long hash = ((sha[0] >>> 24) & 0xFF) |
> ((sha[0] >>> 16) & 0xFF) << 8 |
> ((sha[0] >>> 8) & 0xFF) << 16 |
> ((sha[0] >>> 0) & 0xFF) << 24 |
> ((sha[1] >>> 24) & 0xFF) << 32 |
> ((sha[1] >>> 16) & 0xFF) << 40 |
> ((sha[1] >>> 8) & 0xFF) << 48 |
> ((sha[1] >>> 0) & 0xFF) << 56;
Java的序列化算法
The algorithm to serialize an object is described as below: 1. It writes out the metadata of the class associated with an instance. 2. It recursively writes out the description of the superclass until it finds java.lang.object. 3. Once it finishes writing the metadata information, it then starts with the actual data associated with the instance. But this time, it starts from the topmost superclass. 4. It recursively writes the data associated with the instance, starting from the least superclass to the most-derived class.
要记住的事情:
Static fields in a class cannot be serialized. public class A implements Serializable{ String s; static String staticString = "I won't be serializable"; } If the serialversionuid is different in the read class it will throw a InvalidClassException exception. If a class implements serializable then all its sub classes will also be serializable. public class A implements Serializable {....}; public class B extends A{...} //also Serializable If a class has a reference of another class, all the references must be Serializable otherwise serialization process will not be performed. In such case, NotSerializableException is thrown at runtime.
Eg:
public class B{
String s,
A a; // class A needs to be serializable i.e. it must implement Serializable
}
将文件返回为Object: http://www.tutorialspoint.com/java/java_serialization.htm
import java.io.*;
public class SerializeDemo
{
public static void main(String [] args)
{
Employee e = new Employee();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try
{
FileOutputStream fileOut =
new FileOutputStream("/tmp/employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in /tmp/employee.ser");
}catch(IOException i)
{
i.printStackTrace();
}
}
}
import java.io.*;
public class DeserializeDemo
{
public static void main(String [] args)
{
Employee e = null;
try
{
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
}catch(IOException i)
{
i.printStackTrace();
return;
}catch(ClassNotFoundException c)
{
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
推荐文章
- 如何分割逗号分隔的字符串?
- Java字符串—查看字符串是否只包含数字而不包含字母
- Mockito.any()传递带有泛型的接口
- 在IntelliJ 10.5中运行测试时,出现“NoSuchMethodError: org.hamcrest. matcher . descripbemismatch”
- 使用String.split()和多个分隔符
- Java数组有最大大小吗?
- 在Android中将字符串转换为Uri
- 从JSON生成Java类?
- 为什么java.util.Set没有get(int index)?
- Swing和AWT的区别是什么?
- 为什么Java流是一次性的?
- 四舍五入BigDecimal *总是*有两位小数点后
- 设计模式:工厂vs工厂方法vs抽象工厂
- Java:检查enum是否包含给定的字符串?
- 它的意思是:序列化类没有声明一个静态的最终serialVersionUID字段?