tags:

views:

92

answers:

6

I saw an example like this in a text and wasn't sure why they did it this way. Let's say you're getting a bunch of Apple objects from a database:

List<Apple> appleList = (List<Apple>) db.getApples()

Why would you cast to a List<Apple> instead of one of the concrete List types (ArrayList, Vector or LinkedList)?

A: 

List is just an interface while ArrayList or LinkedList are implementations. According to Joshua Bloch - Effective Java (Item 18; 19), it is always better to use interfaces here. Thus you can easily switch implementations.

PartlyCloudy
A: 

Most of the time you do not know the exact implementation of List returned by the API to which db belongs. It might either be one of the standard implementations found in Java SE or it might be a custom implementation of the API.

Chandru
+5  A: 

The user of the method db.getApples() shouldn't care if this is an ArrayList, a LinkedList etc. That's an implementation detail.

You should only specify the concrete type of datastructure when constructing the datastructure. After that you should refer to the interface that fits your needs.

This way you can change the concrete type of the datastructure without any trouble.

tangens
A: 

Typically working with the common interface is a better approach. That way the underlying implementation can be left to decide which concrete type would best do the job. It also makes it easier to test using mocks.

rally25rs
+2  A: 

This wiki article on the Liskov Substitution Principle and the Interface Segregation Principle may help you understand why you should program to interfaces.

When working across domains which is common in EE development, you many times don't care what kind of Collection is being used. You more often than not just want to retrieve something from it, iterate over it or remove something. None of these require knowing what kind of implementation you are dealing with. It will also make it easy to switch out the underlying implementation. For instance, let's say that I am working on a project and load a list of items from a database into an ArrayList. Elsewhere in the code I am iterating through this list:

class DBUtil {
    public static ArrayList<Item> getMeAllOfMyItems() {
         return items; // load from database whatever...
    }
}

... meanwhile ...

ArrayList<Item> items = DBUtil.getMeAllOfMyItems();
for (int i = 0; i < items.size(); i++) {
    // do something with item
}

Now let's say that I decide to use a Linked List instead. I would have to change the method that loaded everything from the database, as well as the code I was using to iterate through it:

class DBUtil {
    public static LinkedList<Item> getMeAllOfMyItems() {
         return items; // load from database whatever...
    }
}

... meanwhile ...

LinkedList<Item> items = DBUtil.getMeAllOfMyItems();
for (int i = 0; i < items.size(); i++) {
    // do something with item
}

That was two changes. If I had written it originally as:

class DBUtil {
    public static List<Item> getMeAllOfMyItems() {
         return items; // load from database whatever...
    }
}

... meanwhile ...

List<Item> items = DBUtil.getMeAllOfMyItems();
for (int i = 0; i < items.size(); i++) {
    // do something with item
}

I would only had to change one method, the method where I am returning the items from the database.

Even better would be to change the way I am iterating over the items to use the for each style:

class DBUtil {
    public static List<Item> getMeAllOfMyItems() {
         return items; // load from database whatever...
    }
}

... meanwhile ...

List<Item> items = DBUtil.getMeAllOfMyItems();
for (Item i : items) {
    // do something with item
}

Now if I wanted, I could even change out even more of the implementation and as long as whatever I use implements Iterable, I don't even really care what type of Collection the underlying system is using.

You should strive to make things as generic as possible with the intent that you don't want to have to change 3 or 4 files because of a small change elsewhere.

Casey
A: 

Because in Java you should code to interfaces, not implementations.

Doing so allows the author of the library code to choose the list implementation best suited, and you don't really care. If you do, then copy the list to a list implementation with the properties you need.

For instance, if you need O(1) get times, copy to an ArrayLIst.

Thorbjørn Ravn Andersen