When you do:
HashMap telephoneNumbers = new HashMap();
ArrayList<Object> list = new ArrayList<Object>();
You are tied to a specific implementation, i.e. ArrayList. If you were to pass the list object further to other methods, then you are not much flexible. If you program to interface, say Collection instead (which is extended by List), you can change the implementation later. For example, if the objects in the list should be unique, then you could easily change it to be a Set instead (because sets only contain unique objects):
HashMap telephoneNumbers = new HashMap();
Collection<Object> list = new HashSet<Object>(); 
The principle of programming to an interface is really about dependency relationships. It is closely related to the concept of OO concept of Encapsulation:
- A language mechanism for restricting access to some of the object's components.
- A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.
The most important aspect is that by following programming-to-an-interface paradigm we are asking ourself "what" the class can do but not "how" it will do it, which is concerned with the actual implementation.
Using ArrayList you are tightly coupling your code to the ArrayList class. If you only use the generic methods that are in the Collection interface (add(), remove() etc) then it definitely makes sense to declare your list as an interface of type Collection.