Collections.unmodifiableList(...)
returns a new instance of a static inner class UnmodifiableList
. Other unmodifiable collections classes are constructed same way.
Were these classes public, one had two advantages:
UnmodifiableList
), so an API user wouldn't come to the idea of modifying that collection;List
is instanceof UnmodifiableList
.So, were there any advantages not to make those classes public?
EDIT: No definitely convincing arguments were presented, so I choose the most upvoted answer.
The unmodifiableList() method of java. util. Collections class is used to return an unmodifiable view of the specified list. This method allows modules to provide users with “read-only” access to internal lists.
I suggest using "addAll(Collections. emptyList());" instead of add(null) to test for immutable. This will raise the UnsupportedOperationException if immutable and does not modify the list if mutable.
The solution to this problem is quite simple and is highlighted in the following code. final List<String> modifiable = new ArrayList<>(); modifiable. add("Java"); modifiable. add("is"); // Here we are creating a new array list final List<String> unmodifiable = Collections.
Personally I completely agree with you. At the core of the problem is that fact that Java's generics are not covariant, which, in turn, is because Java's collections are mutable.
It is not possible for Java's type system to codify a type that seems to have mutators is actually immutable. Imagine if we were to start designing some solution:
interface Immutable //marker for immutability interface ImmutableMap<K, V> extends Map<K, V>, Immutable
But then ImmutableMap
is a subclass of Map
, and hence Map
is assignable from ImmutableMap
so any method which returns such an immutable Map:
public ImmutableMap<K, V> foo();
can be assigned to a Map and can therefore be mutated at compile time:
Map<K, V> m = foo(); m.put(k, v); //oh dear
So, you can see that the addition of this type has not actually prevented us from doing anything bad. I think for this reason a judgement was made that it did not have enough to offer.
A language like scala has declaration-site variance annotations. That is, you could specify a type as being covariant (and hence immutable) as Scala's Map is (actually it's covariant in its V
parameter). Hence your API can declare whether its return type is mutable or immutable.
As another aside, Scala lets you declare intersection types so that you don't even need to create the ImmutableXYZ
interface as a separate entity, you could specify a method to return:
def foo : XYZ with Immutable
But then scala has a proper type system, whereas Java does not
I think both advantages are there but are not that useful. The main problems remain the same: UnmodifiableList still is a List and thus all the setters are available and the underlying collections still are modifiable. Making the class UnmodifiableList public would add to the illusion of being unmodifiable.
The nicer way would be for the compiler to help, but for that the collection class hierarchies would have to changed a lot. E.g., the collection API of Scala is way more advanced in that respect.
A disadvantage would be the introduction of at least three additional classes / interfaces into the API. Because of them not being that useful, I think leaving them out of the API is a good choice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With