Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calling setters from a constructor

Tags:

java

oop

What are the pro's and con's of calling out to a mutator from a constructor (if any)

i.e.:

public MyConstructor(int x) {   this.x = x; } 

versus:

public MyConstructor(int x) {   setX(x); }  public void setX(int x) {   this.x = x; } 

Do you have a preference? (This is not homework, just looking at our coding standards doc where it says to always call out to mutators when setting instance var's in the constructor and I don't always to this)

like image 414
Billworth Vandory Avatar asked Feb 04 '11 01:02

Billworth Vandory


People also ask

Can we call setter method from constructor in Java?

Yes, calling instance methods from constructors can be hard to reason about, and is not generally preferred. Now, if you want to move your validation logic into a private, final class/static method, and call it from both the constructor and setter, that would be fine.

Do you need setters if you have a constructor?

In simple terms: Use constructor if you think initialization is mandatory before you can use the object. Use setter method when initialization of variable is non-mandatory to use the object.

Can we use getter and setter in constructor in Java?

Getters and setters are used to protect your data, particularly when creating classes. For each instance variable, a getter method returns its value while a setter method sets or updates its value.

Which is better constructor or setter?

Use Setter injection when a number of dependencies are more or you need readability. Use Constructor Injection when Object must be created with all of its dependency.


2 Answers

Personally, I would set the variable directly in most cases.

Methods usually expect that the instance is fully-formed by the time they're called. In particular, calling an overridden method from a constructor is a recipe for hard-to-understand code and hard-to-spot bugs.

Having said that, I often try to make classes immutable anyway, in which case not only is there no setter, but you have to set the final variable from the constructor (or a variable initializer) anyway :)

Where properties have logic, setter logic is usually validation and sometimes change propagation to observers. I'd usually expect the constructor parameters to be checked explicitly at the start of the method, and you wouldn't want any change propagation to occur before an instance is fully created anyway.

like image 68
Jon Skeet Avatar answered Sep 20 '22 12:09

Jon Skeet


I follow two rules about constructors to minimize problems which are why I would not use the mutator method:

Constructors (of non-final classes) should call only final or private methods. If you decide to ignore this rule and let the constructor call non-final/non-private methods, then:

  • those methods and any methods they may call must be careful not to assume the instance is fully initialized, and
  • the subclasses that override those methods (subclasses that may not even be aware that the superclass constructor is calls those methods) must not assume that the subclass constructor and superclasses' constructors have been fully executed. This problem gets worse the deeper down the inheritance hierarchy the superclass with the "evil" constructor is.

Is all that extra cognitive baggage worth it? You could allow an exception for simple mutators that only assign a value to an instance variable, since there's little benefit, even that doesn't seem worth it.

[[ @Jon Skeet mentions this in his answer: "... In particular, calling an overridden method from a constructor is a recipe for hard-to-understand code and hard-to-spot bugs." But I don't think the ramifications of this problem is stressed enough. ]]

Constructors should be cautious about leaking this before the instance is fully initialized. While the previous rule was about methods inside the class and subclasses accessing ivars, you must also be careful about (even final/private) methods passing this to other classes and utility functions before this is fully initialized. The more non-private, overridable methods that the constructor calls, the greater the risk of leaking this.


Some references about constructors calling non-final, non-private methods:

https://www.securecoding.cert.org/confluence/display/java/MET05-J.+Ensure+that+constructors+do+not+call+overridable+methods

http://www.javaworld.com/article/2074669/core-java/java-netbeans--overridable-method-call-in-constructor.html

http://www.javaspecialists.eu/archive/Issue210.html

like image 24
Bert F Avatar answered Sep 19 '22 12:09

Bert F