In "O'Reilly - Programming Android" they recommend avoiding this code:
ArrayList<String> a = new ArrayList<String>();
but to replace it with this:
List<String> a = new ArrayList<String>();
They argue it's easier to maintain code if later the type of a
should be changed to say a linked list. If so, why not make it of type Collection
, or even Object
?
I feel that as the instantiation must be changed to change its type, surely it's better to keep it type restricted as much as possible and change the extra line if needed.
Are they correct?
In my personal opinion you should use the interface as high (in hierarchy) as possible and have the operations you will need.
In some cases you need just to store objects, iterate, and get them using index. List
interface is providing that. Object does not provide you with these methods.
Using Object
- you will make your code less readable and there could be cast exceptions.
They are correct.
You should use the most restricted type possible. If Collection
is the right abstraction for you, instead of List
or Set
, then use it instead. If you need to use something as an Object
, then by all means, refer to it as an Object
. But if you need to be more specific, then just be more specific. The trick is to avoid casting when it's not necessary.
As you have mentioned, the idea is to hide implementation details when you don't want them to be exposed. This makes your software easier to use and more maintainable. For example, if you have a method that returns a List
, then someone using your software doesn't have to worry about what implementation of List
it really is. This helps make your software easier to understand. Now, because of this, you are free to change which type of List
you return with out (for the most part) hurting programs that call that method.
They are wrong.
If a type appears in a public API, it should be as general as semantics allows.
List<String> getStringList();
As an implementation detail, the type should be as specific as the programmer knows.
ArrayList<String> stringList = new ArrayList<>();
Because you can't do anything useful with an Object
reference.