views:

413

answers:

9

Developing Java, you have always learned that its best to create an ArrayList by using the List interface as the type for the variable the list is stored in. Like this

List<String> myList = new ArrayList<String>();

However, by looking at a lot of the android examples that is included in the bundle, they have created the list by using the Class.

ArrayList<String> myList = new ArrayList<String>();

Is there any reason why this is done? Is it faster, lighter or something to explicitly setting the Class?

+9  A: 

In resource constrained environment like the phones that Android are designed for, it's preferrable to avoid using Interface, since it involves additional virtual function call.

Lie Ryan
This is what I've always heard as an explanation, although, I'd be interested to see the difference in terms of real world performance (from the user's perspective).
Erich Douglass
I agree. There would need to be A LOT of constructor calls for this to make a difference. I would be interested to see a practical application that makes enough calls for there to be a performance benefit. But then again I've never programmed for android...
Daniel Standage
@Daniel Standage: I don't think using explicit type actually affects constructor calls; the "interface tax" (virtual function call) is paid for every calls to member functions. The constructor itself is barely affected. However, I'd agree that it would take actual benchmark to see whether this actually still matters since the latest smartphones bears quite powerful processors with decent amount of memory.
Lie Ryan
This is the official reason from the google docs on saving resources. I would also call it premature optimization. Try to use the list interface as long as possible.
Janusz
@Lie Ryan: Thanks for the clarification.
Daniel Standage
A: 

There's not really much difference, except that in the Android example they are using a much more explicit type. Perhaps there are Android methods that rely on receiving an ArrayList rather than just a List.

supercooldave
A: 

It will not be faster or lighter. One reason you could write something like this is to avoid that later in the code myList is pointing to another implementation of List.

ex:

List<String> myList = new ArrayList<String>();
myList = new Vector<String>();

will compile.

ArrayList<String> myList = new ArrayList<String>();
myList = new Vector<String>();

will not.

Dave
The OP is asking why it's the other way around in most Android examples.
Lie Ryan
+2  A: 

While there may be a performance benefit, it is almost certainly tiny and an example of premature optimization.

A much more likely explanation is that the writer of the examples wants to keep you focussed on the thing he (or she) is trying to teach you. Keeping the variable and the object it references the same type is one less thing to think about. Published code examples is one kind of code when you are pretty sure you will never have to modify it, and in that case it's perfectly fine to use ArrayList as the variable type.

DJClayworth
+12  A: 

I'd recommend to read Performance Myths, which explains which are the advantages and problems of defining a variable as List or ArrayList.

Knife
Great link! They showed that for devices that do not have JIT it is 6% faster to use HashMap directly instead of Map (which is HashMap)
Shervin
And, there used to be a page in the docs that specifically stated that for Android you SHOULD AVOID the interface types (because of course, before the JIT, it was slower). Anyway, that's why you see so many Android examples like that, it was advocated by the documentation until recently.
Charlie Collins
+10  A: 

Personally, I believe that the thing "you have always learned" misses the point. This:

List<String> myList = new ArrayList<String>();

has very little maintenance benefit. If you want to change it to a different implementation, it's still only one line to change if you use the implementation type. However, a totally different matter is this:

public void process(List<String> list) {

Here, using the interface really matters because it allows people who call the method to use different implementations without having to change the method signature (which they may not be able to do).

Michael Borgwardt
I fully agree with that +1
Pascal Thivent
+1 It's time to end this pretense. I attached my explanations.
irreputable
`List myList = new ArrayList()` documents the intent of the myList, in that the code expects to use myList as a `List` and not specifically an `ArrayList`.
Steve Kuo
@steve-kuo Except the code specifically uses an ArrayList, presumably for a good reason. Even if in the rare case that any List would work well, I find it hard to believe that a programmer would find it necessary to point that out explicitly and consciously.
irreputable
I don't think it misses the point, not entirely anyway. It's just that you might use that interface type as a parameter (as you note), or return it, and so on, and in those cases you are much better off using the interface from a flexibility and maintenance standpoint. Now if you're ONLY using it internally, then yeah, but it still doesn't hurt you to just use the interface (and it's a habit).
Charlie Collins
I disagree that List<String> myList = new ArrayList<String>();offers little maintenence benefit. If ArrayList<String> myList = new ArrayList<String>(); is used then the coder of the meethod (or a subsequent coder) might use a method specific to ArrayList, which could be a potential maintenence headache. I agree that it's more important as an argument, though.
DJClayworth
+1  A: 

When compiling code that operates on List<> objects, the compiler must use interface calls, which care more expensive than regular virtual calls on concrete types.

Of course, in a piece of code where the compiler sees the object being instantiated and can prove that something that is declared to be a List<> is always an ArrayList<>, the compiler should be able to just emit a regular call instead of an interface call, but methods which are not inlined and operate on already instantiated objects would not benefit from this optimization.

The ubiquitously used optimization that speeds up virtual calls, namely inline caches (frequently Polymorphic Inline Caching or PIC, not to be confused with Position Independent Code), benefits from the observation that instances of only a single subclass are ever accessed through a variable of a certain declared type. In this scenario, after the code has been running instrumented for a while the JIT can optimistically guess that a List<> object will only ever be an ArrayList<>, generate a trap in case the guess was wrong, and fall through with the ArrayList<> call.

Modern processors execute the check very quickly (because they are superscalar and have good branch prediction) so you don't notice the cost of all those virtual call and single implementation interface calls. But it does make the VM work hard, instrumenting, generating and patching all that code.

For server software running in steady state on HotSpot it's irrelevant but for fast startup on a mobile device it might make a difference - I don't know how good is Google's VM.

A nice article about it by Dr. Cliff Click, Jr. (custom big iron hardware, hotspot-deived VM): http://www.azulsystems.com/blog/cliff-click/2010-04-08-inline-caches-and-call-site-optimization

And of course "inline caching" on wikipedia.

Z.T.
A: 

It is a well-known "Design Principle" about howto make a good design, "program to an interface, not an implementation". Like Michael Borgwardt said, maybe it doesn't care to use this principle with your local variables, but if you have associations between types, then it make sense to program to interfaces rather than implementation to use benefits of OOP. To implement to interfaces rather than impl allows dynamic polymorphic assignments in runtime. say,

interface IAa { say(); }
class A implements IAa { public void say() { .. says A ... } } 
class B implements IAa { public void say() { .. says B ... } } 


class App {

public void someFoo() {
    IAa myA = new A();
    myA.say(); // says A
    myA = new B();  
    myA.say(); // says B

}
...
}

i don't think that, it would be different in Android programming :)

Erhan Bagdemir
+1  A: 

The Interface x = new Implementation() pattern is a popular naive attempt at being abstract.

A variable declaration and initialization statement, Type x = new Constructor();, is definitely part of implementation detail. It's not part of a public API (unless it's public final, but List is mutable so that's inappropriate)

As an implementation detail, who are we trying to fool with this "abstraction"? It's better to keep the type as specific as possible. Is it an array list or a linked list? Should it be thread safe or not? The choice is important for implementation, we carefully chose the specific list impl. Then we declare it as a mere List as if it doesn't matter and we don't care?

The only legitimate reason to declare it as List is I'm too lazy to type. That also covers the argument that if I need to move to another List impl I have one less place to modify.

This reason is legitimate only when the variable scope is small, and we can see all of its usages from one glance. Otherwise, declare the most specific type, so that its performance and semantic characteristics are manifest across all the code that use the variable.

irreputable