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

Malachi
  • 608
  • 5
  • 18
overexchange
  • 2,245
  • 2
  • 17
  • 47
  • 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` - one couldn't do this with AbstractList, because there would be no way for Book to extend both Content and AbstractList simultaneously – gnat Jul 05 '15 at 02:33
  • @gnat wording is 'instead of' in your referred query. Here both are used, abstract class and interface – overexchange Jul 05 '15 at 02:35
  • 1
    The motivation is explained in the `AbstractList` [documentation](https://docs.oracle.com/javase/8/docs/api/java/util/AbstractList.html). 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 05 '15 at 02:35
  • So, Are we saying that multiple inheritance is the only reason in this case, to introduce `interface List`? – overexchange Jul 05 '15 at 04:53
  • 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 05 '15 at 05: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. – overexchange Jul 05 '15 at 09:49

3 Answers3

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…

Holger
  • 216
  • 2
  • 5
  • 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](http://programmers.stackexchange.com/questions/288737/why-liste-interface-is-additionally-introduced-in-collection-hierarchy#comment596866_288737). Perfect answer!!!! – overexchange Jul 07 '15 at 03:32
  • one supplementary. Do you think the way we use interface `Comparable` , `Callable` & `ActionListener`is different from usage of interface `List`, `Set` `Collection`? How do you see the difference? – overexchange Jul 07 '15 at 03: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 07 '15 at 08: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 07 '15 at 08: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.

rwong
  • 16,695
  • 3
  • 33
  • 81
  • 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. –  Jul 05 '15 at 03:09
  • it would disqualify some list-like containers.? I did not get you. – overexchange Jul 05 '15 at 08:59
  • 1
    @overexchange with gnat's example - how would you implement `class Book extends Content implements List` 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. –  Jul 05 '15 at 12:46
  • @MichaelT If there are things that don't need `AbstractList`, override it. – overexchange Jul 05 '15 at 12:51
  • 1
    @overexchange more importantly - don't extend things that have no bearing on the class you are writing. –  Jul 05 '15 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."

Nebu Pookins
  • 411
  • 2
  • 5
  • 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`? – overexchange Jul 05 '15 at 09: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`? – overexchange Jul 05 '15 at 09:19
  • forming DAGs: `implements Comparable` is a relevant example. For me, It is clear why `Comparable` is an interface? – overexchange Jul 05 '15 at 09: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. – Jörg W Mittag Jul 05 '15 at 09:54
  • Note: there is nothing wrong with doing ADT-oriented programming in Java, but *if* you want to do OO, *then* you can't use classes or primitives as types. – Jörg W Mittag Jul 05 '15 at 09:55
  • @JörgWMittag Can you give a reference that talks more on "interfaces define object types"? Is interface `Comparable`, `Callable` define object types? – overexchange Jul 05 '15 at 11:37
  • 3
    This is explained much better than I could ever hope to achieve in [*On Understanding Data Abstraction, Revisited*](http://CS.UTexas.Edu/~wcook/Drafts/2009/essay.pdf) by [William R. Cook](http://WCook.BlogSpot.Com/). It uses Java for the examples, but it applies just as well to C# or any other language. – Jörg W Mittag Jul 05 '15 at 11:47
  • @JörgWMittag: Is there anything wrong with `class Foo extends Bar`, or does that run afoul of "the only place a class is allowed to appear is directly next to a `new`"? IOW, are we allowed to inherit from classes, or should we only implement interfaces? – Kevin Jul 06 '15 at 16:04