The implementation of java.util.ArrayList
implements List
as well as extends AbstractList
. But in java docs you can see that AbstractL
1) ArrayList implements List
is redundant but still legal. Only JCF (Java Collection Framework) designers could answer why. Since the lead JCF designer J.Bloch does not say why it's like this in "Effective Java" it seems we will never know why.
2) Arrays.asList returns
public class Arrays {
...
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
...
it's not java.util.ArrayList and it cannot be cast to it
Arrays.asList returns a List. So casting it to ArrayList is not safe as you do not know what type of List is being returned (depends on the array type it's creating the list from). Your second snippet wants an ArrayList implicitly. Hence it fails while your first snippet compiles fine because it expects a List. You can do-
ArrayList<String> a = new ArrayList<String>(Arrays.asList(stra));
I believe, there is a reason. This is just my thought and I didn't find it anywhere in JLS.
If I am a developer who is writing an API which is to be widely used, why will I do this?
There is absolutely no reason of doing this, but consider this scenario, where I have written the List
interface and provided the ArrayList
implementation for the the List
interface.
I have not yet written any abstract class AbstractList
till now.
One day a requirement comes, where I am asked to write few more implementations of the List
interface where most of them are having similar or same concrete methods for the abstract
methods in List
interface.
I will go ahead and write an AbstractList
with necessary implementation for all those methods. But now I will not like that half of my classes to implement the List
interface and half of them extending AbstractList
.
Also, I cannot just go and remove the 'implements List` from the classes I wrote earlier, might be because this is not the right time or I do not want other's code to break with my new release.
Note This is solely my opinion.
I will be simple and direct in my answers.
wouldn't it be redundant to implement List as well as extend AbstractList?
Yes, it is, but they did it just to clarify the code, to be easy to see that the class implements List interface.
The Arrays.asList() method of the Arrays class contains its own implementation of ArrayList. But this one only extends AbstractList but does not implement List.
As you could see, that was redundant, you don't need to re-declare the implementation of List interface if AbstractList already declares that implementation.
I get an error : cannot convert form List to ArrayList What is the reason behind this?
Arrays.asList() returns a List, it could be any type of List. The ArrayList implemented in that code is not the same ArrayList of java.util.ArrayList, they just share the same name, but they are not the same code.
The answer to your first question is that implementing List is a contract. That contract can be defined by both AbstractList and ArrayList. ArrayList implements List to publish the fact that will respect the List contract in the future when it might be necessary to extend not from AbstractList that may or may not implement a List.
For the second question: Arrays.asList returns a List. It could happen that in the current implementation returns ArrayList. In the next version could return a different list LinkedList for example and the contract(defined by the method signature) will still be respected.
For your first question take a look at Why does ArrayList have "implements List"?
To answer your second question
java.util.ArrayList<String> a = Arrays.asList(stra);
as you mentioned Arrays.asList
returns its own implementation of AbstractList and unfortunately creators of this code also named this class ArrayList. Now because we cant cast horizontally but only vertically returned array list can't be cast to java.utli.ArrayList
but only to java.util.AbstractList
or its super types like java.util.List
that is why your first code example works.