This question already has answers here:
What does it mean to "program to an interface"?
(33 answers)
Closed 2 years ago.
(1) List<?> myList = new ArrayList<?>();
(2) ArrayList<?> myList = new ArrayList<?>();
I understand that with (1), implementations of the List interface can be swapped. It seems that (1) is typically used in an application regardless of need (myself I always use this).
I am wondering if anyone uses (2)?
Also, how often (and can I please get an example) does the situation actually require using (1) over (2) (i.e. where (2) wouldn't suffice..aside coding to interfaces and best practices etc.)
Almost always List is preferred over ArrayList because, for instance, List can be translated into a LinkedList without affecting the rest of the codebase.
If one used ArrayList instead of List, it's hard to change the ArrayList implementation into a LinkedList one because ArrayList specific methods have been used in the codebase that would also require restructuring.
You can read about the List implementations here.
You may start with an ArrayList, but soon after discover that another implementation is the more appropriate choice.
I am wondering if anyone uses (2)?
Yes. But rarely for a sound reason (IMO).
And people get burned because they used ArrayList when they should have used List:
Utility methods like Collections.singletonList(...) or Arrays.asList(...) don't return an ArrayList.
Methods in the List API don't guarantee to return a list of the same type.
For example of someone getting burned, in https://stackoverflow.com/a/1481123/139985 the poster had problems with "slicing" because ArrayList.sublist(...) doesn't return an ArrayList ... and he had designed his code to use ArrayList as the type of all of his list variables. He ended up "solving" the problem by copying the sublist into a new ArrayList.
The argument that you need to know how the List behaves is largely addressed by using the RandomAccess marker interface. Yes, it is a bit clunky, but the alternative is worse.
Also, how often does the situation actually require using (1) over (2) (i.e. where (2) wouldn't suffice..aside 'coding to interfaces' and best practices etc.)
The "how often" part of the question is objectively unanswerable.
(and can I please get an example)
Occasionally, the application may require that you use methods in the ArrayList API that are not in the List API. For example, ensureCapacity(int), trimToSize() or removeRange(int, int). (And the last one will only arise if you have created a subtype of ArrayList that declares the method to be public.)
That is the only sound reason for coding to the class rather than the interface, IMO.
(It is theoretically possible that you will get a slight improvement in performance ... under certain circumstances ... on some platforms ... but unless you really need that last 0.05%, it is not worth doing this. This is not a sound reason, IMO.)
You can’t write efficient code if you don’t know whether random access is efficient or not.
That is a valid point. However, Java provides better ways to deal with that; e.g.
public <T extends List & RandomAccess> void test(T list) {
// do stuff
}
If you call that with a list that does not implement RandomAccess you will get a compilation error.
You could also test dynamically ... using instanceof ... if static typing is too awkward. And you could even write your code to use different algorithms (dynamically) depending on whether or not a list supported random access.
Note that ArrayList is not the only list class that implements RandomAccess. Others include CopyOnWriteList, Stack and Vector.
I've seen people make the same argument about Serializable (because List doesn't implement it) ... but the approach above solves this problem too. (To the extent that it is solvable at all using runtime types. An ArrayList will fail serialization if any element is not serializable.)
Finally, I'm not going to say "because its is good style". That "reason" is both a circular argument ("Why is it 'good style'?") and an appeal to an unstated (and probably non-existent!) higher authority ("Who says it is 'good style'?").
(I do think it is good style to program to the interface, but I'm not going to give that as a reason. It is better for you to understand the real reasons and come to the (IMO) correct conclusions for yourself. The correct conclusion may not always be the same ... depending on the context.)
For example you might decide a LinkedList is the best choice for your application, but then later decide ArrayList might be a better choice for performance reason.
Use:
List list = new ArrayList(100); // will be better also to set the initial capacity of a collection
Instead of:
ArrayList list = new ArrayList();
For reference:
(posted mostly for Collection diagram)
It is considered good style to store a reference to a HashSet or TreeSet in a variable of type Set.
Set<String> names = new HashSet<String>();
This way, you have to change only one line if you decide to use a TreeSet instead.
Also, methods that operate on sets should specify parameters of type Set:
public static void print(Set<String> s)
Then the method can be used for all set implementations.
In theory, we should make the same recommendation for linked lists, namely to save
LinkedList references in variables of type List. However, in the Java library, the List interface is common to both the ArrayList and the LinkedList class. In particular, it has get and set methods for random access, even though these methods are very inefficient for linked lists.
You can’t write efficient code if you don’t know whether random access is efficient or not.
This is plainly a serious design error in the standard library, and I cannot recommend using
the List interface for that reason.
To see just how embarrassing that error is, have a look at
the source code for the binarySearch method of the Collections class. That method takes a
List parameter, but binary search makes no sense for a linked list. The code then clumsily
tries to discover whether the list is a linked list, and then switches to a linear search!
The Set interface and the Map interface, are well designed, and you should use them.
When you write List, you actually tell, that your object implements List interface only, but you don't specify what class your object belongs to.
When you write ArrayList, you specify that your object class is a resizable-array.
So, the first version makes your code more flexible in future.
Look at Java docs:
Class ArrayList - Resizable-array implementation of the List interface.
Interface List - An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted.
Array - container object that holds a fixed number of values of a single type.
I use (2) if code is the "owner" of the list. This is for example true for local-only variables. There is no reason to use the abstract type List instead of ArrayList.
Another example to demonstrate ownership:
public class Test {
// This object is the owner of strings, so use the concrete type.
private final ArrayList<String> strings = new ArrayList<>();
// This object uses the argument but doesn't own it, so use abstract type.
public void addStrings(List<String> add) {
strings.addAll(add);
}
// Here we return the list but we do not give ownership away, so use abstract type. This also allows to create optionally an unmodifiable list.
public List<String> getStrings() {
return Collections.unmodifiableList(strings);
}
// Here we create a new list and give ownership to the caller. Use concrete type.
public ArrayList<String> getStringsCopy() {
return new ArrayList<>(strings);
}
}
I think the people who use (2) don't know the Liskov substitution principle or the Dependency inversion principle. Or they really have to use ArrayList.
Actually there are occasions where (2) is not only preferred but mandatory and I am very surprised, that nobody mentions this here.
Serialization!
If you have a serializable class and you want it to contain a list, then you must declare the field to be of a concrete and serializable type like ArrayList because the List interface does not extend java.io.Serializable
Obviously most people do not need serialization and forget about this.
An example:
public class ExampleData implements java.io.Serializable {
// The following also guarantees that strings is always an ArrayList.
private final ArrayList<String> strings = new ArrayList<>();
(3) Collection myCollection = new ArrayList<?>();
I am using this typically. And only if I need List methods, I will use List. Same with ArrayList. You always can switch to more "narrow" interface, but you can't switch to more "wide".
Out of the following two:
(1) List<?> myList = new ArrayList<?>();
(2) ArrayList<?> myList = new ArrayList<?>();
First is generally preferred. As you will be using methods from List interface only, it provides you the freedom to use some other implementation of List e.g. LinkedList in future. So it decouples you from specific implementation. Now there are two points worth mentioning:
We should always program to interface. More here.
You will almost always end up using ArrayList over LinkedList. More here.
I am wondering if anyone uses (2)
Yes sometimes (read rarely). When we need methods that are part of implementation of ArrayList but not part of the interface List. For example ensureCapacity.
Also, how often (and can I please get an example) does the situation
actually require using (1) over (2)
Almost always you prefer option (1). This is a classical design pattern in OOP where you always try to decouple your code from specific implementation and program to the interface.
List is an interface. It doesn't have methods. When you call a method on a List reference, it in fact calls the method of ArrayList in both cases.
And for the future you can change List obj = new ArrayList<> to List obj = new LinkList<> or other types which implement List interface.
Somebody asked this again (duplicate) which made me go a little deeper on this issue.
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
ArrayList<String> aList = new ArrayList<String>();
aList.add("a");
aList.add("b");
}
If we use a bytecode viewer (I used http://asm.ow2.org/eclipse/index.html) weĺl see the following (only list initialization and assignment) for our list snippet:
L0
LINENUMBER 9 L0
NEW ArrayList
DUP
INVOKESPECIAL ArrayList.<init> () : void
ASTORE 1
L1
LINENUMBER 10 L1
ALOAD 1: list
LDC "a"
INVOKEINTERFACE List.add (Object) : boolean
POP
L2
LINENUMBER 11 L2
ALOAD 1: list
LDC "b"
INVOKEINTERFACE List.add (Object) : boolean
POP
and for alist:
L3
LINENUMBER 13 L3
NEW java/util/ArrayList
DUP
INVOKESPECIAL java/util/ArrayList.<init> ()V
ASTORE 2
L4
LINENUMBER 14 L4
ALOAD 2
LDC "a"
INVOKEVIRTUAL java/util/ArrayList.add (Ljava/lang/Object;)Z
POP
L5
LINENUMBER 15 L5
ALOAD 2
LDC "b"
INVOKEVIRTUAL java/util/ArrayList.add (Ljava/lang/Object;)Z
POP
The difference is list ends up calling INVOKEINTERFACE whereas aList calls INVOKEVIRTUAL. Accoding to the Bycode Outline Plugin reference,
invokeinterface is used to invoke a method declared within a Java
interface
while invokevirtual
invokes all methods except interface methods (which use
invokeinterface), static methods (which use invokestatic), and the few
special cases handled by invokespecial.
In summary, invokevirtual pops objectref off the stack while for invokeinterface
the interpreter pops 'n' items off the operand stack, where 'n' is an 8-bit unsigned
integer parameter taken from the bytecode. The first of these items is
objectref, a reference to the object whose method is being called.
If I understand this correctly, the difference is basically how each way retrieves objectref.
The only case that I am aware of where (2) can be better is when using GWT, because it reduces application footprint (not my idea, but the google web toolkit team says so). But for regular java running inside the JVM (1) is probably always better.
I would say that 1 is preferred, unless
you are depending on the implementation of optional behavior* in ArrayList, in that case explicitly using ArrayList is more clear
You will be using the ArrayList in a method call which requires ArrayList, possibly for optional behavior or performance characteristics
My guess is that in 99% of the cases you can get by with List, which is preferred.
for instance removeAll, or add(null)
List interface have several different classes - ArrayList and LinkedList. LinkedList is used to create an indexed collections and ArrayList - to create sorted lists. So, you can use any of it in your arguments, but you can allow others developers who use your code, library, etc. to use different types of lists, not only which you use, so, in this method
ArrayList<Object> myMethod (ArrayList<Object> input) {
// body
}
you can use it only with ArrayList, not LinkedList, but you can allow to use any of List classes on other places where it method is using, it's just your choise, so using an interface can allow it:
List<Object> myMethod (List<Object> input) {
// body
}
In this method arguments you can use any of List classes which you want to use:
List<Object> list = new ArrayList<Object> ();
list.add ("string");
myMethod (list);
CONCLUSION:
Use the interfaces everywhere when it possible, don't restrict you or others to use different methods which they want to use.
Related
Is it possible to find out if some a list is fixed size or not?
I mean, for example this code:
String[] arr = {"a", "b"};
List<String> list = Arrays.asList(array);
returns fixed size List backed by an array. But is it possible to understand programmatically if List is fixed-size or not without trying to add/remove elements and catching the exception? For example:
try {
list.add("c");
}
catch(UnsupportedOperationException e) {
// Fixed-size?
}
A list created from a String[] by
List<String> list = Arrays.asList(array);
will have Arrays as enclosing class, while one created by for example new ArrayList() won't have the enclosing class. So the following should work to check if the List was produced as a result of calling Arrays.toList():
static <T> boolean wasListProducedAsAResultOfCallingTheFunctionArrays_asList(List<T> l) {
return Arrays.class.equals(l.getClass().getEnclosingClass());
}
Beware that this method relies on undocumented behavior. It will break if they added another nested List subclass to the Arrays class.
Is it possible to find out if some list is fixed size or not?
In theory - No. Fixed sizedness is an emergent property of the implementation of a list class. You can only determine if a list has that property by trying to add an element.
And note that a simple behavioral test would not reliably distinguish between a fixed sized list and a bounded list or a list that was permanently or temporarily read-only.
In practice, a fixed sized list will typically have a different class to an ordinary one. You can test the class of an object to see if it or isn't a specific class. So if you understand what classes would be used to implement fixed sized lists in your code-base, then you can test if a specific list is fixed sized.
For example the Arrays.asList(...) method returns a List object whose actual class is java.util.Arrays.ArrayList. That is a private nested class, but you could use reflection find it, and then use Object.getClass().equals(...) to test for it.
However, this approach is fragile. Your code could break if the implementation of Arrays was modified, or if you started using other forms of fixed sized list as well.
No.
The List API is identical regardless of whether a List is expandable or not, something that was deliberate.
There is also nothing in the List API that allows you to query it to determine this feature.
You can't completely reliably determine this information by reflection, because you will be depending on internal details of the implementation, and because there is an unbounded number of classes that are potentially fixed-size. For example, in addition to Arrays.asList, there is also Arrays.asList().subList, which happens to return a different class. There can also be wrappers around the base list like Collections.checkedList, Collections.synchronizedList and Collections.unmodifiableList. There are also other fixed-size lists: Collections.emptyList, Collections.singletonList, and Collections.nCopies. Outside the standard library, there are things like Guava's ImmutableList. It's also pretty trivial to hand-roll a list for something by extending AbstractList (for a fixed-size list you need only implement the size() and get(int) methods).
Even if you detect that your list is not fixed-size, the specification of List.add allows it to refuse elements for other reasons. For example, Collections.checkedList wrappers throw a ClassCastException for elements of unwanted type.
And even if you know your list is expandable, and allows arbitrary elements, that doesn't mean you want to use it. Perhaps it's synchronized, or not synchronized, or isn't serializable, or it's a slow linked list, or has some other quality that you don't want.
If you want control over the type, mutability, serializability, or thread-safety of the list, or you want to be sure that no other code has kept a reference to it, the practice is that you create a new one yourself. It's not expensive to do so when unnecessary (memcopies are blazing fast), and it lets you reason more definitely about your code will actually do at runtime. If you'd really like to avoid creating unnecessary copies, try whitelisting instead of blacklisting list classes. For example:
if (list.getClass() != ArrayList.class) {
list = new ArrayList<>(list);
}
(Note: That uses getClass instead of instanceof, because instanceof would also be true for any weird subclasses of ArrayList.)
There are immutable collections in java-9, but there is still no common #Immutable annotation for example or a common marker interface that we could query to get this information.
The simplest way I can think of would be simply to get the name of the class of such an instance:
String nameList = List.of(1, 2, 3).getClass().getName();
System.out.println(nameList.contains("Immutable"));
but that still relies on internal details, since it queries the name of the common class ImmutableCollections, that is not public and obviously can change without notice.
This question already has answers here:
What does it mean to "program to an interface"?
(33 answers)
Closed 6 years ago.
If we consider two implementations below, what's the actual use of the first one?
List<String> a= new ArrayList<String>();
ArrayList<String> b= new ArrayList<String>();
From what I have read in the posts, the first implementation helps in avoiding breaking change like we can change the implementation again as
a=new TreeList<String>();
But I don't understand whats the actual use of changing the implementation with treelist as we can use only the List interface methods?
But I don't understand whats the actual use of changing the implementation with treelist as we can use only the List interface methods?
Different implementations of interface List have different performance characteristics for different operations. Which implementation of List you should choose is not arbitrary - different implementations are more efficient for different purposes.
For example, inserting an element somewhere in the middle is expensive on an ArrayList, but cheap on a LinkedList, because of the way the implementations work. Likewise, accessing an element by index is cheap on an ArrayList, but expensive on a LinkedList.
It may happen that when you started writing your program, you used an ArrayList without thinking about it too much, but later you discover that a LinkedList would be more efficient.
When you've programmed against the interface List instead of a specific implementation, it's very easy to change from ArrayList to LinkedList - to the rest of the program, it still looks like a List, so you'd only have to change one line.
Lets say that you have decided to develop a more efficient List implementation of your own. Perhaps one that has better memory management internally, or may be a faster set method (insertion) implementation. You can just implement the List interface and rest of your code will continue to work without any change, except this one line. You can also extend ArrayList and write your own code.
//Old code
List<String> a = new ArrayList<String>();
a.set(0, "Test");
//New code
List<String> a = new MyCustomisedList<String>();
//Same code, but your optimized set logic. May be faster...
a.set(0, "Test");
A TreeList doesn't exist, so lets use a PersistentList as an example.
Lets say you have an #Entity that you want to save to a database:
public class MyMagicEntity {
#OneToMany
List<MyChildEntity> children;
public void setChildren(final List<MyChildEntity> children) {
this.children = children;
}
}
Now, when you create MyMagicEntity then you would do something like
final MyMagicEntity mme = new MyMagicEntity();
final List<MyChildEntity> children = new ArrayList<>();
children.add(new MyChildEntity("one"));
children.add(new MyChildEntity("two"));
children.add(new MyChildEntity("three"));
mme.setChildren(children);
//save to DB
So you created an ArrayList that you passed into your MyMagicEntity, which assigns it to the List - it doesn't care that the underlying implementation is as long as it's a List.
Now, later you do:
final MyMagicEntity mme = //load from DB
final List<Children> children = mme.getChildren();
So, what is children? Well, if we are using JPA and Hibernate it is actually a PersistentList, not an ArrayList.
As we access the members of children, Hibernate will go and pull them from the database. This List is still a List - your program doesn't have to know any of this.
Could you do this without using the List interface? No! Because:
you cannot create a PersistentList
Hibernate cannot create an ArrayList
Whilst this is an extreme example, where the underlying behaviour of the List is completely different, this applies in all sorts of other situations.
For example:
ArrayList and LinkedList have different performance characteristics, you may want to switch
Guava has an ImmutableList which you may want to use
Collections.unmodifyableList also implements List, which you may want to use
You could conceivably have a List backed by a file
The basic idea is that List defines what any list must be able to do, but not how it is done.
Here List is an Interface which contains all common operation method can perform with an List.
List Interface is parent for ArrayList , LinkedList and many more class. So, It can hold all these type of Object reference.
All these List method have different (or own type) Implementation with different class. So, whatever method you use will automatically apply according to override method definition of Object belong to the class.
List<String> a= new ArrayList<String>();
ArrayList<String> b= new ArrayList<String>();
Now , In Your case you can declare both ways is alright. but suppose a Scenario like this.
You are calling some services and you know that return any List Type (not specific) of Object. It may be a LinkedList or ArrayList or any other type of List.
at that time whatever response you get You can easily hold those responses in a List Type of Reference Variable.
and after gathering the result you can differentiate further of Object Type.
This question already has answers here:
What does it mean to "program to an interface"?
(33 answers)
Closed 2 years ago.
(1) List<?> myList = new ArrayList<?>();
(2) ArrayList<?> myList = new ArrayList<?>();
I understand that with (1), implementations of the List interface can be swapped. It seems that (1) is typically used in an application regardless of need (myself I always use this).
I am wondering if anyone uses (2)?
Also, how often (and can I please get an example) does the situation actually require using (1) over (2) (i.e. where (2) wouldn't suffice..aside coding to interfaces and best practices etc.)
Almost always List is preferred over ArrayList because, for instance, List can be translated into a LinkedList without affecting the rest of the codebase.
If one used ArrayList instead of List, it's hard to change the ArrayList implementation into a LinkedList one because ArrayList specific methods have been used in the codebase that would also require restructuring.
You can read about the List implementations here.
You may start with an ArrayList, but soon after discover that another implementation is the more appropriate choice.
I am wondering if anyone uses (2)?
Yes. But rarely for a sound reason (IMO).
And people get burned because they used ArrayList when they should have used List:
Utility methods like Collections.singletonList(...) or Arrays.asList(...) don't return an ArrayList.
Methods in the List API don't guarantee to return a list of the same type.
For example of someone getting burned, in https://stackoverflow.com/a/1481123/139985 the poster had problems with "slicing" because ArrayList.sublist(...) doesn't return an ArrayList ... and he had designed his code to use ArrayList as the type of all of his list variables. He ended up "solving" the problem by copying the sublist into a new ArrayList.
The argument that you need to know how the List behaves is largely addressed by using the RandomAccess marker interface. Yes, it is a bit clunky, but the alternative is worse.
Also, how often does the situation actually require using (1) over (2) (i.e. where (2) wouldn't suffice..aside 'coding to interfaces' and best practices etc.)
The "how often" part of the question is objectively unanswerable.
(and can I please get an example)
Occasionally, the application may require that you use methods in the ArrayList API that are not in the List API. For example, ensureCapacity(int), trimToSize() or removeRange(int, int). (And the last one will only arise if you have created a subtype of ArrayList that declares the method to be public.)
That is the only sound reason for coding to the class rather than the interface, IMO.
(It is theoretically possible that you will get a slight improvement in performance ... under certain circumstances ... on some platforms ... but unless you really need that last 0.05%, it is not worth doing this. This is not a sound reason, IMO.)
You can’t write efficient code if you don’t know whether random access is efficient or not.
That is a valid point. However, Java provides better ways to deal with that; e.g.
public <T extends List & RandomAccess> void test(T list) {
// do stuff
}
If you call that with a list that does not implement RandomAccess you will get a compilation error.
You could also test dynamically ... using instanceof ... if static typing is too awkward. And you could even write your code to use different algorithms (dynamically) depending on whether or not a list supported random access.
Note that ArrayList is not the only list class that implements RandomAccess. Others include CopyOnWriteList, Stack and Vector.
I've seen people make the same argument about Serializable (because List doesn't implement it) ... but the approach above solves this problem too. (To the extent that it is solvable at all using runtime types. An ArrayList will fail serialization if any element is not serializable.)
Finally, I'm not going to say "because its is good style". That "reason" is both a circular argument ("Why is it 'good style'?") and an appeal to an unstated (and probably non-existent!) higher authority ("Who says it is 'good style'?").
(I do think it is good style to program to the interface, but I'm not going to give that as a reason. It is better for you to understand the real reasons and come to the (IMO) correct conclusions for yourself. The correct conclusion may not always be the same ... depending on the context.)
For example you might decide a LinkedList is the best choice for your application, but then later decide ArrayList might be a better choice for performance reason.
Use:
List list = new ArrayList(100); // will be better also to set the initial capacity of a collection
Instead of:
ArrayList list = new ArrayList();
For reference:
(posted mostly for Collection diagram)
It is considered good style to store a reference to a HashSet or TreeSet in a variable of type Set.
Set<String> names = new HashSet<String>();
This way, you have to change only one line if you decide to use a TreeSet instead.
Also, methods that operate on sets should specify parameters of type Set:
public static void print(Set<String> s)
Then the method can be used for all set implementations.
In theory, we should make the same recommendation for linked lists, namely to save
LinkedList references in variables of type List. However, in the Java library, the List interface is common to both the ArrayList and the LinkedList class. In particular, it has get and set methods for random access, even though these methods are very inefficient for linked lists.
You can’t write efficient code if you don’t know whether random access is efficient or not.
This is plainly a serious design error in the standard library, and I cannot recommend using
the List interface for that reason.
To see just how embarrassing that error is, have a look at
the source code for the binarySearch method of the Collections class. That method takes a
List parameter, but binary search makes no sense for a linked list. The code then clumsily
tries to discover whether the list is a linked list, and then switches to a linear search!
The Set interface and the Map interface, are well designed, and you should use them.
When you write List, you actually tell, that your object implements List interface only, but you don't specify what class your object belongs to.
When you write ArrayList, you specify that your object class is a resizable-array.
So, the first version makes your code more flexible in future.
Look at Java docs:
Class ArrayList - Resizable-array implementation of the List interface.
Interface List - An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted.
Array - container object that holds a fixed number of values of a single type.
I use (2) if code is the "owner" of the list. This is for example true for local-only variables. There is no reason to use the abstract type List instead of ArrayList.
Another example to demonstrate ownership:
public class Test {
// This object is the owner of strings, so use the concrete type.
private final ArrayList<String> strings = new ArrayList<>();
// This object uses the argument but doesn't own it, so use abstract type.
public void addStrings(List<String> add) {
strings.addAll(add);
}
// Here we return the list but we do not give ownership away, so use abstract type. This also allows to create optionally an unmodifiable list.
public List<String> getStrings() {
return Collections.unmodifiableList(strings);
}
// Here we create a new list and give ownership to the caller. Use concrete type.
public ArrayList<String> getStringsCopy() {
return new ArrayList<>(strings);
}
}
I think the people who use (2) don't know the Liskov substitution principle or the Dependency inversion principle. Or they really have to use ArrayList.
Actually there are occasions where (2) is not only preferred but mandatory and I am very surprised, that nobody mentions this here.
Serialization!
If you have a serializable class and you want it to contain a list, then you must declare the field to be of a concrete and serializable type like ArrayList because the List interface does not extend java.io.Serializable
Obviously most people do not need serialization and forget about this.
An example:
public class ExampleData implements java.io.Serializable {
// The following also guarantees that strings is always an ArrayList.
private final ArrayList<String> strings = new ArrayList<>();
(3) Collection myCollection = new ArrayList<?>();
I am using this typically. And only if I need List methods, I will use List. Same with ArrayList. You always can switch to more "narrow" interface, but you can't switch to more "wide".
Out of the following two:
(1) List<?> myList = new ArrayList<?>();
(2) ArrayList<?> myList = new ArrayList<?>();
First is generally preferred. As you will be using methods from List interface only, it provides you the freedom to use some other implementation of List e.g. LinkedList in future. So it decouples you from specific implementation. Now there are two points worth mentioning:
We should always program to interface. More here.
You will almost always end up using ArrayList over LinkedList. More here.
I am wondering if anyone uses (2)
Yes sometimes (read rarely). When we need methods that are part of implementation of ArrayList but not part of the interface List. For example ensureCapacity.
Also, how often (and can I please get an example) does the situation
actually require using (1) over (2)
Almost always you prefer option (1). This is a classical design pattern in OOP where you always try to decouple your code from specific implementation and program to the interface.
List is an interface. It doesn't have methods. When you call a method on a List reference, it in fact calls the method of ArrayList in both cases.
And for the future you can change List obj = new ArrayList<> to List obj = new LinkList<> or other types which implement List interface.
Somebody asked this again (duplicate) which made me go a little deeper on this issue.
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
ArrayList<String> aList = new ArrayList<String>();
aList.add("a");
aList.add("b");
}
If we use a bytecode viewer (I used http://asm.ow2.org/eclipse/index.html) weĺl see the following (only list initialization and assignment) for our list snippet:
L0
LINENUMBER 9 L0
NEW ArrayList
DUP
INVOKESPECIAL ArrayList.<init> () : void
ASTORE 1
L1
LINENUMBER 10 L1
ALOAD 1: list
LDC "a"
INVOKEINTERFACE List.add (Object) : boolean
POP
L2
LINENUMBER 11 L2
ALOAD 1: list
LDC "b"
INVOKEINTERFACE List.add (Object) : boolean
POP
and for alist:
L3
LINENUMBER 13 L3
NEW java/util/ArrayList
DUP
INVOKESPECIAL java/util/ArrayList.<init> ()V
ASTORE 2
L4
LINENUMBER 14 L4
ALOAD 2
LDC "a"
INVOKEVIRTUAL java/util/ArrayList.add (Ljava/lang/Object;)Z
POP
L5
LINENUMBER 15 L5
ALOAD 2
LDC "b"
INVOKEVIRTUAL java/util/ArrayList.add (Ljava/lang/Object;)Z
POP
The difference is list ends up calling INVOKEINTERFACE whereas aList calls INVOKEVIRTUAL. Accoding to the Bycode Outline Plugin reference,
invokeinterface is used to invoke a method declared within a Java
interface
while invokevirtual
invokes all methods except interface methods (which use
invokeinterface), static methods (which use invokestatic), and the few
special cases handled by invokespecial.
In summary, invokevirtual pops objectref off the stack while for invokeinterface
the interpreter pops 'n' items off the operand stack, where 'n' is an 8-bit unsigned
integer parameter taken from the bytecode. The first of these items is
objectref, a reference to the object whose method is being called.
If I understand this correctly, the difference is basically how each way retrieves objectref.
The only case that I am aware of where (2) can be better is when using GWT, because it reduces application footprint (not my idea, but the google web toolkit team says so). But for regular java running inside the JVM (1) is probably always better.
I would say that 1 is preferred, unless
you are depending on the implementation of optional behavior* in ArrayList, in that case explicitly using ArrayList is more clear
You will be using the ArrayList in a method call which requires ArrayList, possibly for optional behavior or performance characteristics
My guess is that in 99% of the cases you can get by with List, which is preferred.
for instance removeAll, or add(null)
List interface have several different classes - ArrayList and LinkedList. LinkedList is used to create an indexed collections and ArrayList - to create sorted lists. So, you can use any of it in your arguments, but you can allow others developers who use your code, library, etc. to use different types of lists, not only which you use, so, in this method
ArrayList<Object> myMethod (ArrayList<Object> input) {
// body
}
you can use it only with ArrayList, not LinkedList, but you can allow to use any of List classes on other places where it method is using, it's just your choise, so using an interface can allow it:
List<Object> myMethod (List<Object> input) {
// body
}
In this method arguments you can use any of List classes which you want to use:
List<Object> list = new ArrayList<Object> ();
list.add ("string");
myMethod (list);
CONCLUSION:
Use the interfaces everywhere when it possible, don't restrict you or others to use different methods which they want to use.
I am writing an interface and and its implementation. The interface has a method like
doSomething(String[] strs, Integer[] ints, String msg);
I declared parameters as arrays simply because it will call to an external interface having similar arguments. Some people suggest that doSomething agruments should be util List instead of arrays. But I couldn't find any best practice explains the reason reason why util List is preferable?
Loc
Lists are easier to work with, as they have a richer API, and a variety of implementations. So, the upshot is that it's generally more flexible and maintainable.
Josh Bloch's Effective Java highlights one other reason to prefer Lists: "invariance".
Generics are checked at compile time, so typed lists will actually catch more errors than arrays:
// Fails at runtime!
Object[] objectArray = new Long[1];
objectArray[0] = "I don't fit in"; // Throws ArrayStoreException
// Won't compile!
List<Object> ol = new ArrayList<Long>(); // Incompatible types
ol.add("I don't fit in");
So, in some instances it's actually safer to use Lists over Arrays.
There's more to it than that, but it starts getting difficult to explain. See this link to the relevant section of Effective Java, ch 5: http://java.sun.com/docs/books/effective/generics.pdf
HTH
Basically list is abstract type and it need to be implemented again by any of its family members like ArrayList etc. So there is no much difference in using array and list in regarding performance, both are identical. Only in terms of maintainability we go for List interface and we can implement it for any family of List interface later based on the requirement.Also list provide flexible operations over array.
This falls under maintainability. You will find it very convenient to use the methods prepared for you.
Ok so I know that Set, List and Map are interfaces but what makes the first line of code any better than the second line?
List myArr = new ArrayList();
ArrayList myArr = new ArrayList();
If you use the first form, you are saying all you are ever going to use is the functionality of the List interface - nothing else, especially nothing extra added by any implementation of it. This means you can easily change the implementation used (e.g. just substitute LinkedList for ArrayList in the instantiation), and not worry about it breaking the rest of the code because you might have used something specific to ArrayList.
A useful general principle about types in programming (sometime referred to as the robustness principle) is as follows:
Be liberal about what you accept
Be conservative about what you emit
List is more liberal than ArrayList, since List can be any kind of List implementation e.g. an ArrayList, a LinkedList or FrancosSpecialList. Hence it is a good idea to be liberal and accept any kind of list since you may want to change the implementation later.
The main reason to use ArrayList explicitly as a type (your second case) is if you need to use methods that are specific to ArrayList that are not available through the List interface. In this case a generic List won't work (unless you want to do lots of ugly and confusing casting), so you might as well be explicit and use an ArrayList directly. This has the added bonus of hinting to a reader that specific features of ArrayList are needed.
As you can see from the source of ArrayList here, most of the methods implemented are annotated as #override because all of them that are defined through List interface so, if you are gonna use just basic functionalities (that is what you are gonna do most of the time) the difference won't be any practical one.
The difference will come if someday you will think that the features of the ArrayList are not suitable anymore for your kind of problem and you will need something different (a LinkedList for example). If you declared everything as List but instantiated as ArrayList you will easily switch to new implementation by changing the instantiations to new LinkedList() while in other case you will have to change also all variable declarations.
Using List list = new ArrayList() is more OOP style since you declare that you don't care about the specific implementation of the list, and that you want to discard the static information about the type since you will rely on the interface provided by this kind of collection abstracting from its implementation.