Is it possible in java to create 'blank' instance of class without no-arg constructor using reflection?

17,622

Solution 1

With standard reflection, no, but there is a library that can do it for you: objenesis.

It's specifically designed to instantiate classes without default constructors, and it's used by other serialization libraries like xstream.

Note: the constructor might not be called in these cases (but that's presumably what you want).

Solution 2

Having Class instance provided as variable clazz:

ReflectionFactory rf = ReflectionFactory.getReflectionFactory();
Constructor objDef = parent.getDeclaredConstructor();
Constructor intConstr = rf.newConstructorForSerialization(clazz, objDef);
clazz.cast(intConstr.newInstance());

as described in http://www.javaspecialists.eu/archive/Issue175.html

Solution 3

Your solution will be JVM specific.

If you need a portable solution use a 3rd party library.

For Sun's JVM v1.5 you can do this:

    final Class<?> myClass = MyClass.class;
    final ReflectionFactory reflection = ReflectionFactory.getReflectionFactory();
    final Constructor<Object> constructor = 
        reflection.newConstructorForSerialization(
            myClass, Object.class.getDeclaredConstructor(new Class[0]));
    final Object o = constructor.newInstance(new Object[0]);

    System.out.print(o.getClass());

The relevant classes in XStream are:

  • com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider
  • com.thoughtworks.xstream.core.JVM;

Solution 4

The only solution I can think of would be to use a bytecode manipulation library such as javassist to add a default constructor.

Solution 5

If your class has no other constructor, then the compiler will create one for you. You might have a no-arg constructor and not realize it.

If you do not write a no-arg constructor, and you include even one constructor that takes an argument, then the compiler will not give you one. Reflection won't help, either: if you try to find a no-arg constructor and there isn't one, what do you expect to happen?

It doesn't sound like you can use Java object serialization using java.lang.Serializable, but that's not your only choice. You can also use XML, or JSON, or prototype buffers, or any other protocol that's convenient.

Share:
17,622
Vladimir
Author by

Vladimir

Updated on June 16, 2022

Comments

  • Vladimir
    Vladimir almost 2 years

    I have a class which has not default constructor. And I need a way to get 'blank' instance of this class. 'blank' means that after instantiation all class fields should has default values like null, 0 etc.

    I'm asking because I need to be able serialize/desirialize big tree of objects. And I have no access to sources of this objects classes and classes has neither default constructors nor implements serializable. It is likely not very good idea to try to serialize such structure but the alternative is to convert it to something more easily serializable.

  • Sean Patrick Floyd
    Sean Patrick Floyd over 13 years
    +1 for being (almost) the only one who knows what he (and the OP) is talking about
  • Sean Patrick Floyd
    Sean Patrick Floyd over 13 years
    Nice. We might have a winner here! (+1)
  • iirekm
    iirekm over 13 years
    I agree - very evil. When a programmer creates no ctor they he/she expects that nobody calls it, and - surprise! :-)
  • iirekm
    iirekm over 13 years
    But from the other side, "normal" reflection also breaks the rules of class design (like accessing private fields), but at least most programmers realize, that such thing like reflection exists. Very few programmers know about objensis.
  • Francis Upton IV
    Francis Upton IV over 12 years
    Keep in mind though that the ReflectionFactory class is a Sun class so this will only work on Sun/Oracle VMs, and even then it's subject to change.
  • Wayne Citrin
    Wayne Citrin almost 8 years
    Not particularly evil -- very useful in implementing custom serialization schemes, particularly when the original object isn't implemented as serializable. .NET has a method, FormatterServices.GetUninitializedObject(), for just this purpose. I wish Java had something similar that was "official."
  • Raffi Khatchadourian
    Raffi Khatchadourian over 7 years
    Where does parent come from?
  • Jordan
    Jordan over 6 years
    yes not particularly evil, but it can be used to break at least one of the guarantees of Java: jqno.nl/post/2015/02/28/hacking-java-enums
  • duffymo
    duffymo over 6 years
    Unsafe wasn't an option in 2010 when this question was posted. It's a JDK 9 feature: javaworld.com/article/2952869/java-platform/…
  • Ordiel
    Ordiel over 5 years
    This should by far be the accepted answer. I also have the same question (as so many other mothers)... who is/provides the parent...? or is it a list of calling newConstructorForSerlialization all the way up to a no arg constructor class either serializable or not? and then just filling up the instantiated classes with the serialized data?
  • Guss
    Guss almost 4 years
    Regarding parent - I think the idea is to "skip" the inaccessible c'tor and use one of the super classes' c'tor instead - so as much of the object fields will be initialized properly. As per @jonstok's answer, you can even just use Object's default c'tor. The main think that I worry about here - fields that the provided c'tor don't know about, are they zero-initialized?
  • Guss
    Guss almost 4 years
    If I understand correctly, your code causes Sun's ReflectionFactory to use Object's default constructor in place of MyClass's inaccessible constructors. This seems to work but the question remains - are MyClass fields zero initialized when no constructor code exist that know them? I tried to follow the code for ReflectionFactory but it was somewhat too complex for me.