Well, after reading the title, first thought which comes to mind is “Is there a guideline for Getter/Setter in java?” .
The answer is “No, there isn’t, this blog entry is my mistakes done during my last 10 years of coding (or many times people refer to it as “experience” :D)”.
So let's get started, I will not go into details of what, why, how etc of object oriented programming and where do getter/setter fit in, but if you google it out, you will find detailed explanations on these topics.
Mistake No 1: Is assigning the object reference directly into the Setter of business objects.
For example: Consider a Employee class having int[] array of employeeIds with a default setter coded for it. Assume below code is written in some method:
.....Some business code...
.....Some business code...int[] employeeIds= {5001, 5002, 4002, 3002, 2004, 9874};employeeObj.setEmployeeIds(employeeIds);
.....
employeeIds[1] = 1; // setting the value 1 resets the value of employeeObj employeeIds array index 1’s value from 5002 to 1.
.....
Hence I will always recommend to write setter like below :
public void setEmployeeIds(int[] ids)
{
this.employeeIds = new int[ids.length];
System.arraycopy(ids, 0, this.employeeIds, 0, ids.length);
}
Mistake No 2 : Is returning the object reference directly from the Getter for business objects.
Suppose somewhere in the business logic the code is as follows :
.....Some business code...
// lets say employee Obj has these Ids= {5001, 6002, 4002, 3002};
.....Some business code...int[] employeeIds= employeeObj.getEmployeeIds();
.....
employeeIds[1] = 891; // setting the value 1 resets the value of employeeIds array index 1’s value from 6002 to 891.
.....
Hence to fix the above issue, I would recommend to write the getter as follows:
public int[] getEmployeeIds()
{
int len = this.employeeIds.length;
int[] copyIds = new int[len];
System.arraycopy(this.employeeIds, 0, copyIds, 0, len);
return copyIds;
}
Mistake No 3. Writing Getter/Setter for mutable Java data types e.g java.util.Date. or Calendar etc.
Java has some mutable data types e.g Date, Calendar etc, if any one resets the value using a get method or using a reference method , it becomes a huge maintainability headache while debugging(searching using method references can turn out to be an ardent task).Hence I would always recommend to always write getter and setter using defensive copy i.e deep cloning.
public void setDateOfJoining(Date date)
{
this.dateOfJoining = (Date) date.clone();
}public Date getDateOfJoining()
{
return (Date) this.dateOfJoining.clone();
}
Mistake No 4: Getter/Setter for Collection of business objects.
As mistake no 3 points out cloning for mutable data types of java this is also applicable for mutable business object or mutable collection of objects.
Lets say every employee works on multiple Project so with in each Employee object we hold a list of Project, keeping the above in mind to always return a copy we write our getter/setter as follows :
private List<Project> projectList;public void setProjectList(List<Project> list)
{
this.projectList = new ArrayList<Project>(list);
}public List<Project> getProjectList()
{
return new ArrayList<Project>(this.projectList);
}
But there is a flaw which can be exposed as follows:
...In some business method...
...some business Code ...List<Project> list1 = new ArrayList<>();
list1.add(new Project("Government Project 1"));
list1.add(new Project("Internal Project #20"));
list1.add(new Project("Self Project #12"));employeeObj.setProjectList(list1);
list1.get(2).setProjectName("Dummy Wrong Project"); // This line sets wrong project name since new collection is pointing to same Project object.
So to avoid the above mistake always implement clone method with deep cloning as follows :
public Object clone()
{
Project cloneProject = new Project(this.projectName);
....
.... return cloneProject;
}
And in Employee Class
public void setProjectList(List<Project> list)
{
for (Project project: list)
{
this.projectList.add((Project) project.clone());
}
}public List<Project> getProjectList()
{
List<Project> listReturn = new ArrayList<>();
for (Project project: this.projectList)
{
listReturn.add((Project) project.clone());
}
return listReturn;
}
Mistake No 5 : Getter/Setter is required for private scope, they are pretty much useless if provided for public scoped variable.
This is self explanatory, this mistake seldom happens but needs to be taken care.