tags:

views:

379

answers:

8
+5  Q: 

Java Generics

Can someone explained, as detailed as possible, the differences between the following types?

List

List<Object>

List<?>

Can I get an answer, not a link?

Let me make this more specific.

When would I want to use

public void CanYouGiveMeAnAnswer( List l ){}

?

When would I want to use

public void CanYouGiveMeAnAnswer( List<Object> l ){}

?

When would I want to use

public void CanYouGiveMeAnAnswer( List<?> l ){}

?

+8  A: 

I refer you to the excellent Java Generics tutorial, and the "advanced" Generics tutorial, both available from Sun Microsystems. Another great resource is the Java Generics and Collections book.

Rob
Sometimes people would like to hear it explained in a different way.
Joe Philllips
Sometimes people would benefit from taking the time to learn their language, rather than expecting people to spoon-feed back-of-a-fag-packet answers, especially for fundamentals which require a bit more than three lines of explanation.
Rob
@Rob If I wanted Sun's answer to my question, I would have went to there site, I want a spoon-feed back-of-a-fag-packet stackoverflow answer.
ForYourOwnGood
You might like having a quick and dirty answer, but another visitor might appreciate having a link to a more comprehensive resource.
Rob
Ok, but its my question, I just wanted a quick and dirty answer, don't be so sensitive about your link.
ForYourOwnGood
Ultimately, while you may have asked the question, the objective of the site is for that question to become a more general-purpose reference resource for future visitors. I posted a link to the two tutorials because they comprehensively explain a fairly complex subject.
Rob
(Continued) Therefore, you shouldn't feel that you "own" the question in any editorial sense. I'm surprised that this exchange is taking place.
Rob
Robert! Stop! Your not getting the last word on this one. I dont care what the object of the site is, the objective of my question is to get a answer with no link.
ForYourOwnGood
I think the community will decide what's the best way to answer this question.
pek
NOTE TO ALL :As a result of this disagrement between ForYourOwnGood and Rob, Rob went a voted down 7 of ForYourOwnGood answers, so if you disagree with Rob on any issue, be prepared to lose some points.
ForYourOwnGood
Probably he thought that was for your own good. :-)
OscarRyz
A: 

To complement the tutorials mentioned by Rob, here's a wikibook explaining the topic:
http://en.wikibooks.org/wiki/Java_Programming/Generics


Edit:

  1. No restrictions on type of items in list

  2. Items in list must extend Object

  3. Wildcard used by itself, so it matches anything

Would it be naive of me to conclude at this point that there's hardly any/no difference at all?

Tim
+1  A: 

Simplest explanation which is not "RTFM":

List

Will generate lots of compiler warnings, but is mostly equivalent to:

List<Object>

While:

List<?>

basically means its something generic, but you don't know what the generic type is. Its great for getting rid of compiler warnings when you cant modify the return types of other things that just returned List. Its much more useful in the form:

List<? extends SomeOtherThing>
John Gardner
+2  A: 

The shortest possible explanation is: The second item is a list that can hold any type, and you can add objects to it:

List<Object>

The first item you list is treated as essentially equivalent to this, except you will get compiler warnings because it is a "raw type".

List

The third is a list that can hold any type, but you cannot add anything to it:

List<?>

Basically, you use the second form (List<Object>) when you truly have a list that can contain any object and you want to be able to add elements to the list. You use the third form (List<?>)when you receive the list as a method return value and you will iterate over the list but never add anything to it Never use the first form (List) in new code compiling under Java 5 or later.

Eddie
If you're going to vote this down, please at least do the courtesy of explaining what you find objectionable.
Eddie
+1  A: 

I'd put it this way: While List and List<Object> can contain any type of objects, List<?> contains elements of an unknown type, but once that type is captured, it can only contain elements of that type. Which is why it is the only type safe variant of those three, and therefore generally preferable.

Fabian Steeg
+3  A: 

In my own simple terms:

List

Would declare an ordinary collection, can hold any type, and will always return Object.

List<Object>

Will create a list that can hold any type of object, but can only get assigned a another List<Object>

