Java - ObjectOutputStream writeObjectOverride(Object obj) method



Description

The Java ObjectOutputStream writeObjectOverride(Object obj) method is used by subclasses to override the default writeObject method. This method is called by trusted subclasses of ObjectInputStream that constructed ObjectInputStream using the protected no-arg constructor. The subclass is expected to provide an override method with the modifier "final".

  • It is only called if you override the ObjectOutputStream.writeObject(Object obj) method and call writeObjectOverride() from there.

  • This gives you full control over how objects are written - useful for custom serialization, filtering, encryption, logging, etc.

Declaration

Following is the declaration for java.io.ObjectOutputStream.writeObjectOverride(Object obj) method.

public void writeObjectOverride(Object obj)

Parameters

  • obj − The object to be written.

Return Value

This method does not return a value.

Exception

  • IOException − If I/O errors occur while writing to the underlying stream.

Example - Automatically replace null objects with default values during serialization

The following example shows the usage of ObjectOutputStream writeObjectOverride(Object obj) method. If a null object is passed to writeObject(), we'll serialize a default fallback value instead (e.g., "UNKNOWN" string).

ObjectOutputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class ObjectOutputStreamDemo {
   public static void main(String[] args) {
      String filename = "override3.ser";

      try (CustomStream oos = new CustomStream(new FileOutputStream(filename))) {
         oos.writeObjectOverride(null);                  // Should serialize "UNKNOWN"
         oos.writeObjectOverride("Normal string");       // Should serialize as-is
      } catch (IOException e) {
         e.printStackTrace();
      }

      // Read the objects back
      try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
         Object first = ois.readObject();
         Object second = ois.readObject();

         System.out.println("First object: " + first);
         System.out.println("Second object: " + second);
      } catch (IOException | ClassNotFoundException e) {
         e.printStackTrace();
      }
   }

   // Custom ObjectOutputStream that replaces nulls with "UNKNOWN"
   static class CustomStream extends ObjectOutputStream {
      public CustomStream(OutputStream out) throws IOException {
         super(out);
      }

      @Override
      protected void writeObjectOverride(Object obj) throws IOException {
         if (obj == null) {
            System.out.println("Replacing null with default string.");
            super.writeObject("UNKNOWN");
         } else {
            super.writeObject(obj);
         }
      }
   }
}

Output

Let us compile and run the above program, this will produce the following result −

Replacing null with default string.
First object: UNKNOWN
Second object: Normal string

Explanation

  • We override writeObjectOverride(Object o) to check for null.

  • Instead of letting ObjectOutputStream write null, we substitute a default value ("UNKNOWN").

  • This technique is useful when serializing data for systems that can’t handle null cleanly.

Example - Log every object that is being serialized

The following example shows the usage of ObjectOutputStream writeObjectOverride(Object obj) method. We're printing the class name of each object before serializing it.

ObjectOutputStreamDemo.java

package com.tutorialspoint;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class ObjectOutputStreamDemo {
   public static void main(String[] args) throws IOException {
      try (CustomStream oos = new CustomStream(new FileOutputStream("override1.ser"))) {
         oos.writeObjectOverride("Hello World");
         oos.writeObjectOverride(123);
      }
   }

   static class CustomStream extends ObjectOutputStream {
      public CustomStream(OutputStream out) throws IOException {
         super(out);
         enableReplaceObject(true);  // Optional: to use replaceObject if needed
      }

      @Override
      protected void writeObjectOverride(Object obj) throws IOException {
         System.out.println("Serializing object of type: " + obj.getClass().getName());
         super.writeObject(obj);  // still call base method to actually serialize
      }       
   }
}

Output

Let us compile and run the above program, this will produce the following result−

Serializing object of type: java.lang.String
Serializing object of type: java.lang.Integer

Example - Block serialization of specific classes

The following example shows the usage of ObjectOutputStream writeObjectOverride(Object obj) method. We're throwing an exception if someone tries to serialize a Secret object.

ObjectOutputStreamDemo.java

package com.tutorialspoint;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

public class ObjectOutputStreamDemo {

   public static void main(String[] args) {
      try (CustomStream oos = new CustomStream(new FileOutputStream("override2.ser"))) {
         oos.writeObjectOverride("Safe Data");
         oos.writeObjectOverride(new Secret("This should not be saved"));
      } catch (IOException e) {
         System.err.println("Exception: " + e.getMessage());
      }
   }

   static class Secret implements Serializable {
      String data;
      public Secret(String data) {
         this.data = data;
      }
   }

   static class CustomStream extends ObjectOutputStream {
      public CustomStream(OutputStream out) throws IOException {
         super(out);
      }

      @Override
      protected void writeObjectOverride(Object obj) throws IOException {
         if (obj instanceof Secret) {
            throw new NotSerializableException("Blocked class: " + obj.getClass().getName());
         }
         super.writeObject(obj);
      }
   }
}

Output

Let us compile and run the above program, this will produce the following result−

Exception: Blocked class: com.tutorialspoint.ObjectOutputStreamDemo$Secret
java_io_objectoutputstream.htm