Setter methods or constructors

JavaConstructorSetter

Java Problem Overview


so far I have seen two approaches of setting a variable's value in Java. Sometimes a constructor with arguments is used, others setter methods are used to set the value of each variable.

I know that a constructor initialises an instance variable inside a class once a class is instantiated using the "new" Keyword.

But when do we use constructors and when do we use setters?

Java Solutions


Solution 1 - Java

You should use the constructor approach, when you want to create a new instance of the object, with the values already populated(a ready to use object with value populated). This way you need not explicitly call the setter methods for each field in the object to populate them.

You set the value using a setter approach, when you want to change the value of a field, after the object has been created.

For example:-

MyObject obj1 = new MyObject("setSomeStringInMyObject"); // Constructor approach
// Yippy, I can just use my obj1, as the values are already populated
// But even after this I can change the value
obj1.setSomeString("IWantANewValue"); // Value changed using setter, if required.
..
MyObject obj2 = new MyObject();
obj2.setSomeString("setSomeStringNow"); // Setter approach
// values weren't populated - I had to do that. Sad :(

And as Axel mentioned, if you want to create immutable objects, you cannot use setter-methods approach. I won't say everything has to be initialised in the constructor because different approaches exist, like lazy-evaluation which can be used even with immutable objects.

Solution 2 - Java

I think you asked a good question: - But when do we use constructors and when do we use setters?

First, let's start with some concepts. I hope this explanation helps everybody that want to know when to use constructors or setters() and getters() methods (Accessors and Mutators). Constructors are similar to Methods, however there are few differences between constructor and method in java:

  1. Constructor is used to initialize the state of an object. Method is used to expose behaviour of an object.

  2. Constructor must not have return type. Method must have return type.

  3. Constructor is invoked implicitly. Method is invoked explicitly.

  4. Getters(), or accessors, are methods that provide access to an object's instance variables. Setters(), or mutators, are methods that provide the caller with an opportunity to update the value of a particular instance variable.

Having this clear, let's think in term of Object Oriented Programming (OOP), to meet the requirement of OOP principals (The Objects Oriented Programming (OOP) is constructed over four major principles: Encapsulation, Data Abstraction, Polymorphism and Inheritance.), Getter() and Setter() methods is the key to achieve this.

Here is a formula that is going to show you what I mean:

> Private fields + Public accessors == Encapsulation;

As you can see based on this formula when we set private fields and use public accesors we are performing encapsulation one of the 4 OOP principals.

Here I am going to provide you two classes, I added comment on it to try to make my code self explaining. Take these classes as a lab on methods with Customer and TestCustomer [the one with the main() method] classes, you can copy the code and run it yourself. Note I used two constructors in order to explain a class having multiple constructors and having public setters() and getters() methods in order to access private instance variables:

package com.exercise.lecture2;

/**
 * 1) Create a Customer class that has the following attributes:
 * name, SSN.
 * 2) This class should have two methods: getName() and getSSN().
 * 3) If the class is instantiated with only a SSN, then give the default name of "John Doe". (HINT: Use two constructors)
 * 4) Also, add a method toString(), that returns a string representation of the customer object (name and SSN concatenated).
 * 		Make sure to set this method public.
 * 5) Create a class to test your program (e.g. a class that include the main() method). In your test program, instantiate
 * 		three customers and print out the value using toString() method.
 * 
 * @author Samuel M.
 *
 */

//this class is complemented with class  TestLabCustomer.java
public class LabCustomer {

// Private filds: name and socialSecurityNum
	private String name;
	private int socialSecurityNum;
	
	// constructors
	public LabCustomer(String name, int socialSecurityNum) {
		this.name = name;
		this.socialSecurityNum = socialSecurityNum;
	}
	
	/** The keyword 'this' can be used to call a constructor from a constructor,
	 * when writing several constructor for a class, there are times when
	 * you'd like to call one constructor from another to avoid duplicate code.
	 */
	// Account with This() on a second constructor
	public LabCustomer(int socialSecurityNum) {
		this("John Doe", socialSecurityNum); // default name is printed if only the SSN is provided
	}
	
	// Public accessors (getters and setters)
	String getName() {
		return name;
	}
	
	void setName(String name) {
		this.name = name;
	}
	
	int getSSN() {
		return socialSecurityNum;
	}
	
	void setSSN(int socialSecurityNum) {
		this.socialSecurityNum = socialSecurityNum;
	}

	
	// instance method
	public String toString() { //overriding the toString() method 
		return ("Customer name: " + getName() + ", SSN#: " + getSSN() ); // concatenating the name and SSN
		
	}
}

Here is the test class, the one that has the main() method and calling an instance method after instantiating an object of the previews class:

package com.exercise.lecture2;

//this class is complemented with class  LabCustomer.java
public class TestLabCustomer {

