Reputation: 6831
Sorry my title may be misleading.
This is actually from one of my recent JAVA interviews, the interviewer asked me this question: if we have a parameter that is of type HashMap, how can we make sure that in the accepting method, there is no way the user can modify this HashMap (i.e., get() method)
I was saying using final during the interview, which the interviewer didn't appreciate at all, and I've searched online for this topic for a while still have no clue.
Could experts help? Thanks
Upvotes: 0
Views: 1520
Reputation: 136062
There are 2 ways
1) this.map = Collections.unmodifiableMap(map);
2) defensive copying: this.map = new HashMap(map);
Upvotes: 0
Reputation: 8715
Using of final
doesn't prevent from calling methods on the reference. It only makes the reference itself unchangeable. So your answer was wrong.
My suggestion is to use generic (only for such interviews, not in programs!):
Map<String, String> map = new HashMap< String, String >();
map.put("a", "b"); // OK
Map< ? extends String, ? extends String > mapRO = new HashMap< String, String >();
mapRO.put("a", "b"); // Compile error
String value = mapRO.get("a"); // OK
As you can see, hiding generic types with ? extends ...
prevent "writing" methods (like put
) to be called, because they usually need the type to be fully defined. But you can still call clear()
, so it's rather very pool security concept.
Also you can use some wrapper, that would throw an exceptions on all "writing" method calls.
Upvotes: 1
Reputation: 16364
It sounds like you may be coming from a C++ background, where making the parameter const
would indeed prevent the method from modifying the object. In Java, final
only prevents assigning to that variable; you can still call methods that modify the object itself.
So, for example:
void callingMethod() {
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(1, 2);
badMethod(map);
// NullPointerException
System.out.println(map.get(1).intValue());
}
void badMethod(final HashMap<Integer, Integer> map) {
map.clear();
}
There are several ways to prevent this:
Upvotes: 1
Reputation: 4338
How about creating an unmodifiable Collection from that Hashmap like here?
You would then do:
yourMethod(Collections.unmodifiableMap(yourHashmap));
Using final only means that you wont be able to overwrite that reference with another reference in this block, it does not prevent any method calls on that object.
Upvotes: 0
Reputation: 10881
Collections.unmodifiableMap(myMap)
will return the read-only map. You should work on the Map object returned by this.
Upvotes: 0
Reputation: 41230
I think that is immutable or unmodifiable map.
Collections#unmodifiableCollection
It returns an unmodifiable view of the specified map. This method allows modules to provide users with "read-only" access to internal maps. Query operations on the returned map "read through" to the specified map, and attempts to modify the returned map, whether direct or via its collection views, result in an UnsupportedOperationException.
Upvotes: 0