1

I know how to create a immutable class . I created the following .

public class Employee {

    private final int id;
    private final String name;
    private final int salary;

    public Employee(int id, String name, int salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getSalary() {
        return salary;
    }
}

Few articles also suggests that, you declare your class as final, even Effective JAVA book says "mark your methods as final so that they can not be overriddden" . But I am not able to understand why I need to use final on class or on setter methods, when the fields are declared private and also final ?

Or the articles and EFFECTIVE JAVA suggesting an alternative approach !!!

nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
HakunaMatata
  • 814
  • 2
  • 12
  • 22

4 Answers4

2

Making the class immutable and declaring the class as final has different meaning. If you make the class final it means you cannot override any of the functionality (methods) in your methods, which is different from immutablity. Even if you make the field as final, I can still extend your class, and override other methods, say for example in your method getName you are returning employee name, i can override the method and i can make the method returns employee name + employee id.

See an example:

public class SubEmployee extends Employee{

 public String getName(){
     return "Darth Vader";

    }
}

From Java Doc Strategy for Defining Immutable Objects

   Don't allow subclasses to override methods. The simplest way to do 
this is to declare the class as final. A more sophisticated approach is to make the
constructor private and construct instances in factory methods.
Sajan Chandran
  • 11,287
  • 3
  • 29
  • 38
2

As explained by others, its to prevent subclasses from changing the behavior of the parent class. Quoting Effectice Java

Ensure that the class can’t be extended. This prevents careless or malicious subclasses from compromising the immutable behavior of the class by behaving as if the object’s state has changed. Preventing subclassing is generally accomplished by making the class final, but there is an alternative that we’ll discuss later.

Here's an example:

public class Manager extends Employee {

    public Manager(int id, String name, int salary) {
        super(id, name, salary);
    }

    @Override
    public String getName() {
        return "doppelganger";
    }

    public static void main(String[] args) {
        Employee e = new Manager(0, "Eric", 100); //e should be immutable right!
        System.out.println(e.getName()); // prints "doppelganger", I thought employee was immuatble!?
    }
}
rocketboy
  • 9,573
  • 2
  • 34
  • 36
1

If you don't make the class Employee final or all the methods on it final, I can write a class MyEmployee that is mutable. I can then pass it into any method that takes an Employee. If your code relies on the fact that Employee is immutable, it will be very surprised when the ID changes because it's a MyEmployee, not just an Employee.

public class MyEmployee extends Employee {

    private final int id;

    public MyEmployee(int id, String name, int salary) {
        super(id, name, salary);
        this.id = id;
    }

    public int getId() {
        return this.id;
    }

    public void setId(final int id) {
        this.id = id;
    }
Eric Stein
  • 13,209
  • 3
  • 37
  • 52
0

First you need to understand the difference between Final and Private Accesses. When you declare a method to Private it doesn't mean you can't override it. Final keyword on class makes the class inaccessible and on method makes non overridden and on variable to as constants. It is good to use the Final Keyword on setters in order to avoid unintentional changes from any other classes that uses it.

Vigneshwaran
  • 387
  • 1
  • 2
  • 14
  • Can you give an example code in which you can override a private method ? private Members are not inherited and i dont think overriding is possible. Please share the sample code . – HakunaMatata Sep 21 '13 at 11:26
  • Unfortunately, classes declared final are sometimes more difficult to unit test. Not all unit test frameworks can effectively mock a final class, and overriding methods that bugger your test is also next to impossible. final is especially irritating in old code which is not junit tested... – extraneon Sep 21 '13 at 11:27