0

I have following classes :

Emp.java

final public class Emp { private Integer id; private String name; private Department department; public Emp(Integer id, String name, Department department) { this.id = id; this.name = name; this.department = department; } public Department getDepartment() { return department; } public Integer getId() { return id; } public String getName() { return name; } } 

Department.java

public class Department { private Integer id; private String name; public Department(Integer id, String name) { this.id = id; this.name = name; } public Integer getId() { return id; } public String getName() { return name; } public void setId(Integer id) { this.id = id; } public void setName(String name) { this.name = name; } } 

EmployeeTest.java

public class EmployeeTest { public static void main(String args[]) { Department dept1 = new Department(1, "dept1"); Emp emp = new Emp(1, "emp1", dept1); emp.getDepartment().setName("dept2"); System.out.println("emp = "+emp); } } 

Here Emp class is not purely an immutable class because somehow I am able to change the values of Department (as shown in the example).

What are the best possible changes which will make Emp class a pure Immutable class ?

3
  • 1
    Why do you need the setters in Department? Commented Aug 20, 2012 at 9:10
  • There might be a chances that Department class can be used at other places also... My intention is to make Emp class pure immutable, not Department. Commented Aug 20, 2012 at 9:14
  • 3
    The technique you need is called defensive copying. Google is at your disposal. Commented Aug 20, 2012 at 9:17

5 Answers 5

3

In getters for non-primitive field, use this structure

public class Line { private final Point start; private final Point end; public Line(final Point start, final Point end) { this.start = new Point(start); this.end = new Point(end); } public Point getStart() { return new Point(start); } public Point getEnd() { return new Point(end); } } 

So, simply create new instance of department that is equals to previous

P.S. In my example you can see pure immutable class
EDIT:
Also you can add to Department class copy-contructor

public Department(final Department dep) { ... } 

And to Employer

getDepartment() { return new Department(department); } 
Sign up to request clarification or add additional context in comments.

Comments

1

See Efffective Java:

Item 15: Minimize mutability – 5 rules to follow.

  1. Don’t provide any methods that modify the object’s state
  2. Ensure that the class can’t be extended
  3. Make all fields final
  4. Make all fields private
  5. Ensure exclusive acess to any mutable components

Comments

1

If you don't like removing setters and do initialization in a constructor, you can think about returning immutable (from the point of view of the Emp class) objects, which will web objects' copies, in getters (see https://stackoverflow.com/a/128712/1579085).

final public class Emp { private Integer id; private String name; private Department department; public Emp(Integer id, String name, Department department) { this.id = id; this.name = name; this.department = (Department) department.clone(); } public Department getDepartment() { return (Department) department.clone(); } public Integer getId() { return id; } public String getName() { return name; } } 

And implement the method clone() in Department (which will implement the interface Cloneable) of course.

This approach is suitable, if you need to be able to modify Department, but the objects of the Emp class should be safe from those outer modifications.

4 Comments

The Department could still be changed in your code. You must do a copy/clone in you constructor as well.
@maba Yes, but now the Emp class is safe, and nobody can break its logic by altering department. (I'll correct my answer.)
But if I have a reference depto Department and use that in the constructor then I can update the Department outside the Emp by doing dep.setName("other") and altered the department.
@maba In that case one can should use a copy again - in the constructor. Sorry, forgot to put in in the code.
0

make all attributes final, and remove all setters

1 Comment

That would make all his classes immutable and that was not his intention. Department should be mutable.
0

Implement clone() in Department and make Emp return a clone of department in getDepartment().

If references to Department used in constructing Emp are available after construction, then Emp's constructor should clone given Department.

1 Comment

@Ilya I failed to notice that. This makes my answer unusable.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.