82

What is the difference between these two declarations?

Declaration 1:

ArrayList<String> arrayList = new ArrayList<String>();

Declaration 2:

List<String> arrayList = new ArrayList<String>();
Radiodef
  • 37,180
  • 14
  • 90
  • 125
Adil
  • 4,503
  • 10
  • 46
  • 63
  • 1
    possible duplicate of [Why the coding should be "to the interface" especially for primitive datatypes?](http://stackoverflow.com/questions/9392813/why-the-coding-should-be-to-the-interface-especially-for-primitive-datatypes) – assylias Sep 07 '12 at 15:32
  • This one too: http://stackoverflow.com/questions/1413543/what-does-it-mean-to-program-to-a-interface – assylias Sep 07 '12 at 15:33
  • Have a look at http://stackoverflow.com/questions/3383726/java-declaring-from-interface-type-instead-of-class – Maciej Sep 07 '12 at 15:49
  • 1
    Possible duplicate of [Type List vs type ArrayList in Java](http://stackoverflow.com/questions/2279030/type-list-vs-type-arraylist-in-java) – Tom Mar 29 '16 at 12:22

10 Answers10

71
List<String> arrayList = new ArrayList<String>();

Is generic where you want to hide implementation details while returning it to client, at later point of time you may change implementation from ArrayList to LinkedList transparently.

This mechanism is useful in cases where you design libraries etc., which may change their implementation details at some point of time with minimal changes on client side.

ArrayList<String> arrayList = new ArrayList<String>();

This mandates you always need to return ArrayList. At some point of time if you would like to change implementation details to LinkedList, there should be changes on client side also to use LinkedList instead of ArrayList.

kosa
  • 65,990
  • 13
  • 130
  • 167
  • 3
    And don't forget the Collections class works entirely with the List interface, so things like Collections.emptyList, Collections.synchronizedList Collections.unmodifiableList all return List. So if an API expects ArrayList, you're out of luck if you want to wrap an existing list with these methods. – Matt Sep 07 '12 at 17:11
  • For _input_ parameters, sure, I agree, but this is about the opposite; namely, object _instantiation_. In this case, the _only_ thing it does is remove all ArrayList-specific functions that _should_ be available to you. – Nyerguds Jan 06 '17 at 14:40
  • "This mandates you always need to return ArrayList" is completely wrong, by the way. You can perfectly make your return type `List` anyway, no matter what you use internally. – Nyerguds Jan 06 '17 at 14:41
  • @Matt: you still can use Collections or CollectionUtils for array list – uncle bob May 21 '21 at 09:27
17

List is an interface and ArrayList is an implementation of the List interface. The ArrayList class has only a few methods(i.e clone(), trimToSize(), removeRange() and ensureCapacity()) in addition to the methods available in the List interface. There is not much difference in this.

   1. List<String> l = new ArrayList<>();
   2. ArrayList<String> l = new ArrayList<>();

If you use the first, you will be able to call the methods available in the List interface and you cannot make calls to the new methods available in the ArrayList class. Where as, you are free to use all the methods available in the ArrayList if you use the second one.

I would say the first approach is a better one because, when you are developing java applications, when you are supposed to pass the collection framework objects as arguments to the methods, then it is better to go with first approach.

List<String> l = new ArrayList<>();
doSomething(l);

In future due to performance constraints, if you are changing the implementation to use LinkedList or someother classes which implements List interface, instead of ArrayList, you need to change at one point only(the instantiation part).

List<String> l = new LinkedList<>();

Else you will be supposed to change at all the places, wherever, you have used the specific class implementation as method arguments.

Dhaval Patel
  • 10,119
  • 5
  • 43
  • 46
  • Can you elaborate why using the first option makes us to change more than the declaration line? – TheLogicGuy Oct 31 '16 at 19:25
  • Why do people keep propagating the dumb "you can change it later" argument? If you design it well, that should _always_ be the exception instead of the rule. The only real effect here is that you lose all functions available on your `ArrayList` except for the `List` basics. – Nyerguds Jan 06 '17 at 14:44
9

The difference is that variant 1 forces you to use an ArrayList while variant 2 only guarantees you have anything that implements List<String>.

Later on you could change that to List<String> arrayList = new LinkedList<String>(); without much hassle. Variant 1 might require you to change not only that line but other parts as well if they rely on working with an ArrayList<String>.

Thus I'd use List<String> in almost any case, except when I'd need to call the additional methods that ArrayList provides (which was never the case so far): ensureCapacity(int) and trimToSize().

Thomas
  • 87,414
  • 12
  • 119
  • 157
4

The first declaration has to be an ArrayList, the second can be easily changed to another List type. As such, the second is preferred as it make it clear you don't require a specific implementation. (Sometimes you really do need one implementation, but that is rare)

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Well, the second isn't preferred when speed is the focus :-p `invokeinterface` can be a bit slower than `invokevirtual`, which may be significant in some contexts. – obataku Sep 07 '12 at 15:42
3

It is easy to change the implementation to List to Set:

Collection<String> stringList = new ArrayList<String>();
//Client side
stringList = new LinkedList<String>();

stringList = new HashSet<String>();
//stringList = new HashSet<>(); java 1.7 and 1.8
Sufian
  • 6,405
  • 16
  • 66
  • 120
sambhu
  • 111
  • 1
  • 5
3

Basically it allows Java to store several types of objects in one structure implementation, by generic type declaration (like class MyStructure<T extends TT>), which is one of Javas main features.

Object-oriented approaches are based in modularity and reusability by separation of concerns - the ability to use a structure with any kind of types of object (as long as it obeys a few rules).

You could just instantiate things as followed:

ArrayList list = new ArrayList();

instead of

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

By declaring and using generic types you are informing a structure of the kind of objects it will manage and the compiler will be able to inform you if you're inserting an illegal type into that structure, for instance. Let's say:

// this works
List list1 = new ArrayList();
list1.add(1);
list1.add("one");

// does not work
List<String> list2 = new ArrayList<>();
list2.add(1); // compiler error here
list2.add("one");

If you want to see some examples check the documentation documentation:

/**
 * Generic version of the Box class.
 * @param <T> the type of the value being boxed
 */
public class Box<T> {
    // T stands for "Type"
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

Then you could instantiate things like:

class Paper  { ... }
class Tissue { ... }

// ...
Box<Paper> boxOfPaper = new Box<>();
boxOfPaper.set(new Paper(...));

Box<Tissue> boxOfTissues = new Box<>();
boxOfTissues.set(new Tissue(...));

The main thing to draw from this is you're specifying which type of object you want to box.

As for using Object l = new ArrayList<>();, you're not accessing the List or ArrayList implementation so you won't be able to do much with the collection.

nuno
  • 1,771
  • 1
  • 19
  • 48
1

List is interface and ArrayList is implemented concrete class. It is always recommended to use.

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

Because here list reference is flexible. It can also hold LinkedList or Vector object.

Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
1

There are a few situations where you might prefer the first one to (slightly) improve performance, for example on some JVMs without a JIT compiler.

Out of that kind of very specific context, you should use the first one.

assylias
  • 321,522
  • 82
  • 660
  • 783
1

Possibly you can refer to this link http://docs.oracle.com/javase/6/docs/api/java/util/List.html

List is an interface.ArrayList,LinkedList etc are classes which implement list.Whenyou are using List Interface,you have to itearte elements using ListIterator and can move forward and backward,in the List where as in ArrayList Iterate using Iterator and its elements can be accessed unidirectional way.

cxyz
  • 823
  • 8
  • 19
  • 37
0

Whenever you have seen coding from open source community like Guava and from Google Developer (Android Library) they used this approach

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

because it's hide the implementation detail from user. You precisely

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

it's generic approach and this specialized approach

ArrayList<String> strings = new ArrayList<String>();

For Reference: Effective Java 2nd Edition: Item 52: Refer to objects by their interfaces

Yasir Shabbir Choudhary
  • 2,458
  • 2
  • 27
  • 31