For instance this doesn't work;

List<Object> l = new ArrayList<String>();

Of course you can add anything but only can pull Object.

List<Object> l = new ArrayList<Object>();

l.add( new Employee() );
l.add( new String() );

Object o = l.get( 0 );
Object o2 = l.get( 1 );

Finally

List<?>

Will let you assign any type, including

List <?> l = new ArrayList(); 
List <?> l2 = new ArrayList<String>();

This would be called collection of unknown and since the common denominator of unknown is Object you will be able to fetch Objects ( a coincidence )

The importance of unknown comes when its used with subclassing:

List<? extends Collection> l = new ArrayList<TreeSet>(); // compiles

List<? extends Collection> l = new ArrayList<String>(); // doesn't,
// because String is not part of *Collection* inheritance tree.

I hope using Collection as the type doesn't create confusion, that was the only tree that came to my mind.

The difference here, is that l is a collection of unknow that belongs to the Collection hierarchy.

OscarRyz
Raw Collection isn't a great example...
Tom Hawtin - tackline
@Tom: I agree, but I couldn't think in a more familiar hierarchy than that! :) Feel free edit it.
OscarRyz
A: 

When would I want to use

public void CanYouGiveMeAnAnswer( List l ){}

When you cant to do all the casting your self.

When would I want to use

public void CanYouGiveMeAnAnswer( List l<Object> ){}

When you want to restrict the type of the List. For instance, this would be an invalid argument.

 new ArrayList<String>();

When would I want to use

public void CanYouGiveMeAnAnswer( List l<?> ){}

Mostly never.

OscarRyz
+3  A: 

As the other posts have noted, you're asking about a java feature called generics. In C++, this is called templates. The java beasties are far tamer to deal with.

Let me answer your questions functionally (if that's not a naughty word for OO discussions).

Before generics, you had good old concrete classes like Vector.

Vector V = new Vector();

Vectors hold any old object you give them.

V.add("This is an element");
V.add(new Interger(2));
v.add(new Hashtable());

However, they do this by casting everything you give it into an Object (the root of all java classes). That's OK until you attempt to retrieve the values stored in your Vector. When you do, you need to cast the value back into the original class (if you want to do anything meaningful with it).

String s = (String) v.get(0);
Integer i = (Integer) v.get(1);
Hashtable h = (Hashtable) v.get(2);

Casting gets pretty old fast. More than that, the compiler whines at you about unchecked casts. For a vivid example of this, use the XML-RPC library from Apache (version 2 anyway). The most important problem with this is that consumers of your Vector have to know the exact class of its values at compile time in order to cast correctly. In cases where the producer of the Vector and the consumer are completely isolated from each other, this can be a fatal issue.

Enter generics. Generics attempt to create strongly typed classes to do generic operations.

ArrayList<String> aList = new ArrayList<String>();
aList.add("One);
System.out.println("Got one: " + aList.get(0)); // no cast needed

Now, if you take a look at the infamous gang of four's /Design Patterns/ book, you'll notice that there is some wisdom in divorcing variables from their implementing class. It's better to think of contracts rather than implementation. So, you might say that all List objects do the same things: add(), get(), size(), etc. However, there are many implementations of List operations that may choose to obey the contract in various ways (e.g. ArrayList). However, the type of data these object deal with is left as a runtime consideration to you, the user of the generic class. Put it all together and you'll see the following line of code very frequently:

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

You should read that as "L is a kind of List that deals with String objects". When you start dealing with Factory classes, it is critical to deal with contracts rather than specific implementations. Factories produce objects of various types at runtime.

Using generics is pretty easy (most of the time). However, one awful day you may decide you want to implement a generic class. Perhaps you've thought of a great new List implementation. When you define that class, you use as a placeholder for the kind of object that will be manipulated by the methods. If you're confused, use the generic classes for List until you're comfortable. Then, you can dive into the implementation with a bit more confidence. Or you can look at the source code for the various List classes that ship with the JRE. Open source is great that way.

Cheers.

jjohn