Home  >  Article  >  Java  >  Detailed explanation of basic examples of using object serialization in java tutorial

Detailed explanation of basic examples of using object serialization in java tutorial

高洛峰
高洛峰Original
2017-01-18 11:25:051128browse

This process can also be implemented over the network. You can first create an object on a Windows machine, serialize it, and then send it to a Unix machine over the network, and then re-"assemble" it accurately there. One of them, such as RMI, Socket, JMS, and EJB, why they can transfer Java objects to each other is of course due to the object serialization mechanism.

Java object serialization mechanism generally has two uses:

Java's JavaBeans: Bean's status information is usually configured at design time, and Bean's status information must be stored. In order to restore this state information when the program is running, this requires saving the state of the object to a file, and then reconstructing the object and restoring the program state by reading the object state.
RMI allows you to operate objects on a remote machine as if they were on the local machine; or for programs that use sockets to transmit objects over the network, these require the implementation of the serializaiton mechanism.
We can serialize a class by letting the class implement the Java.io.Serializable interface. This interface is a marker interface. That is, the interface does not need to implement any methods for the class to implement it. It is mainly used to notify the Java Virtual Machine (JVM) that an object needs to be serialized.

Regarding this, there are several points we need to be clear about:

Not all classes can be serialized. Under cmd, we enter serialver Java.net.Socket to get whether the socket can be serialized. Information, in fact, the socket is not serializable.
Java has many basic classes that have implemented the serializable interface, such as string, vector, etc. But for example, hashtable does not implement the serializable interface.
There are two main classes for reading or writing objects into streams: ObjectOutputStream and ObjectInputStream. ObjectOutputStream provides the writeObject method for writing objects to the output stream, and ObjectInputStream provides the readObject method for reading objects from the input stream. Objects using these methods must already be serialized. That is, the Serializable interface must have been implemented. If you want to writeobject a hashtable object, then you will get an exception.
The process of serialization is to write objects into the byte stream and read objects from the byte stream. After converting the object state into a byte stream, you can use the various byte stream classes in the Java.io package to save it to a file, pipe it to another thread, or send the object data to another host over a network connection. The object serialization function is very simple and powerful, and has applications in RMI, Socket, JMS, and EJB. The problem of object serialization is not the most exciting topic in network programming, but it is quite important and has many practical implications.
Object serialization can implement distributed objects. Main applications include: RMI uses object serialization to run services on the remote host just like when running objects on the local machine.
Java object serialization not only retains the data of one object, but also recursively saves the data of each object referenced by the object. The entire object hierarchy can be written to a byte stream, which can be saved in a file or passed over a network connection. Object serialization can be used to perform "deep copy" of the object, that is, copying the object itself and the referenced object itself. Serializing an object may result in the entire object sequence.
Java serialization is relatively simple, and there is usually no need to write custom code to save and restore object state. Class objects that implement the Java.io.Serializable interface can be converted to or restored from a byte stream without adding any code to the class. Only in rare cases will custom code be needed to save or restore object state. Note here: not every class can be serialized, and some classes cannot be serialized. For example, classes involving threads have a very complex relationship with a specific JVM.

Serialization mechanism:

Serialization is divided into two parts: serialization and deserialization. Serialization is the first part of the process, breaking the data into a stream of bytes so that it can be stored in a file or transmitted over the network. Deserialization is all about opening the byte stream and reconstructing the object. Object serialization not only converts basic data types into byte representations, but sometimes also restores the data. Restoring data requires an object instance of the restored data. The serialization process in ObjectOutputStream is connected with the byte stream, including object type and version information. When deserializing, the JVM uses the header information to generate an object instance, and then copies the data in the object byte stream to the object data members. Below we will explain it in two parts:

Processing object streams: (serialization process and deserialization process)
The Java.io package has two classes for serializing objects. ObjectOutputStream is responsible for writing objects to byte streams, and ObjectInputStream reconstructs objects from byte streams.
Let’s first understand the ObjectOutputStream class. The ObjectOutputStream class extends the DataOutput interface.
The writeObject() method is the most important method and is used for object serialization. If the object contains references to other objects, the writeObject() method recursively serializes those objects. Each ObjectOutputStream maintains a serialized object reference table to prevent sending multiple copies of the same object. (This is important) Since writeObject() can serialize an entire set of cross-referenced objects, the same ObjectOutputStream instance may be accidentally requested to serialize the same object. At this time, dereference serialization is performed instead of writing the object byte stream again.

