简体   繁体   中英

Why to make class final to create immutable object

I am trying to follow code below. I am not exactly sure what happens at line #5 and why does statement at line #7 set the value of tmp in immutable class to 10?

public class HelloWorld{ 
         public static void main(String []args){
            child c = new child(4);
            System.out.println(c.getTemp()); // line #4 prints 4
            immutable i = (immutable) c; //line #5
            System.out.println(i.getTemp()); // line #6 prints 4
            c.setTemp(10); //line #7
            System.out.println(i.getTemp()); // line 8 prints 10
         }
    }

    class immutable{
        private int tmp;       
        immutable(){              
        }
        immutable(int val){
            tmp = val;}
        public int getTemp(){
            return tmp; }        
     }

    class child extends immutable{
        private int tmp1;         
        child(){              
        }
        child(int y){
            super(y);
            tmp1= y;
        }
         public int getTemp(){
            return tmp1;}

         public void setTemp(int y){                 
            tmp1 = y;}
    }

Ignoring the style and convention errors here and just focusing on your problem.

If your class is not final, there is a possibility of a subclass overriding the Immutability. Here is an example.

This is the Immutable class

public class Immutable {
 private final int value;

 public Immutable(int value) {
     this.value = value;
 }

 public int getValue() {
     return value;
 }

}

The class "Immutable" is not final, so I can extend it.

public class Mutable extends Immutable {
 private int newValue;

 public Mutable(int value) {
     super(value);

     newValue = value;
 }

 public int getValue() {
     return newValue;
 }
 public void setValue(int newValue) {
     this.newValue = newValue;
 }


}

Now to the main class,

public static void main(String[] arg){
    Immutable immutable = createImmutableObject(10)
    System.out.println(immutable.getValue()); //This prints 10
    mutable.setValue(100);
    System.out.println(immObj.getValue()); //This prints 100
}

private Immutable createImmutableObject(int val){
    return new Mutable(val);
}

In the method createImmutableObject, I am returning a reference of type Immutable. Hence, developers using the API would assume that the returning object is Immutable. However, the object is of type Mutable (whose state can be changed) and just the reference is of the parent class. I can change the state of the returned object which would break the "immutability"

Class is made final for making it immutable so that it cannot be extended and its method overridden. Also, that is not the only thing that you do to make the class immutable.

All Java functions are virtual - meaning, no matter what the declared type of a variable, you always get the underlying class's implementation of the method.

That means that any reference you have to c , no matter the declared type, will use c 's implementation of a method.

So, line 5 effectively does nothing (it would throw an exception if c didn't extend immutable ).

When you call getTemp on i , you're invoking c class's ( child 's) implementation of getTemp , even though the type of i is immutable .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM