31

I have seen code like this many times:

List<String> list = new ArrayList<String>();

Why do people take the parent of ArrayList (and other classes) instead of the type of the generated object?

Does that take less performance? Or why should someone do this?

codepleb
  • 10,086
  • 14
  • 69
  • 111
  • 9
    What is it with the fixation on "performance"? 90% of the time, that's about the *least important* aspect of writing code! – Joachim Sauer Aug 20 '13 at 07:31
  • 2
    http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface – kiheru Aug 20 '13 at 07:32
  • You can also take a look at this : http://stackoverflow.com/questions/17459553/why-do-some-people-use-the-list-base-class-to-instantiate-a-new-arraylist – Marc Aug 20 '13 at 07:34
  • @JoachimSauer Perhaps the easiest thing would be if we told newbees that this greatly improves performance, like in "Everybody knows that ..." – Ingo Aug 20 '13 at 07:38
  • 1
    If I can't see the reason for a thing in a programm, for what else should I ask? I wouldn't say that taking the parent-reference gives you a more "readable" code. :) But now I have the answer, thanks to all. – codepleb Aug 20 '13 at 07:58
  • 1
    @TrudleR: it communicates intent: `List x = new ArrayList()` means that you don't really need any special features of `ArrayList`, you "promise" to "only" use the features exposed by the `List` interface. Taking it further would be `Collection x = new ArrayList()` or even `Iterable x = new ArrayList()`. – Joachim Sauer Aug 20 '13 at 08:02

7 Answers7

43

When someone writes code like this, he/she is trying to follow a basic OO design principle which says -

Program to an interface, not to a concrete implementation

I have explained this principle in one of my blog posts. Look in the Class Inheritance VS Interface Inheritance section.

To summarize the post, when you use a reference of a parent type to refer to an instance of a sub-type, you get a lot of flexibility. For example, if you ever need to change your sub-type implementation in the future, you will be able to do that easily, without changing much of your code.

Consider the following method -

public void DoSomeStuff(Super s) {
    s.someMethod();
}

and a call to this method -

DoSomeStuff(new Sub());

now, if you ever need to change the logic inside someMethod, you can easily do it by declaring a new subtype of Super, say NewSubType, and changing the logic inside that implementation. In this way, you will never have to touch other existing code which utilizes that method. You will still be able to use your DoSomeStuff method in the following way -

DoSomeStuff(new NewSubType());

Had you declared the parameter of DoSomeStuff to be of Sub, you would then have to change its implementation too -

DoSomeStuff(NewSubType s) {
    s.someMethod();
}

and it may also chain/bubble to several other places.

In terms of your collection example, this lets you change the list implementation that a variable is pointing to without much hassle. You can easily use a LinkedList in place of an ArrayList.

MD Sayem Ahmed
  • 28,628
  • 27
  • 111
  • 178
  • 3
    "Program to an interface, not to a concrete implementation" is a good advice. However, it's not really an argument to do `List list = new ArrayList();` because a) this code is still tied to ArrayList due to the constructor and b) it's more about API design and not the private implementation. It's one of the java things you learn from the beginning which is not really justified. Often the implementation offers some niceties which you will never see if you insist on using the interface. Answer is still good, of course. (+1) – atamanroman Aug 20 '13 at 07:41
  • 1
    BUT, his argument still stands. You can swap out functionality by changing the argument. This supports several nice code features, such as dependency injection, loose coupling and substitutability. – christopher Aug 20 '13 at 07:44
  • @atamanroman: A consequence of that principle encourages you to refer to the concrete instances in terms of their _interfaces_. This is why I think it's relevant here. – MD Sayem Ahmed Aug 20 '13 at 07:44
  • @Chris: Totally agree with you. – MD Sayem Ahmed Aug 20 '13 at 07:45
  • In the original question, there is no argument. Theres only `List l = new ArrayList();` If the implementation changes, that line changes. Would'nt be any different if it was `ArrayList l = new ArrayList();`. The whole situation changed if the list was an external dependency (somehow injected). In this case programming to the interface would make a difference and is highly recommended. – atamanroman Aug 20 '13 at 07:49
  • @atamanroman: As I said, the basic idea was to manipulate an instance with a reference of super type. If only the methods defined in the `List` is sufficient to manipulate that instance, then it will be better to do so. Who knows may be in the future he may decide to make it a property rather than a local variable, and he may also decide to inject a different implementation than an `ArrayList`. Certainly referring by the `List` will give him an advantage here. It's the _practice_ which is of importance here. – MD Sayem Ahmed Aug 20 '13 at 08:05
13

When you write:

List<String> list = new ArrayList<String>();

Then you are sure you'll use only the functionality of the interface List.
(ArrayList implements List, so List is more flexibl). Using this, allows you to change the ArrayList to other types in the future (like LinkedList..).

Maroun
  • 94,125
  • 30
  • 188
  • 241
12

It means you can swap out the type of list at any point with anything that implements the List interface, as opposed to creating a rigid model that can only use ArrayList. For example:

private List<String> list;

public SomeConstructor()
{
     // At this point, you can make it any type of object you want.
     list = new ArrayList<String>();
     list = new LinkedList<String>();
     list = new AttributeList<String>();
}

This will abstract your code that uses the list object, away from the details like what exact object type list is. All it needs to know is that it has the add method etc. This is called Loose Coupling.

christopher
  • 26,815
  • 5
  • 55
  • 89
5

To sort things out:

For more flexibility you initiate interface List:

So if you don't need all ArrayList use List only.

You can write something like: List<String> = Arrays.asList("aa", "bb","cc").

For sure, less functionality can help to performance. As you know If you want to use multithreaded application, use Vector instead but it will down your performance.

enter image description here

Took from here

Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
  • 2
    http://www.wilsonmar.com/1arrays.htm – Maxim Shoustin Aug 20 '13 at 07:42
  • @Maxim Shoustin: Good picture! Does this mean, that I should take "AbstractMap" as reference for all the map-collection-objects? – codepleb Aug 20 '13 at 08:01
  • 1
    @TrudleR: no, `AbstractMap` is an implementation detail you should never really care about: You *either* reference the map using the `Map` interface *or* a more specific interface (such as `NavigableMap`). In rare cases you might need the specific implementation type, but `AbstractMap` itself is rarely referenced by anyone except when they extend it. – Joachim Sauer Aug 20 '13 at 08:04
4

Because a method doesn't have to know what list-implementation you use.

A Method just needs to know that is is a list.

The Method can still be used.

Always program to an interface, not to a concrete implementation. (In this case List)

Philipp Sander
  • 10,139
  • 6
  • 45
  • 78
3

Generally it is preferred to work with the Interface class (List in this case) so that any List implementation could later be substituted with minimal fuss if requirements change.

Although ArrayList possibly supports some methods that are not on the List interface, this declaration makes it clear that those extra methods are not relevant in that case.

Adrian Pronk
  • 13,486
  • 7
  • 36
  • 60
2
List<String> list = new ArrayList<String>();

In collection framework List is an interface while ArrayList is implementation. Main reason you'd do this is to decouple your code from a specific implementation of the interface also this will be helpful in case if you wish to move to some other implementation of List in the future.

Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115