Reputation: 11559
I know its commonly accepted to cast all List
implementations down to List
. Whether it is a variable, method return, or a method parameter using an ArrayList
, CopyOnWriteArrayList
, etc.
List<Market> mkts = new ArrayList<>();
When I'm using a Guava ImmutableList
, I have the sense it can arguably be an exception to this rule (especially if I'm building in-house, complicated business applications and not a public API). Because if I cast it down to list, the deprecated mutator methods will no longer be flagged as deprecated. Also, it no longer is identified as an immutable object which is a very important part of its functionality and identity.
List<Market> mkts = ImmutableList.of(mkt1,mkt2,mkt3);
Therefore it makes sense to pass it around as an ImmutableList
right? I could even argue that its a good policy for an internal API to only accept ImmutableList
, so mutability and multithreading on the client side won't wreck anything inside the library.
ImmutableList<Market> mkts = ImmutableList.of(mkt1,mkt2,mkt3);
I know there is a risk of ImmutableList
itself becoming deprecated, and the day Oracle decides to create its own ImmutableList
will require a lot of refactoring. But is it arguable the pros of maintaining an ImmutableList
cast can outweigh the cons?
Upvotes: 7
Views: 13020
Reputation: 11900
Keep using List
rather than ImmutableList
! There is no problem with that and no reason for your API to start using ImmutableLists
explicitly for several reasons:
ImmutableList
is Guava only and unlikely to become standard Java at any point. Don't tie your code and coding habits to a third party library (even if it is a cool one like Guava).UserThatCanBeSubclassed
. List
that was passed into it and ALWAYS make a defensive copy when passing a List
to a client. Introducing ImmutableList
here would lure you and the clients of your API into a false sense of security and entice them to violate that rule.Upvotes: 2
Reputation: 718926
I agree with your rationale. If you are using the Guava collection library and your lists are immutable then passing them as ImmutableList
is a good idea.
However:
I know there is a risk of ImmutableList itself becoming deprecated, and the day Oracle decides to create its own ImmutableList will require a lot of refactoring.
The first scenario seems unlikely, but it is a risk you take whenever you use any 3rd-party library. But the flipside is that you could chose to not upgrade your application's Guava version if they (Google) gratuitously deprecated a class or method that you relied on.
UPDATE
Louis Wasserman (who works for Google) said in a comment:
"Guava provides pretty strong compatibility guarantees for non-@Beta APIs."
So we can discount the possibility of gratuitous API changes.
The second scenario is even more unlikely (IMO). And you can be sure that if Oracle did add an immutable list class or interface, that would not require you to refactor. Oracle tries really hard to avoid breaking existing code when they enhance the standard APIs.
But having said that, it is really up to you to weigh up the pros and cons ... and how you would deal with the cons should the eventuate.
Upvotes: 8
Reputation: 46432
Unfortunately, there's no corresponding interface in Java (and most probably never will be). So my take is to pretend that ImmutableList
is an interface. :D But seriously, it add important information which shouldn't get lost.
The ancient rule it all comes from actually states something like "program against interfaces". IIRC at the time the rules was created, there was no Java around and "interface" means programming interface, i.e., the contract, not java interface
.
A method like
void strange(ArrayList list) {...}
is obviously strange, as there's no reason not to use List
. A signature containing ImmutableList
has a good reason.
I know there is a risk of ImmutableList itself becoming deprecated, and the day Oracle decides to create its own ImmutableList will require a lot of refactoring.
You mean Java 18? Let's see, but Guava's ImmutableList
is pretty good and there's not much point in designing such a class differently. So you can hope that most changes will be in your imports only. And by 2050 there'll be worse problems than this.
Upvotes: 2
Reputation: 10925
I would rather stay with just List
for method parameter. There is no much benefit to enforce the caller to pass ImmutableList
- it's your own method and you won't mutate list anyway, but you'd have method more reusable and generic.
As a return type, I would go with ImmutableList
to let method users know that this list cannot be modified.
Upvotes: 0
Reputation: 6149
I understand your dilemma.
Personnaly, I would advise to keep using List
as the reference type (to be future-proof and benefit from polymorphism), and use an @Immutable
annotation to convey the information that it is immutable.
Annotations are more visible than plain javadoc comments, and you can even use the one from JSR-305 (ex-JCIP). Some static analysis tools can even detect it and verify that your object is not mutated.
Upvotes: 0