The no-argument constructor is a
requirement (tools like Hibernate use
reflection on this constructor to
instantiate objects).
I got this hand-wavy answer but could somebody explain further? Thanks
Hibernate, and code in general that creates objects via reflection use Class<T>.newInstance() to create a new instance of your classes. This method requires a public no-arg constructor to be able to instantiate the object. For most use cases, providing a no-arg constructor is not a problem.
There are hacks based on serialization that can work around not having a no-arg constructor, since serialization uses jvm magic to create objects without invoking the constructor. But this is not available across all VMs. For example, XStream can create instances of objects that don't have a public no-arg constructor, but only by running in a so-called "enhanced" mode which is available only on certain VMs. (See the link for details.) Hibernate's designers surely chose to maintain compatibility with all VMs and so avoids such tricks, and uses the officially supported reflection method Class<T>.newInstance() requiring a no-arg constructor.
Erm, sorry everyone, but Hibernate does not require that your classes must have a parameterless constructor. The JPA 2.0 specification requires it, and this is very lame on behalf of JPA. Other frameworks like JAXB also require it, which is also very lame on behalf of those frameworks.
(Actually, JAXB supposedly allows entity factories, but it insists on instantiating these factories by itself, requiring them to have a --guess what-- parameterless constructor, which in my book is exactly as good as not allowing factories; how lame is that!)
But Hibernate does not require such a thing.
Hibernate supports an interception mechanism, (see "Interceptor" in the documentation,) which allows you to instantiate your objects with whatever constructor parameters they need.
Basically, what you do is that when you setup hibernate you pass it an object implementing the org.hibernate.Interceptor interface, and hibernate will then be invoking the instantiate() method of that interface whenever it needs a new instance of an object of yours, so your implementation of that method can new your objects in whatever way you like.
I have done it in a project and it works like a charm. In this project I do things via JPA whenever possible, and I only use Hibernate features like the interceptor when I have no other option.
Hibernate seems to be somewhat insecure about it, as during startup it issues an info message for each of my entity classes, telling me INFO: HHH000182: No default (no-argument) constructor for class and class must be instantiated by Interceptor, but then later on I do instantiate them by interceptor, and it is happy with that.
To answer the "why" part of the question for tools other than Hibernate, the answer is "for absolutely no good reason", and this is proven by the existence of the hibernate interceptor. There are many tools out there that could have been supporting some similar mechanism for client object instantiation, but they don't, so they create the objects by themselves, so they have to require parameterless constructors. I am tempted to believe that this is happening because the creators of these tools think of themselves as ninja systems programmers who create frameworks full of magic to be used by ignorant application programmers, who (so they think) would never in their wildest dreams have a need for such advanced constructs as the... Factory Pattern. (Okay, I am tempted to think so. I don't actually think so. I am joking.)
Hibernate instantiates your objects. So it needs to be able to instantiate them. If there isn't a no-arg constructor, Hibernate won't know how to instantiate it, i.e. what argument to pass.
The hibernate documentation says:
4.1.1. Implement a no-argument constructor
All persistent classes must have a default constructor (which can be non-public) so that Hibernate can instantiate them using Constructor.newInstance(). It is recommended that you have a default constructor with at least package visibility for runtime proxy generation in Hibernate.
The hibernate is an ORM framework which supports field or property access strategy. However, it does not support constructor-based mapping - maybe what you would like ? - because of some issues like
1º What happens whether your class contains a lot of constructors
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) { ... }
public Person(String name) { ... }
public Person(Integer age) { ... }
}
As you can see, you deal with a issue of inconsistency because Hibernate cannot suppose which constructor should be called. For instance, suppose you need to retrieve a stored Person object
Person person = (Person) session.get(Person.class, <IDENTIFIER>);
Which constructor should Hibernate call to retrieve a Person object ? Can you see ?
2º And finally, by using reflection, Hibernate can instantiate a class through its no-arg constructor. So when you call
Person person = (Person) session.get(Person.class, <IDENTIFIER>);
Hibernate will instantiate your Person object as follows
Person.class.newInstance();
Which according to API documentation
The class is instantiated as if by a new expression with an empty argument list
Moral of the story
Person.class.newInstance();
is similar To
new Person();
Nothing else
Hibernate needs to create instances as result of your queries (via reflection), Hibernate relies on the no-arg constructor of entities for that, so you need to provide a no-arg constructor. What is not clear?
Actually, you can instantiate classes which have no 0-args constructor; you can get a list of a class' constructors, pick one and invoke it with bogus parameters.
While this is possible, and I guess it would work and wouldn't be problematic, you'll have to agree that is pretty weird.
Constructing objects the way Hibernate does (I believe it invokes the 0-arg constructor and then it probably modifies the instance's fields directly via Reflection. Perhaps it knows how to call setters) goes a little bit against how is an object supposed to be constructed in Java- invoke the constructor with the appropriate parameters so that the new object is the object you want. I believe that instantiating an object and then mutating it is somewhat "anti-Java" (or I would say, anti pure theoretical Java)- and definitely, if you do this via direct field manipulation, it goes encapsulation and all that fancy encapsulation stuff.
I think that the proper way to do this would be to define in the Hibernate mapping how an object should be instantiated from the info in the database row using the proper constructor... but this would be more complex- meaning both Hibernate would be even more complex, the mapping would be more complex... and all to be more "pure"; and I don't think this would have an advantage over the current approach (other than feeling good about doing things "the proper way").
Having said that, and seeing that the Hibernate approach is not very "clean", the obligation to have a 0-arg constructor is not strictly necessary, but I can understand somewhat the requirement, although I believe they did it on purely "proper way" grounds, when they strayed from the "proper way" (albeit for reasonable reasons) much before that.
It is much easier to create object with a parameterless constructor through reflection, and then fill its properties with data through reflection, than to try and match data to arbitrary parameters of a parameterized constructor, with changing names/naming conflicts, undefined logic inside constructor, parameter sets not matching properties of an object, et cetera.
Many ORMs and serializers require parameterless constructors, because paramterized constructors through reflection are very fragile, and parameterless constructors provide both stability to the application and control over the object behavior to the developer.
Hibernate uses proxies for lazy loading. If you do no define a constructor or make it private a few things may still work - the ones that do not depend on proxy mechanism. For example, loading the object (with no constructor) directly using query API.
But, if you use session.load method() you'll face InstantiationException from proxy generator lib due to non-availability of constructor.
This guy reported a similar situation:
http://kristian-domagala.blogspot.com/2008/10/proxy-instantiation-problem-from.html
Check out this section of the Java language spec that explains the difference between static and non-static inner classes: http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3
A static inner class is conceptually no different than a regular general class declared in a .java file.
Since Hibernate needs to instantiate ProjectPK independantly of the Project instance, ProjectPK either needs to be a static inner class, or declared in it's own .java file.
reference org.hibernate.InstantiationException: No default constructor
In my case, I had to hide my no-arg constructor, but because Hibernate I couldn't do it. So I solved the problem in another way.
/**
* #deprecated (Hibernate's exclusive constructor)
*/
public ObjectConstructor (){ }
Summarizing of what is below. It matters if you want to be JPA compatible or strictly Hibernate
Just look at official documentation: https://docs.jboss.org/hibernate/orm/5.6/userguide/html_single/Hibernate_User_Guide.html#entity-pojo
Section 2.1 The Entity Class of the JPA 2.1 specification defines its requirements for an entity class. Applications that wish to remain portable across JPA providers should adhere to these requirements:
One point says:
The entity class must have a public or protected no-argument
constructor. It may define additional constructors as well.
However, hibernate is less strict in this:
Hibernate, however, is not as strict in its requirements. The differences from the list above include:
One point says:
The entity class must have a no-argument constructor, which may be
public, protected or package visibility. It may define additional
constructors as well.
More on that is right below:
https://docs.jboss.org/hibernate/orm/5.6/userguide/html_single/Hibernate_User_Guide.html#entity-pojo-constructor
JPA requires that this constructor be defined as public or protected. Hibernate, for the most part, does not care about the constructor visibility, as long as the system SecurityManager allows overriding the visibility setting. That said, the constructor should be defined with at least package visibility if you wish to leverage runtime proxy generation.
This question already has answers here:
Are getters and setters poor design? Contradictory advice seen [duplicate]
(16 answers)
Closed 3 years ago.
from a basic learner!
Is it best to create objects and set their initial state by a constructor or use a set of setters?
Although if I understand it well setters are mutators is their any reason to not prefer them over constructors?
Thank you
Constructors are good if you have a small number of attributes to set, e.g. 2-3 attributes.
If you need to initialize an object that has 10 or more attributes, it can be hard. You have to calculate what position corresponds to what attribute. If let say attribute 7 and attribute 8 out of 12 are both strings, then you can easily pass to parameter 7 value intended for parameter 8, and you will not even notice it, because they have same type and there will be no compile error. This can lead to a bug that requires much time for analysis.
That's why if you have more than 3-4 parameters in constructor, I recommend to use setters instead. When you use setter, you see clearly what value is passed to what parameter. E.g. if you write setName(address), you will notice it quickly and will fix it. Where as in a constructor you could pass address variable to a name parameter and would not notice that.
As a convenient way to use setters you can use builders.
To your comment Setters can't be used to set the inital state of an object?!:
It is opinion based. Some consider object as initialized after contructor completed. The others including me call initialization all steps needed to prepare the object to be used in some application logic. For instance, if you create an instance of java.util.Properties, then call its method load(). I say it is initialized only after this method is called. But as I said there are different opinions about that.
There is no harm using setters over constructor.
However, there is a difference between setter and constructor. If you use a parameterized constructor, you have to pass those attribute values and they kind of become mandatory. With setters, they are optional.
If you already know the attribute values before the object is created, it is preferred to use constructor over setters. There is a time window from creating an object and using it. If the attribute values are not set within that window, there is a change of getting a NullPointerException if the object is used. So, it is preferred to use constructor to be sure that the object is created with necessary attributes.
Constructors are used for object initializations and setter for future changes to the attributes
The difference is partly semantic and partly functional. Functionally, if you need to initialize a field to have some state upon instantiation, there is no difference between using the constructor and creating the object and calling a setter. However, the constructor enforces that this field must be initialized, whereas the setter does not. Furthermore, your setter allows that field to be updated at any point in the lifetime of the object thereafter, while your constructor does not.
What is more important here, though, is the semantics. Doing this work in the constructor is preferred as it makes explicit the dependencies of the class. If someone else were to come along and read your code, it would be clear to them what is required in order to make use of your class.
A constructor is simply a method that is called when a new object is created, its purpose is to initialize everything which every object of the class must have - the basic stuff.
If you think you would later need to modify any fields, then provide setter methods.
I know
A JavaBean is just a standard
All properties private (use getters/setters)
A public no-argument constructor
Implements Serializable.
Source
We all know it is not required to provide a non argument constructor in a class, because if we have not specified any constructor in our class java compiler will create a non argument constructor. If so why programmers wanted to create a non argument constructor in a javabean as a convention.
You are confusing requirements on the JavaBean class with the requirements on its source code. No part of the JavaBeans specification deals with how your source code must look like, it is strictly about the resulting class.
So yes, each JavaBeans class must provide a nullary constructor, and how you achieve that with source code (or even with a bytecode generator) is completely up to you.
It is considered good practice by some to always include the non-arg constructor in your code, because that prevents the scenario where a later maintenance introduces another constructor, thereby discarding the implicit non-arg one, thereby breaking any external code that relies on it.
You don't have to create it explicitly. There's no rule saying you have to do that. Even for a JavaBean, it's fine to leave the compiler to create one for you (as long as you're not providing another one, in which case you'd need an explicit no-arg constructor too).
But there does need to be one, explicit or implicit, because the ORM needs to be able to create instances.
You'd want to create a no argument in these cases:
1) You want to do some logic in the no argument constructor, so can't use the default.
2) You have other constructors that take arguments, in that case no default no-arg constructor will be provided for you.
point 2 implies that having an explicit no arg constructor to start with allows you to add future constructors with arguments without worrying about losing the implicit no-arg constructor.
Without one many API internals like ORMs or IOC containers can't instantiate the object in order to proceed with setting the bean properties from the data source or other bean dependencies.
Many do approximately this:
Class<?> clazz = Class.forName("com.foo.BeanClass");
Constructor<?> constructor = clazz.getConstructor();
Object bean = constructor.newInstance();
I am trying to persist the objects generated by JAXB. Here is the sample structure:
#Column(name = "reporting_identifier")
private String reportingIdentifier;
#Column(name = "apply_quiet_time")
private boolean applyQuietTime;
#Embedded
private RecipientDetailsList recipientDetailsList;
Below is the structure of RecipientDetailsList class:
#ElementCollection(targetClass=String.class)
private List<RecipientDetails> recipientDetails;
Now, the RecipientDetails class has one argument constructor, which accepts a String. That String I want to persist in the database as a part of the whole record. I am seeing
org.hibernate.InstantiationException: No default constructor for entity: RecipientDetailsList
exception when I try to save an object. I have two questions:
Do we have any work around this exception? I can't change the class as it is designed for JAXB marshalling/unmarhsalling. Can I somehow store the objects without altering the structure? Also, I am interested in only storing the first record of the list referenced by
recipientDetails as I want only one row for object. I want it to ignore the rest of the records if it has more than 1 record. Is it possible?
Is this good design to use the annotation directly into classes which are generated by JAXB? Should I create another classes (and possibly mappers/converters) just to store and retrieve the information?
For your first question: this is happening because when Hibernate tries to create a bean, it does it via reflection. It does the object creation by calling the no-arg constructor, and then using the setter methods to set the properties. You can't use a bean that doesn't have a no-arg constructor.
For the second question: if something else has generated classes for you that don't have a no-arg constructor, really your only option (if you can't modify the class) is to create a wrapper round it, or a subclass that has a no-arg constructor. I don't see any other way of doing it if you can't modify the class directly. But the subclassing should be fine as long as the class you've got has enough visibility on the methods (i.e., doesn't have private methods that you then can't get to).
I have a class that implements Serializable, it's part of a bigger mesh of objects, it contains a Constructor field, but when it's the Constructors turn to be serialized it throws the NotSerializableException.
I guess I'll have to write the logic myself and recreate the constructor myself every time I deserialize the containing object, but why the heck on earth would the designers of Java wanna create such hassle in the first place? I realize that the ClassLoader is needed to figure out the identity of a class, and that the ClassLoader itself will not be serialized and deserialized, but shouldn't the constructor remember the string arguments used to create it?
Yes, as you realized Constructor is not serializable.
You need to make the Constructor field transient and restore it manually, when needed.
Yes, the Java designers could have made the Constructor class serialized down to the class name and argument list, but that would open a huge can of worms, basically boiling down to the fact that in any given JVM there can be an arbitrary number of classes with that name and there's no sane way to know which one to use when deserializing such an object.