1

Below is the diagram, where, if we just consider the implementations of List,

enter image description here

  1. AbstractList maintains the core behavior of list. To introduce the new implementation class MyList(say) one can inherit AbstractList and override(if necessary) required methods. By extending AbstractList. Additionally, class MyList is obeying the contract to behave like a list.

    class MyList extends AbstractList{..}
    
  2. Users can use collection hierarchy, as,

    AbstractList l = new ArrayList<String>();
    l.add("one"); //execute ArrayList's add method
    
  3. A class can also maintain composition relation with any list implementation(at runtime), by having

    AbstractList l;
    

    as member, that gets populated at runtime, with any list implementation.

So,

I would like to understand the clear reason, Why additionally interface List<E> is introduced?

note1: Intention is to understand, how to use interface. This not a duplicate question, because both abstract class and interface are used.I did not use the word 'instead of' or 'rather'

note2: Let us not get into java-8 default methods, as above collection hierarchy was designed with whatever was provided till java-7

6
  • 4
    "interfaces are essential for single-inheritance languages like Java and C# because that's the only way in which you can aggregate different behaviors into a single class..." class Book extends Content implements List<Page> - one couldn't do this with AbstractList, because there would be no way for Book to extend both Content and AbstractList simultaneously
    – gnat
    Jul 5, 2015 at 2:33
  • @gnat wording is 'instead of' in your referred query. Here both are used, abstract class and interface Jul 5, 2015 at 2:35
  • 1
    The motivation is explained in the AbstractList documentation. Quote: "This class provides a skeletal implementation of the List interface to minimize the effort required to implement this interface backed by a "random access" data store (such as an array)."
    – rwong
    Jul 5, 2015 at 2:35
  • 1
    @overexchange No, also conceptual cleanness: List is purely a specification of interface, AbstractList has behaviour that could conceivably be wrong in some situations. Interface-only inheritance should be preferred when you do not need to inherit behaviour but only need to provide the capability of polymorphism.
    – Jules
    Jul 5, 2015 at 5:21
  • 1
    @Jules Only advantage that I understand: Any class MyList that defines all of the required methods and obeys the general contract is preferred to implement an interface List, because the class Myclass(some business class) do not need to reside in the above class hierarchy. This has nothing to do with multiple inheritance or polymorphism. Jul 5, 2015 at 9:49

3 Answers 3

7

Your question seems to stem from the wrong assumption that every List is also a subclass of AbstractList. While AbstractList offers versatile base implementations for a lot of methods, there might be reasons not to use this option.

It’s hard to find an example when looking to the public API only, but there is one: CopyOnWriteArrayList.

You will find much more once you understand that not every implementation is public, e.g. by looking at Collections.unmodifiableList and Collections.synchronizedList, both returning implementations not inheriting from AbstractList for a good reason. They have base classes which are more suitable to their task, UnmodifiableList extends UnmodifiableCollection and SynchronizedList extends SynchronizedCollection.

There can be other, application-specific reasons not to subclass AbstractList, in the end, the decision to make the entire Collection-API interface-based is fundamental and there is no reason to make an exception for List. It’s not different to why you should use the Collection interface instead of AbstractCollection or the Set interface instead of AbstractSet

Regarding how to use it… If it is about parameters or heap variables which ought to offer the maximum flexibility, of course, you should always use the least specific type that is required for the operation, e.g. the List interface, if it is required that the provided Collection has List semantic. As said, there are List types which do not extend AbstractList.

If it is about local variables within an implementation code, you might declare a variable to match the type of the actual implementation, e.g. ArrayList<X> l=new ArrayList<>(); to reduce the number of different types which occur in this code. But that still implies that there is no reason to refer to AbstractList. The only place where a reference is to AbstractList is feasible is in the extends AbstractList clause…

4
  • 1) java.util.Collections is container of all inner static class data models and algo. Why would it sit under AbstractList? So, yes you are right, this static impl has to program on interfaces. ##2) If implementations like CopyOnWriteArrayList are sitting in subpackg (java.util.concurrent), then yes, CopyOnWriteArrayList has to program on interface as I said in this comment. Perfect answer!!!! Jul 7, 2015 at 3:32
  • one supplementary. Do you think the way we use interface Comparable , Callable & ActionListeneris different from usage of interface List, Set Collection? How do you see the difference? Jul 7, 2015 at 3:52
  • Comparable, Callable & ActionListener have only a single abstract method, thus, there is little sense in providing an abstract base class. Since Java 8, such interfaces are called functional interfaces and can be implemented using a lambda expression. Now that interfaces can have default methods, you’ll have to think about whether an interface is basically a function, i.e. has one primary abstract method, as then, you might want to provide default methods for all others. However, note that AbstractList maintains mutable state, i.e. the modCount.
    – Holger
    Jul 7, 2015 at 8:04
  • Further, AbstractList is a skeleton for certain kind of list implementation (i.e. compare to AbstractSequentialList), thus is not that open to arbitrary interface implementations. It’s useful for a lot of implementations but not for all. That’s the reason why UnmodifiableList and SynchronizedList are not subclasses of AbstractList (in contrast to EmptyList), not because they are nested types of Collections but because the AbstractList’s base implementation is not suitable for their purpose.
    – Holger
    Jul 7, 2015 at 8:07
