Java ObjectInputStream Class
In Java, the ObjectInputStream
class, part of the java.io
package, is used for reading serialized objects from an input stream. It allows you to deserialize data, meaning it converts the byte stream into a Java object that you can manipulate in your application. Serialization is a mechanism to convert an object into a byte stream, and ObjectInputStream
provides a way to read these byte streams back into objects.
Serialization and deserialization are common techniques used for object persistence (saving objects to files or sending objects over a network). ObjectInputStream
is primarily used to read objects that were previously serialized using ObjectOutputStream
.
The ObjectInputStream
class is a subclass of InputStream
, which is used for reading serialized objects from a stream. When you write an object to an output stream (like using ObjectOutputStream
), the object is converted into a byte stream. The ObjectInputStream
class reads this byte stream and converts it back into the original object.
The primary use case for ObjectInputStream
is for deserializing objects. Deserialization allows an application to reconstruct objects that were previously saved or transmitted.
The ObjectInputStream
class inherits methods from InputStream
but also provides unique methods for reading and deserializing objects. Here are the most important ones:
Object readObject()
:
This method is the core function of ObjectInputStream
. It reads the next object from the input stream and returns it. The object is deserialized into its original state.
Object obj = objectInputStream.readObject();
int read()
:
Reads a single byte of data from the input stream. This is inherited from the InputStream
class and can be used for general byte reading.
void close()
:
Closes the stream and releases any system resources associated with it. It is important to close the stream after it is no longer needed.
void defaultReadObject()
:
This method is used when you want to read non-static and non-transient fields from the stream. It's typically used in the context of custom deserialization logic (e.g., when implementing the readObject()
method in your classes).
long skip(long n)
:
Skips over n
bytes of data in the input stream, returning the number of bytes actually skipped.
int available()
:
Returns the number of bytes that can be read from the stream without blocking. This can be useful for checking if data is available to read.
void enableResolveObject(boolean resolve)
:
This method controls whether or not to resolve object references during the deserialization process.
The following example demonstrates how to deserialize a simple object using ObjectInputStream
. In this case, the object is a simple Person
object that was previously serialized.
import java.io.*;
class Person implements Serializable {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
public class ObjectInputStreamExample {
public static void main(String[] args) {
// Assuming the object was previously serialized and saved in "person.ser"
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
Person person = (Person) ois.readObject(); // Read and deserialize the object
System.out.println(person); // Output the deserialized object
} catch (IOException | ClassNotFoundException e) {
System.out.println("An error occurred during deserialization.");
e.printStackTrace();
}
}
}
Explanation:
Person
class implements the Serializable
interface, indicating that instances of this class can be serialized.ObjectInputStream
is used to read the object from a file called person.ser
.readObject()
method deserializes the object and returns it.Note: This example assumes that the object was serialized previously using ObjectOutputStream
.
When dealing with custom serialization, you can define your own deserialization logic by implementing the readObject()
method in your class. This gives you more control over how an object is deserialized.
import java.io.*;
class Person implements Serializable {
String name;
transient int age; // transient fields are not serialized
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject(); // Read default fields
this.age = 30; // Set default value for age after deserialization
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
public class CustomDeserializationExample {
public static void main(String[] args) {
// Assuming the object was serialized in a previous session
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
Person person = (Person) ois.readObject();
System.out.println(person); // Output the deserialized object with custom deserialization logic
} catch (IOException | ClassNotFoundException e) {
System.out.println("An error occurred during deserialization.");
e.printStackTrace();
}
}
}
Explanation:
Person
class has a transient
field age
, which means it won't be serialized by default.readObject()
method is implemented to manually handle the deserialization of the object. It uses defaultReadObject()
to read the non-transient fields and sets a default value for the age
field.In some scenarios, you may deserialize objects that are being sent over a network. Below is an example of deserializing an object received via a socket connection.
import java.io.*;
import java.net.*;
class Person implements Serializable {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
public class NetworkDeserializationExample {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(12345)) {
System.out.println("Server is waiting for connection...");
try (Socket socket = serverSocket.accept();
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
Person person = (Person) ois.readObject(); // Deserialize object from network stream
System.out.println("Received object: " + person);
} catch (IOException | ClassNotFoundException e) {
System.out.println("An error occurred during deserialization.");
e.printStackTrace();
}
} catch (IOException e) {
System.out.println("An error occurred while setting up the server.");
e.printStackTrace();
}
}
}
Explanation:
ServerSocket
. The server listens for incoming connections and deserializes the received object using ObjectInputStream
.Note: This example assumes that an object was serialized and sent from a client to the server.
ObjectInputStream
allows you to restore an object from its serialized form, which is useful for object persistence and network communication.readObject()
and defaultReadObject()
.Serializable
interface, making it seamless to handle object-based data.