Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using setter methods or direct reference to variable inside constructor?

Tags:

java

Both methods work, however which is the proper way to do it?

Method one:

public class Object {
   private String name;

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public Object(String name){
       this.name = name;
   }
}

Method two:

public class Object {
   private String name;

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   //Changed this.name = name to setName(name)
   public Object(String name){
       setName(name);
   }
}

I've searched around but couldn't find an exact question that referred to this. If there is one, free to post the link and I'll remove the question

like image 942
Juxhin Avatar asked Dec 06 '22 00:12

Juxhin


2 Answers

My first thought was to use the setter in the constructor. So if you want to change how the name is stored, or if you want to add any other behavior while setting the name, you just have to change it once.

But thinking just a bit more on this, I think using direct access to the variable is better if the class is not final and the method is not private. Otherwise someone could extend your, override the method, causing your constructor to call their method with unpredictable behavior.

Rule of thumb: If the class is not final, you should only call private methods in the constructor.

like image 178
enrico.bacis Avatar answered May 14 '23 02:05

enrico.bacis


While using a setter in the constructor reduces code duplication, calling overrideable methods (ie non final / non private methods) in a constructor is discouraged - it can lead to weird bugs when extending a class.

Consider the following case (based off of your example):

public class Object {
   private String name;

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   //Changed this.name = name to setName(name)
   public Object(String name){
       setName(name);
   }
}

With the following subclass:

public class SubObject extends Object {
   private String Id;

   @Override
   public void setName(String name) {
       super.setName(name + Id);
   }

   public SubObject(String name){
       super(name);
       this.id = "1";
   }
}

Creating an instance of SubObject will cause a null pointer, as setName() is called in the constructor, but the implementation of setName() relies on the Id field having been initialized.

Someone extending a class should not have to go check the source code of the super class to ensure the constructor isn't calling overrideable methods.

like image 28
rthur Avatar answered May 14 '23 02:05

rthur