6

In both of your code snippets, the use of AbstractList is discouraged.1 The correct usage is to put the new instance of list in a List variable.

The abstract classes AbstractList and AbstractSequentialList are provided for the convenience of implementers (i.e. library writers) of list-like containers, by providing default implementations(*) for some of the instance methods, in an effort to reduce code duplication.

(*)There is an ongoing, legitimate debate on what are the (i) preferred-, (ii) tolerable- and (iii) discouraged-ways of providing default implementations of instance methods in the Java language. Please see some of the other questions asked by overexchange for a starting point.

Every list-like container must implement the List interface directly or indirectly, for them to be usable by other applications in a list-like manner. Inheritance from AbstractList or AbstractSequentialList is optional.

Likewise, applications that would like to accept a list-like container should accept a List. It should not require an AbstractList or AbstractSequentialList because it would disqualify some list-like containers.

As to the motivation for naming the interface List as is, it is likely2 the decision of some influential Java founding fathers that decided that interfaces shall not have any naming decorations that indicate they are interfaces (i.e. not backed by any concrete implementations). That position is debatable but it will stay with the Java language forever.

1 "discouraged" is used as an euphemism for "plainly wrong."

2 Citation needed. Feel free to edit this post to add the necessary reference, or to remove this paragraph if this is incorrect.

5
  • 3
    Key point: if you extend AbstractList, you can't extend another class. If you want to implement list and extend something else - you can't unless there is a list interface.
    – user40980
    Jul 5, 2015 at 3:09
  • it would disqualify some list-like containers.? I did not get you. Jul 5, 2015 at 8:59
  • 1
    @overexchange with gnat's example - how would you implement class Book extends Content implements List<Page> without being able to implement a List as an interface? You would have to have Content extend AbstractList - which doesn't necessarily make sense. AbstractList contains common tools for implementing a list. It also implements List. But there are things that don't need AbstractList that want to implement a List that need to extend something that shouldn't extend AbstractList. So you have the List interface.
    – user40980
    Jul 5, 2015 at 12:46
  • @MichaelT If there are things that don't need AbstractList, override it. Jul 5, 2015 at 12:51
  • 1
    @overexchange more importantly - don't extend things that have no bearing on the class you are writing.
    – user40980
    Jul 5, 2015 at 12:52
3

I would like to understand the clear reason, Why additionally interface List is introduced?

In Java, types form a directed acyclic graph, but classes form a tree. As such, types are strictly more flexible than classes. When designing APIs, you should prefer uses non-class types as much as possible for your parameters and your return types. And pretty much your only choice in Java for a non-class type is an interface.

In other words, interfaces are nicer for users of your types.

However (at least prior to Java 8), if you actually want these types to have an implementation, you need a (possibly abstract) class. So classes are nicer for implementors of your types.

In order to satisfy both users and implementors, the designers of the List API provided both a List interface and an AbstractList abstract class.

Funnily enough, today with Java 8, interfaces can have so called "default implementations", thus removing the need for the AbstractList abstract class. So your question should be phrased the other way: "Why was the additional abstract class AbstractList introduced?" and the answer would have been "due to historical reasons, old Javas did not have default methods."

8
  • you mean: "Trees are DAGs with the restriction that a child can only have one parent.", But what is the advantage of DAG formation with AbstractList implementing interface List in addition to extending AbstractCollection? Jul 5, 2015 at 9:09
  • interfaces are nicer for users of your types.? you mean, If one introduces a new class hierarchy, users had to get access to that new class hierarchy via their interfaces? Is that the reason we have interface List<E>? Jul 5, 2015 at 9:19
  • forming DAGs: implements Comparable is a relevant example. For me, It is clear why Comparable is an interface? Jul 5, 2015 at 9:41
  • Also, interfaces define object types, classes define abstract data types, so, if you want to do object-oriented programming in Java, you must use only interfaces as types, you cannot use anything else (classes or primitives) as types. This means: types of locals, fields, static fields, method parameters, method return types, the argument to an instanceof or cast operator, and the type argument to a generic interface can only be interfaces. Classes can only be used as factories, i.e. the only place a class is allowed to appear is directly next to a new. Nowhere else. Jul 5, 2015 at 9:54
  • 3
    This is explained much better than I could ever hope to achieve in On Understanding Data Abstraction, Revisited by William R. Cook. It uses Java for the examples, but it applies just as well to C# or any other language. Jul 5, 2015 at 11:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.