Java Specialists' Java Training Europehome of the java specialists' newsletter

The Java Specialists' Newsletter
Issue 1752009-09-08 Category: Tips and Tricks Java version: Java 6.0

GitHub Subscribe Free RSS Feed

Creating Objects Without Calling Constructors

by Dr. Heinz M. Kabutz
Abstract:
De-Serialization creates objects without calling constructors. We can use the same mechanism to create objects at will, without ever calling their constructors.

Welcome to the 175th issue of The Java(tm) Specialists' Newsletter. Something rather odd happened last night in Crete, which has not occurred since May. We had water falling down from the sky! So, it is time that I say goodbye to my extended summer holiday and start working again :-)

I am en route to the JavaZone conference in Oslo, Norway, where I will be speaking about some of the weird and wonderful things you can do with reflection (download slides here). Hope to see some of you at the conference! The organizers thought it would be fun to give me the second-last speaking slot of the last day ... at least if I embarrass myself, there won't be too many witnesses :-)

NEW: Please see our new "Extreme Java" course, combining concurrency, a little bit of performance and Java 8. Extreme Java - Concurrency & Performance for Java 8.

Creating Objects Without Calling Constructors

A few months before disappearing amongst the sand dunes of Chania's beaches on my extended summer vacation, I was explaining to the students on my advanced Java course how deserialization worked. If the object is serializable, then it is created magically without having the constructor called. If its parent class is not serializable, then the super class no-args constructor is invoked. For example, let's begin with a superclass that does not implement Serializable:

public class NotSerializable {
  public NotSerializable() {
    System.out.println("NotSerializable constructor called");
  }
}
  

We subclass this with MySerializable that prints out a message in the constructor:

import java.io.Serializable;

public class MySerializable extends NotSerializable
    implements Serializable {
  public MySerializable() {
    System.out.println("MySerializable constructor called");
  }
}
  

We now write the MySerializable object to an ObjectOutputStream and generate a byte[] from which we then read back the object. When we run this, we see that the NotSerializable constructor is called twice, once when the MySerializable object is constructed and once when it is deserialized. We also see that the MySerializable constructor is only called once:

import java.io.*;

public class DeserializeTest {
  public static void main(String[] args)
      throws IOException, ClassNotFoundException {
    MySerializable ms = new MySerializable();

    // writing object to byte[]
    System.out.println("writing ms");
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(ms);
    oos.close();
    byte[] objectInBinaryForm = baos.toByteArray();

    // reading object from byte[]
    System.out.println("reading ms2");
    ObjectInputStream ois = new ObjectInputStream(
        new ByteArrayInputStream(objectInBinaryForm)
    );
    MySerializable ms2 = (MySerializable) ois.readObject();
    System.out.println("ms == ms2 = " + (ms == ms2));
    System.out.println("ms = " + ms);
    System.out.println("ms2 = " + ms2);
  }
}
  

The output is the following, note the number of times that each constructor is called:

    NotSerializable constructor called
    MySerializable constructor called
    writing ms
    reading ms2
    NotSerializable constructor called
    ms == ms2 = false
    ms = MySerializable@1827391d
    ms2 = MySerializable@6f7a29a1
  

By digging around a bit, I found the code that is used to construct the serializable object without calling the constructor, which we can use to create objects. To use it, we need to specify the first class in our hierarchy, where we want to call the actual constructor. For example, to simulate what happens in the DeserializeTest, we could call it with

      SilentObjectCreator.create(
        MySerializable.class,
        NotSerializable.class)
    
Here is my SilentObjectCreator, used to instantiate objects without invoking any constructors:

import sun.reflect.ReflectionFactory;
import java.lang.reflect.Constructor;

public class SilentObjectCreator {
  public static <T> T create(Class<T> clazz) {
    return create(clazz, Object.class);
  }

  public static <T> T create(Class<T> clazz,
                             Class<? super T> parent) {
    try {
      ReflectionFactory rf =
          ReflectionFactory.getReflectionFactory();
      Constructor objDef = parent.getDeclaredConstructor();
      Constructor intConstr = rf.newConstructorForSerialization(
          clazz, objDef
      );
      return clazz.cast(intConstr.newInstance());
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new IllegalStateException("Cannot create object", e);
    }
  }
}
  

In our test class, we demonstrate what happens when we create the MySerializable by also calling the superclass constructor and the default behaviour of only calling Object's constructor:

public class CreationTest {
  public static void main(String[] args) {
    // Creating MySerializable by calling NotSerializable no-args
    // constructor, but not the MySerializable constructor.
    MySerializable ms = SilentObjectCreator.create(
            MySerializable.class, NotSerializable.class);
    System.out.println("ms = " + ms);

    // Creating MySerializable by not calling any constructors.
    MySerializable ms2 = SilentObjectCreator.create(
        MySerializable.class
    );
    System.out.println("ms2 = " + ms2);
  }
}
  

In the output we see that in the first case, the NotSerializable constructor is called, but not in the second:

    NotSerializable constructor called
    ms = MySerializable@1d5ee671
    ms2 = MySerializable@593d93f4
  

We can use this mechanism to create just about any class, except abstract classes. For example, here we are making Thread.State.class instances:

import java.lang.reflect.Field;

public class EnumCreation {
  public static void main(String[] args) throws Exception {
    Thread.State fastAsleep =
        SilentObjectCreator.create(Thread.State.class);
    Field name = Enum.class.getDeclaredField("name");
    name.setAccessible(true);
    name.set(fastAsleep, "FAST_ASLEEP");
    System.out.println("fastAsleep = " + fastAsleep);
  }
}
  

This creates enum instances, but for a better approach, please see my newsletter 161.

This SilentObjectCreator could of course also be used to create Singleton instances, even if we were very careful to protect ourselves against that. For example:

public class Singleton {
  private static final Singleton instance = new Singleton();

  private Singleton() {
    if (instance != null) {
      throw new IllegalStateException("already initialized");
    }
  }

  public static Singleton getInstance() {
    return instance;
  }

  // etc.
}
  

We can now easily make several instances of this, despite the check in the constructor, by simply instantiating it with the SilentObjectCreator class.

Disclaimer

We should avoid using sun.* classes in our code directly, as it is then not portable and will break if we change JDKs. In my original article, I did not mention this (on purpose) as I assume that readers of an advanced Java newsletter would be aware of this.

Kind regards

Heinz

Tips and Tricks Articles Related Java Course

Java Master
Java Concurrency
Design Patterns
In-House Courses



© 2010-2014 Heinz Kabutz - All Rights Reserved Sitemap
Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners. JavaSpecialists.eu is not connected to Oracle, Inc. and is not sponsored by Oracle, Inc.
@CORE_THE_BAND #RBBJGR