Search code examples
javacollectionsguavaimmutability

After assigning a Map to ImmutableMap, how to stop or restrict reassign another map


I declared a ImmutableMap like

public static ImmutableMap<String, String> mapImmutable;

Assigned a map to this variable

mapImmutable= ImmutableMap.copyOf(map2);

Now if I assign other map to this 'mapImmutable' variable. It will not throw any exception and will update values.

mapImmutable=ImmutableMap.copyOf(map3);

public class UnmodifiedMap {

public static ImmutableMap<String, String> mapImmutable;

public static void main(String[] args) {
    Map<String,String> map2=new HashMap<String,String>();

    map2.put("name", "mark");
    mapImmutable= ImmutableMap.copyOf(map2);
    System.out.println(mapImmutable);

    Map<String,String> map3=new HashMap<String,String>();

    map3.put("Country", "USA");
    map3.put("name", "Joy");

            mapImmutable=ImmutableMap.copyOf(map3);\\It should throw an exception while reassign.
    System.out.println(mapImmutable);}}

Console Result -: {name=mark} {Country=USA}

It should throw an exception while reassign.


Solution

  • Here:

    mapImmutable = ImmutableMap.copyOf(map3);
    

    You are not actually changing the contents of the map that the field mapImmutable refers to. You are making mapImmutable refer to an entirely different map!

    ImmutableMap being immutable doesn't mean that you can reset a variable of its type. It only means that instances of it will not change. e.g. you can't add new items to the map or remove items from it. In the above line, you are not modifying any instances of ImmutableMap, you are creating a new instance of ImmutableMap by calling copyOf, and assigning it to mapImmutable. The map that mapImmutable was referring to is not changed, but is simply lost.

    If you want to disallow resetting a field, declare it as final, and set it in the static constructor:

    public final static ImmutableMap<String, String> mapImmutable;
    
    static {
        Map<String,String> map2=new HashMap<String,String>();
    
        map2.put("name", "mark");
        mapImmutable= ImmutableMap.copyOf(map2);
        System.out.println(mapImmutable);
    
        Map<String,String> map3=new HashMap<String,String>();
    
        map3.put("Country", "USA");
        map3.put("name", "Joy");
    
                mapImmutable=ImmutableMap.copyOf(map3); // now we have an error!
        System.out.println(mapImmutable);}
    }
    

    Also note that final only prevents resetting the field/variable, but does not prevent the object from being modified. If you have a final HashMap, you can still add KVPs to it.