Search code examples
javajavabeans

Must a Bean have a default constructor?


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?


Solution

  • 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.