1

Any user who would like to access the java.util.ArrayList facility, has to obey the usage contract provided in java.util.List.

But one can break this usage contract easily and access the methods trimToSize

public void trimToSize() { ... }

and ensureCapacity

public void ensureCapacity(int minCapacity) { ...}

Because these two methods are neither overridden from java.util.AbstractList nor implemented from java.util.List.

So, Why these two methods provide public level access and break the abstraction provided by java.util.List?

Mureinik
  • 297,002
  • 52
  • 306
  • 350
overexchange
  • 15,768
  • 30
  • 152
  • 347
  • 2
    These methods are additional functionality. I don't think they break any contract in `java.util.List`, as all of that functionality is also (presumably) correctly implemented. In what way do you think they break the contract? – clstrfsck Aug 03 '15 at 05:41
  • 2
    In what way is the abstraction provided by `java.util.List` "broken" by these `ArrayList` methods? That's kind of like saying that dogs "break the abstraction of 'mammal'" because they can bark, while barking is not part of the abstraction "mammal". – Ted Hopp Aug 03 '15 at 05:42
  • So you're saying that subclasses should never be able to extend the interface of their super classes with public methods? – Smutje Aug 03 '15 at 05:42
  • http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface – Sotirios Delimanolis Aug 03 '15 at 05:44
  • @TedHopp Here the abstraction separates interface(`List`) from implementation(`ArrayList`/`LinkedList`). Purpose of this abstraction is to access the list facility via interface(`List`) only. Am I correct? – overexchange Aug 03 '15 at 06:08
  • The purpose of the abstraction is to specify a contract of behavior that all `List` implementations must provide. Implementation classes are free to add behavior beyond that specified in the contract. If one knows that an object is a specific implementation type, nothing is "broken" by using that extra behavior. It is a different question, however, to ask if _using_ those extra methods violates the ["interface-based programming"](https://en.wikipedia.org/wiki/Interface-based_programming) architectural pattern or "program to the interface" advice. It does. But the methods themselves don't. – Ted Hopp Aug 03 '15 at 15:35

2 Answers2

6

There are some cases where efficiency may cost more than data abstraction. The ensureCapacity may be used to preallocate the internal buffer once when you are about to add known number of elements. The trimToSize may be used when you are not going to add more elements to free wasted memory. Both methods are non-applicable to other List implementations, thus they are added to ArrayList only.

Note that usually list is created and initially populated by one method which knows what implementation is used. So this does not break abstraction. For example, consider such code:

public List<String> createList() {
    ArrayList<String> list = new ArrayList<>();
    // populate the list
    list.trimToSize();
    return list;
}

This way you can save the memory and still return the List interace.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
2

Nothing here breaks List's contract. ArrayList is a specific implementation of List, and if your program has specific performance needs that are important enough for you to forgo the abstraction of using a List, there's no reason not to allow you to use specific methods to tune ArrayList's behavior.

Mureinik
  • 297,002
  • 52
  • 306
  • 350