By Yakov Fain

Seasoned Java programmers are programming to interfaces. What does that mean?

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’s a better way of declaring the variable customers:

List 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 variablecustomers 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 take 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 Listdefines.  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 is 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 bycustomers 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 like refactoring this may become a time consuming process.

If you just need a behaviour 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));

or even shorter (Thanks Henning Hoefer)

customers.forEach(System.out::println);

Programming to Interfaces in Java

| Java Language| 1,773 views | 3 Comments
Profile photo of voxxed
About The Author
-

3 Comments

  • Henning Hoefer
    Reply Report user

    “List customers” ist NOT a better way than “ArrayList”, because it’s a raw type. While I agree that coding to interfaces is the preferred way, you should not throw generics under the bus while attempting to do so.

    The correct version of the second code example should therefore read “List customers = new ArrayList(3);”

    Also, the Java 8 example in the P.S. can be shortened to “customers.forEach(System.out::println);”

  • Peter Boszormenyi
    Reply

    Actually, there is a good reason to declare the variable as an ArrayList. The loop always access the item by the index. I bet the author of the code assumes that the index based access in the ArrayList is constant. If you change the code to use LinkedList, the performance will degrade, because for each indexed access, the LinkedList iterates through for every item. In short: the code depends on the implementation, you cannot just swap to another one.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>