In general, it's preferred to code to interfaces (your first example, declare the variable using the interface, not the class). That way, if you need to change to a different implementation, it's trivial to do that — you just change the new
to something else, and nothing else needs to change, because you code to the interface.
The reason it works is that ArrayList<BigDecimal>
implements List<BigDecimal>
, and so is assignment-compatible with it. That means that a variable declared as List<BigDecimal>
is allowed to haev a reference of type ArrayList<BigDecimal>
assigned to it. It's a design feature of the language. This is fundamental to how interfaces, and indeed OOP in general, works in Java.