	public static void main(String[] args) {
		// Instantiating an object of class LabCustomer and creating three customers objects
		LabCustomer cust1 = new LabCustomer("Juan Melendez", 123457789);
		LabCustomer cust2 = new LabCustomer("Mary Lee", 125997536);
		LabCustomer cust3 = new LabCustomer(124963574); // when instantiating with no "name", the default (John Doe) is printed 
		
		/**
		 * Once you've instantiated an object and have an object variable,
		 * you can use object variable to call an instance method. 
		 * 	e.g.:
		 * 	object variables: cust1, cust2, cust3
		 * 	call the method toString() using the object variable and dot [.] in order to perform the method call.
		 */
		// calling method toString() in class LabCustomer to print customer values
		System.out.println(cust1.toString());
		System.out.println(cust2.toString());
		System.out.println(cust3.toString());

	}

}

> result: > > Customer name: Juan Melendez, SSN#: 123457789 > > Customer name: Mary Lee, SSN#: 125997536 > > Customer name: John Doe, SSN#: 124963574

Solution 3 - Java

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.

Refer to documentation page for more details.

Solution 4 - Java

If you want to have an immutable class use constructor otherwise use setters.

Solution 5 - Java

We use the approach depending on the scenario.

  1. Constructor Approach: We should go ahead with this approach when there are parameters which are mandatory for object's instantiation and we can not construct an object without them.

  2. Setter Approach: For optional parameters we can go ahead with the setter approach.

Solution 6 - Java

In most cases, i use both of them :) (since you 9/10 times want to come back and edit something (and that isn't a good practice to make a new instance of it)

I normally make something like this

    public class User {

    	private int id;
    	private String initials;
    	private String firstName;
    	private String lastName;
    	private String email;
	
    	public User() {
          	this(0, "", "", "");
    	}
	
     	public User(int id, String firstName, String lastName, String email) {
		    this.id = id;
	      	this.firstName = firstName;
	    	this.lastName = lastName;
	    	this.email = email;
	    }
       // Getters and setters should be here
    }

And when you want to edit something with it you can just use the setters, (a good thing if you for example is saving your users in an ArrayList, then you can just get the object from the arraylist and just set the field you wanna edit, instead of making a brand new object of it :)

Solution 7 - Java

Say we have a class, named Counter:

public class Counter{
    int count;
    //constructor
    public Counter(int c){
        count = c;
    }
    public void setCounter(int newCounter){
        count = newCounter;
    }
}

In the class above, when you want to create a new Counter object, you would use a constructor and set the count variable within that. like so:

Counter myCounter = new Counter(1);

If you want to change the count variable during runtime, you would use the setter method:

myCounter.setCounter(2);

Solution 8 - Java

In case of Constructors, When you update fields, you create a new object every time by using new keyword.

Customer customer = new Customer("Tom", 23, 10000);

For example, if you want to update the salary of Tom, you need to write this line again with updated salary, that means memory is wasted.

In case of setter methods you can set individual fields in original object only.

Solution 9 - Java

It depends on application domain and purpose of the class in it.

Java beans normally have a no arg constructor and getter/setters for relevant member variables. There are advantages to this approach as Java beans are supported out of the box in many frameworks like Struts and Spring.

A class can also enforce mandatory availability of values by having such variables passed as parameters to a base constructor. And non-mandatory values can be set through other convenience constructors or setter methods.

On the other hand immutable classes can have constructors but require absence methods that modify its state including setters.

Overall, such decisions can be made with consideration to overall design of application, frameworks1 it runs in, contract it must enforce, etc.

1 - Although, its recommended that class design should be independent of frameworks. Good frameworks like Spring don't enforce such requirements.

Solution 10 - Java

You can combine the two aproaches. Inside the constructor you can invoke the setters of instace variables. Something like:

public class TestClass {
    private String someField;

    public TestClass(String someField) {
        setSomeField(someField);
    }

    public String getSomeField() {
        return someField;
    }

    public void setSomeField(String someField) {
        this.someField = someField;
    } 
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionssayyedView Question on Stackoverflow
Solution 1 - JavaRahulView Answer on Stackoverflow
Solution 2 - JavaS. MayolView Answer on Stackoverflow
Solution 3 - JavaRavindra babuView Answer on Stackoverflow
Solution 4 - JavaEvgeniy DorofeevView Answer on Stackoverflow
Solution 5 - JavaeatSleepCodeView Answer on Stackoverflow
Solution 6 - JavaKasper Sanguesa-FranzView Answer on Stackoverflow
Solution 7 - JavahmirView Answer on Stackoverflow
Solution 8 - JavaJackView Answer on Stackoverflow
Solution 9 - Javasgp15View Answer on Stackoverflow
Solution 10 - JavaColdView Answer on Stackoverflow