I'm writing a library method that will be used in several places. One of the method's parameters is a collection of objects, and the method does not mutate this collection. Should the method signature specify a mutable or immutable collection?
public static void foo(List<Bar> list) {
// ...
}
Pros: Clients can pass in whichever of List<Bar>
or ImmutableList<Bar>
is more convenient for them.
Cons: It is not immediately obvious that the list
parameter will not be mutated. Clients must read documentation and/or code to realize this. Clients may make unnecessary defensive copies anyway.
public static void foo(ImmutableList<Bar> list) {
// ...
}
Pros: Clients have a guarantee that the list
parameter will not be mutated.
Cons: If the client has a List<Bar>
, they must first convert it to an ImmutableList<Bar>
before calling foo
. This conversion wastes a small amount of time, and it is forced on clients whether they like it or not.
Note: For the purposes of this question, let's assume that all clients will have Guava's ImmutableList
available, for example because the library and client code all belong to the same codebase that already uses ImmutableList
elsewhere.
As the creator of the foo()
API, this is none of your business. You take a list and you don't modify it, and that's it. Your code, in fact, doesn't care about the list's mutability (it's a concern of the caller): so document your intent and stop there.
If the caller needs to guarantee that the list will not be tampered with, they would create defensive copies not because you don't promise to leave the list unchanged, but because they need that guarantee.
It's following the same logic that we perform null checks in method implementations: it's needed because our code needs to be robust, not because the caller can send a null argument.
In other words, document your method as you intend to implement them, and leave it up to the caller to pick the list implementation. The reasons of their choices will vary (ie, it won't always be only whether you'll modify the list).
Leave it at List
.
Here are some situations to consider:
Collections.synchronizedCollection
does not modify the client's collection.
Collections.frequency
does not modify the client's collection.
These reasons aren't why the JDK doesn't expose an immutable interface. Those reasons are explained in the documentation . In the case of synchronizedCollection
, although it doesn't modify the client's collection, it does return a modifiable view of the client's collection; some would say this function wouldn't apply here. However, frequency
and other query functions still hold strong.
You shouldn't restrict clients for the purpose of trying to advertise safety and nothing more. There should be more justification, otherwise your attempt to help could be a burden on the client. In some cases, your goal can be contradictive to what the function/system is achieving, such as with the synchronizedCollection
example.
It's good to encourage safety, but having your system force it onto your clients without the system benefiting from it would be abuse of power; that's not your decision to make.
ernest_k makes a really good point in his answer , suggesting that you need to analyze what your system should be in charge of, and what the client should be in charge of. In this case, it should be up to the client whether the collection is immutable or not, since your system doesn't care about mutability. As he put it, " it's none of your business ", which I agree with.
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.