I wouldn't call this a "runtime" polymorphism. This is because you do an upcast and it is always typesafe. Everything can be resolved at compile-time.
On the other hand a downcast, like for example from List to ArrayList, must be checked at runtime. You also must explicitly mark such a downcast in the code.
> This makes it more flexable and easily reused !!!
> How ...?
How? The best example is the Comparable interface. Objects of any class can be sorted using the standard Java sorting methods as long as they implement the Comparable interface.
How was this flexibility accomplished? Because the sorting methods were not written especially for a certain specific class. No, they were written only assuming the Comparable interface. This is how they became so general and flexible and reusable.
Another reason is that some classes implement methods which are not part of the interface. In reality most of these method can be replaced with methods from the interface but can make the code fixed to a specific container type.
Swing is a good example of this. Instead of taking Lists or Collections it takes Vectors or Vector of Vectors.
If you have your data in an ArrayList, you have to create a Vector with a copy of all the elements just so you can call one of the Swing methods. Why not use Vector all the time, because the methods are slower, and some are not as safe e.g. Enumerations is not fail fast.
With the specific List list = new ArrayList();
there's probably not much practical advantage. True, you could later change that ArrayList to a LinkedList and you'd only have to change that one instantiation, as opposed to anything else where you're using that and have declared ArrayList instead of List. But that doesn't often happen, in my experience.
But if you're doing, say, something with JDBC... Connection con = DriverManager.getConnection(url);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
Connection, Statement, and ResultSet are all interfaces. You don't know or care what the implementing class is. Only that it meets the contract specified by those interfaces.
In general, declaring things to be the "most abstract" or "closest to Object" that still gives you everything that you need gives flexibility. It means that any class implements the declared interface or is a subclass of the declared class will work there, and you don't have to know what that class is, or change other code that uses that variable if you change the class.