Seasoned Java programmers are programming to interfaces. What does it means?
Let’s consider a simple example. Let’s say I’ve declared a variable customers of type ArrayList
:
ArrayList<Customer> customers = new ArrayList<>(3);
While this code is correct, there a better way of declaring the variable customers
:
List<Customer> customers = new ArrayList(3);
You can read the first example as follows: “I want to declare a variable customers
that will have all access to all API offered by the class ArrayList
“. The second version means the following: “I want to declare a variable customers
that has a behavior declared in the List
interface”. The first example declares a variable of a specific implementation of the List
interface – ArrayList
. Now rake a look at this code example:
ArrayList<Customer> customers = new ArrayList<>(3);
// The code to populate customers with instances of
// Customer is omitted for brevity
int totalElem = customers.size();
// Iterate through the list customers and do something with each
// element of this collection
for (int i=0; i<totalElem;i++){
Customer currentCustomer= customers.get(i);
System.out.println(currentCustomer);
}
}
ArrayList
implements several interfaces besides List
, which means that it has more methods that the List
defines. But if you read the documentation on the List
interface, you’ll see that among others it includes the methods as add()
, get()
, and size()
, which are the only ones used with our collection customers
. If this is all we need, declaring a variable customers
of type List
gives us more flexibility. If later we decide to switch to a different implementation of the List (e.g. LinkedList
instead of ArrayList
) we won’t need to change the type of the variable customers
.
You may say that changing a variable declaration from ArrayList
to LinkedList
it’s not a big deal – it’s still the same line of code. But it may be a bigger deal if, say you program needs to pass the object referred by customers
to another object’s method that also was declared with the argument of type ArrayList
:
processCustomers (ArrayList<Customer> customers){
...
}
Now we need to change both the variable and the method argument declarations . In large projects such a refactoring may become a time consuming process.
If you just need a behavior defined in a particular interface (e.g. List
), declare the variable of this interface type rather than of a concrete implementation (e.g. ArrayList
) of this interface.
P.S. Here’s the Java 8 way of writing the above loop, which is not relevant for the blog subject:
customers.forEach( customer -> System.out.println(customer));