Occasionally, yes. If you actually need a method that's declared in ArrayList<T>
but not in List<T>
then sure, go for it.
However, the reverse is more flexible - if you don't need any methods declared in ArrayList<T>
, then your code can express that by declaring the variable to be of type List<T>
instead. That says, "I just need a list. I happen to be picking ArrayList<T>
, but just because its behaviour suits me... not because I need any extra features it exposes."
That's useful to know if later someone wonders whether they could substitute a different implementation, for example. It also limits how much a reader has to think about... the more general the type of the variable, the less one can do with it - so the less one needs to think about it.
For example, if I see a variable of type Iterable<T>
I know there's precious little that's likely to be done with it later: basically, it's going to be used to iterate, and that's all. I don't need to worry about whether any later code is going to try to add a value to the collection, or access it by index etc.
This is relatively unimportant for local variables, but much more so for instance variables and particularly parameters: the less concrete you make your parameters, the more flexibility the caller has about which arguments they'll pass.