Now, let us learn about the ObjectOutputStream class from an example.

// 序列化 today's date 到一个文件中.  
FileOutputStream  f = new  FileOutputStream ("tmp" );  
ObjectOutputStream  s = new  ObjectOutputStream (f);  
s.writeObject("Today" );  
s.writeObject(new  Date ());  
s.flush();

Now, let us understand the ObjectInputStream class. It is similar to ObjectOutputStream. It extends the DataInput interface. The methods in ObjectInputStream mirror the public methods in DataInputStream for reading Java basic data types. The readObject() method deserializes an object from a byte stream. Each time the readObject() method is called, the next Object in the stream is returned. The object byte stream does not transmit the bytecode of the class, but includes the class name and its signature. When readObject() receives the object, the JVM loads the class specified in the header. If this class is not found, readObject() throws ClassNotFoundException. If you need to transmit object data and bytecode, you can use the RMI framework. The remaining methods of ObjectInputStream are used to customize the deserialization process.
Examples are as follows:

//从文件中反序列化 string 对象和 date 对象  
FileInputStream  in = new  FileInputStream ("tmp" );  
ObjectInputStream  s = new  ObjectInputStream (in);  
String  today = (String )s.readObject();  
Date  date = (Date )s.readObject();
custom serialization process:
Serialization can usually be completed automatically, but sometimes the process may need to be controlled. Java can declare a class as serializable, but you can still manually control the data members declared as static or transient.

Example: A very simple serialization class.

public  class  simpleSerializableClass implements  Serializable {  
String  sToday="Today:" ;  
transient  Date  dtToday=new  Date ();  
}

When serializing, all data members of the class should be serializable except members declared as transient or static. Declaring a variable as transient tells the JVM that we will be responsible for serializing the variable. After a data member is declared as transient, the serialization process cannot add it to the object byte stream. There is no data sent from the transient data member. When the data is deserialized later, the data member needs to be reconstructed (because it is part of the class definition), but it does not contain any data because this data member does not write any data to the stream. Remember, object streams do not serialize static or transient objects. Our class will use the writeObject() and readObject() methods to handle these data members. When using the writeObject() and readObject() methods, be sure to read these data members in the order they are written.
Part of the code on how to use custom serialization is as follows

//重写writeObject()方法以便处理transient的成员。  
public  void  writeObject(ObjectOutputStream  outputStream) throws  IOException {  
outputStream.defaultWriteObject();//使定制的writeObject()方法可以  
//利用自动序列化中内置的逻辑。  
outputStream.writeObject(oSocket.getInetAddress());  
outputStream.writeInt(oSocket.getPort());  
}  
//重写readObject()方法以便接收transient的成员。  
private  void  readObject(ObjectInputStream  inputStream) throws IOException ,  
ClassNotFoundException {  
inputStream.defaultReadObject();//defaultReadObject()补充自动序列化  
InetAddress  oAddress=(InetAddress )inputStream.readObject();  
int  iPort =inputStream.readInt();  
oSocket = new  Socket (oAddress,iPort);  
iID=getID();  
dtToday =new  Date ();  
}

Fully customized serialization process:
If a class is to be fully responsible for its own serialization, implement the Externalizable interface instead of the Serializable interface. The Externalizable interface definition includes two methods writeExternal() and readExternal(). These methods can be used to control how the object data members are written to the byte stream. When a class implements Externalizable, the header is written to the object stream, and then the class is fully responsible for serializing and restoring the data members. Except for the header, there is no automatic serialization at all. Something to note here. Declaring a class to implement the Externalizable interface poses a significant security risk. The writeExternal() and readExternal() methods are declared as public, and malicious classes can use these methods to read and write object data. Use extreme caution if the object contains sensitive information. This includes using secure sockets or encrypting the entire byte stream. So far, we have learned the basics of serialization.

For more detailed explanations of basic examples of object serialization in java tutorials and related articles, please pay attention to the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn