views:

436

answers:

6

This is a real beginner question (I'm still learning the Java basics).

I can (sort of) understand why methods would return a List<String> rather than an ArrayList<String>, or why they would accept a List parameter rather than an ArrayList. If it makes no difference to the method (i.e., if no special methods from ArrayList are required), this would make the method more flexible, and easier to use for callers. The same thing goes for other collection types, like Set or Map.

What I don't understand: it appears to be common practice to create local variables like this:

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

While this form is less frequent:

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

What's the advantage here?

All I can see is a minor disadvantage: a separate "import" line for java.util.List has to be added. Technically, "import java.util.*" could be used, but I don't see that very often either, probably because the "import" lines are added automatically by some IDE.

+1  A: 

if later you want to change implementation of the list and use for example LinkedList(maybe for better performance) you dont have to change the whole code(and API if its library). if order doesnt matter you should return Collection so later on you can easily change it to Set if you would need items to be sorted.

01
"why methods would return a List<String> rather than an ArrayList<String>" <- so its API ;)
01
+1  A: 

The best explanation I can come up with (because I don't program in Java as frequently as in other languages) is that it make it easier to change the "back-end" list type while maintaining the same code/interface everything else is relying on. If you declare it as a more specific type first, then later decide you want a different kind... if something happens to use an ArrayList-specific method, that's extra work.

Of course, if you actually need ArrayList-specific behavior, you'd go with the specific variable type instead.

Twisol
+11  A: 

When you read

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

you get the idea that all you care about is being a List<String> and you put less emphasis on the actual implementation. Also, you restrict yourself to members declared by List<String> and not the particular implementation. You don't care if your data is stored in a linear array or some fancy data structure, as long as it looks like a List<String>.

On the other hand, reading the second line gives you the idea that the code cares about the variable being ArrayList<String>. By writing this, you are implicitly saying (to future readers) that you shouldn't blindly change actual object type because the rest of the code relies on the fact that it is really an ArrayList<String>.

Mehrdad Afshari
This is abstractophilia. The efficiencies of one implementation vs. another depend on the code that _uses_ the variable: I can't see that I would ever want anything but a tight coupling between the two.
Ben M
"I can't see that I would ever want anything but a tight coupling between the two": Isn't the whole concept of interfaces based on the fact that you actually **want** loose coupling?
Mehrdad Afshari
Of course. But when would you want loose coupling between the work of a function and its local variables? Especially when selecting a collection implementation, since collections are so often optimized for specific situations.
Ben M
One reason to desire loose coupling to the local variables is when the local is exposed. In other words it is generally better to return a List than an ArrayList. Declaring the variable as a List encourages this.
Michael Rutherfurd
+4  A: 

Using the interface allows you to quickly change the underlying implementation of the List/Map/Set/etc.

It's not about saving keystrokes, it's about changing implementation quickly. Ideally, you shouldn't be exposing the underlying specific methods of the implementation and just use the interface required.

Mike Cornell
+2  A: 

I would suggest thinking about this from the other end around. Usually you want a List or a Set or any other Collection type - and you really do not care in your code how exactly this is implemented. Hence your code just works with a List and do whatever it needs to do (also phrased as "always code to interfaces").

When you create the List, you need to decide what actual implementation you want. For most purposes ArrayList is "good enough", but your code really doesn't care. By sticking to using the interface you convey this to the future reader.

For instance I have a habit of having debug code in my main method which dumps the system properties to System.out - it is usually much nicer to have them sorted. The easiest way is to simply let "Map map = new TreeMap(properties);" and THEN iterate through them, as TreeMap returns the keys sorted.

When you learn more about Java, you will also see that interfaces are very helpful in testing and mocking, since you can create objects with behaviour specified at runtime conforming to a given interface. An advanced (but simple) example can be seen at http://www.exampledepot.com/egs/java.lang.reflect/ProxyClass.html

Thorbjørn Ravn Andersen
A: 

Basically this comes from people who have to run large projects, possibly other reasons - you hear it all the time. Why, I don't actually know. If you have need of an array list, or Hash Map or Hash Set or whatever else I see no point in eliminating methods by casting to an interface.

Let us say for example, recently I learned how to use and implemented HashSet as a principle data structure. Suppose, for whatever reason, I went to work on a team. Would not that person need to know that the data was keyed on hashing approaches rather than being ordered by some basis? The back-end approach noted by Twisol works in C/C++ where you can expose the headers and sell a library thus, if someone knows how to do that in Java I would imagine they would use JNI - at which point is seems simpler to me to use C/C++ where you can expose the headers and build libs using established tools for that purpose.

By the time you can get someone who can install a jar file in the extensions dir it would seem to me that entity could be jus short steps away - I dropped several crypto libs in the extensions directory, that was handy, but I would really like to see a clear, concise basis elucidated. I imagine they do that all the time.

At this point it sounds to me like classic obfuscation, but beware: You have some coding to do before the issue is of consequence.

Nicholas Jordan