Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Must a Bean have a default constructor?

Tags:

java

javabeans

I'm reading the JavaBean specification but I can't find a sentence where it clearly states that a bean must have a default constructor. So does it or doesn't?

like image 401
zer0uno Avatar asked May 11 '16 20:05

zer0uno


People also ask

Is it mandatory to have default constructor?

The compiler doesn't ever enforce the existence of a default constructor. You can have any kind of constructor as you wish. For some libraries or frameworks it might be necessary for a class to have a default constructor, but that is not enforced by the compiler.

Is default constructor mandatory in Spring?

No, you are not required to use default (no arg) constructors.

Can a bean have private constructor?

Yes, Spring can invoke private constructors. If it finds a constructor with the right arguments, regardless of visibility, it will use reflection to set its constructor to be accessible.

Is it mandatory to have default constructor in C#?

We also call this as a special method of the class. In case we don't provide any constructor in the class, the compiler will create a default constructor for that particular class. So by default there will be one constructor of the class and it's mandatory.


2 Answers

You can look at the wikipedia about java bean:

https://en.wikipedia.org/wiki/JavaBeans

The bean should have a public default constructor is one of the rules for it qualifying as a JavaBean. However, this is not explicitly defined by the standard, but is a good practice adopted by many frameworks.

EDIT: If we were to elaborate about the reasons WHY a non-args constructor is desired (but generally not enforced), below is one of the reasons:

CDI frameworks generally have two way of injecting dependencies in your bean:

Constructor injection: Where you have defined explicitly the dependencies of your bean in its constructor. Example (Spring):

@Component
public class SuchBean {
     private MuchDependency muchDependency;

     @Autowired
     public SuchBean(MuchDependency muchDependency){
         this.muchDependency = muchDependency;
     }

}

Setter/Reflection injection: Where you haven't necessarily injected any dependencies through the constructor, but the dependencies are injected by the CDI environment by either using reflection or the setters. Example:

@Component
public class SuchBean {
     // this dep doesn't have a setter, so the CDI will use reflection to set it
     @Autowired private MuchDependencyWithReflection muchDependencyWithReflection;
     // this dep has a setter so the CDI will use the setter to set it
     @Autowired private MuchDependencyWithSetter muchDependencyWithSetter;

     public void setMuchDependencyWithSetter(MuchDependencyWithSetter muchDependencyWithSetter){
         this.muchDependencyWithSetter = muchDependencyWithSetter;
     }
}

In the above example, if you haven't explicitly defined the no-args constructor, of course, you know, Java provides it for you (cause every class that doesn't have any constructor explicitly defined, just has an automatically provided no-args constructor). So everything would be fine and dandy until you decide to define your own constructor with args:

@Component
public class SuchBean {
     // this dep doesn't have a setter, so the CDI will use reflection to set it
     @Autowired private MuchDependencyWithReflection muchDependencyWithReflection;
     // this dep has a setter so the CDI will use the setter to set it
     @Autowired private MuchDependencyWithSetter muchDependencyWithSetter;

     public SuchBean(String nonDefaultConstuctorArg){
         System.out.println(nonDefaultConstuctorArg);
     }

     public void setMuchDependencyWithSetter(MuchDependencyWithSetter muchDependencyWithSetter){
         this.muchDependencyWithSetter = muchDependencyWithSetter;
     }
}

In the above example it is not obvious, but any dependency framework would complain and won't be able to instantiate it, because in fact, when you are using reflection/setter injection, the framework does:

Constructor.newInstance();

behind the scenes AND then injects the dependencies. However, since you just made your class not have a default constructor, newInstance() without args wouldn't work. Hence, you need a default args constructor in this case. To summarize:

  • If you use constructor injection, you don't need a no-args constructor.
  • If you use reflection/setter injection, you need to use a no-args constructor.
  • Since good code should have good conventions, the JavaBeans standard "nudges" you into having a default no-args constructor everywhere to have a consistent, conventional code that is usable across various frameworks and being readable/understandable/maintainable due to its standardization.
like image 52
Nikola Yovchev Avatar answered Sep 23 '22 04:09

Nikola Yovchev


A bean does not need to have a default constructor. Simply because the spec does not define that requirement.

Additionally chapter 10.3 Instantiating a bean talks about obtaining bean instances:

A bean can be delivered as either a serialized template (which must be deserialized to create an instance of the bean) or as an implementation class (where a bean instance is created simply by creating an instance of the class).

This strategy is implemented by Beans.instantiate: It looks for a serialized bean (a special named Java resource). If it doesn't find one it tries to instantiate the bean via Class.newInstance. But this mechanism clearly shows that the spec writers thought about providing a generic method to get bean instances which do not have a default constructor.

like image 41
wero Avatar answered Sep 23 '22 04:09

wero