Wednesday, January 15, 2014

Why Default or No Argument Constructor is Important in Java Class

Almost all Java developers knows that compiler adds a default constructor or better known as no argument constructor in every Java class, but many of them forget that, it only does when you don't provide any other constructor. Which means it becomes developers responsibility to add a no argument constructor, if he is adding explicit constructor. Now, Why it's important to provide default constructor in Java, What happens if your class don't have a no argument constructor? Well, this is how it's asked in many Java interviews, most commonly as part of Spring and Hibernate interviews. It's not mandatory to define default constructor, but if you are writing Hibernate persistent class, JPA entities or using Spring framework to manage object creation and wiring dependencies, you need to be bit careful. Many of open source framework, uses reflection to create instance or Object at runtime, based upon name of class. For example When Hibernate creates instance of entities using reflection it uses Class.newInstance() method, which require a no argument constructor to create an instance. It's effectively equivalent of new Entity(). This method throws InstantiationException if it doesn't found any no argument constructor in Entity class, and that's why it's advised to provide a no argument constructor.



Effect of not defining Default Constructor in Java

Why Provide No Argument Constructor in a Java class
By the way it's not just Hibernate, who make use of Reflection to create instance of class. If you are familiar with Spring and Dependency Injection, that you might know that Spring also creates instance of class using reflection, but it's more sophisticated and allow you to choose which constructor to call by specifying various constructor argument using <constructor-arg value="someValue"/> and <constructor-arg ref="someRefrence"/> tags.

How about this code, do you think this will work if Order class doesn't have a no argument constructor?

<bean id="OrderManager" class="com.exchange.OrderManager">
           <property name="symbolValidator" ref="someSymbolValidator"/>
</bean>

No, it will not work if your OrderManager class has an explicit constructor, because above configuration will create instance of OrderManager by calling no argument constructor and than use Setter Injection to provided dependency. If you have defined your class like below, then you better use constructor injection to create instance of this bean.

public class OrderManager{
    private SymbolValidator symbolValidator;

    public OrderManager(SymbolValidator validator){
         symbolValidator = validator;
    }

    .....

}


Above configuration will show following error :

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'OrderManager' defined in class path resource [app-config.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.exchange.OrderManager]: No default constructor found;

So, You should always define a no argument constructor in your Java class, even if you are writing an explicitly constructor, until you are absolutely sure that, it's won't be instantiated using reflection and instantiating it with no argument constructor is a bug, like in our example of Spring Bean management. Though, In case of Hibernate Persistent classes or Entities, it's must to provide a no argument constructor, so that Hibernate can create instance of Persistence classes, when you hibernate load them from database. It also uses newInstance() method to create instance of persistent classes.

4 comments :

Venkateswarlu konda said...

How we know, java.lang package is default ?

Debjit Saha said...

Using an IDE like Eclipse points out to such issues even before you compile the code. So if you create that parametrized constructor and forget the default constructor, there's Eclipse to come to your rescue!

Peter Lawrey said...

You might like to make a comment about Unsafe.allocateInstance(Class) which doesn't call a constructor.

Anonymous said...

Recently I missed no-argument constructor for a class, which was not final but doesn't implement an interface and don't have a default constructor, because of another parameteric constructor present in the class. Now you can't create mock or dummy version of that class, because
a) it doesn't implement an interface
b) there is no default constructor, means you can't extend it until you use their parametric constructor, which is not possible in case of dummy implementation. This makes testing that class a lot difficult. This teaches me lesson that implement interface and provide no arg constructor alteast.

Post a Comment