This week's book giveaway is in the Android forum.
We're giving away four copies of Head First Android and have Dawn & David Griffiths on-line!
See this thread for details.
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Generics doubt Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login

Win a copy of Head First Android this week in the Android forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Generics doubt" Watch "Generics doubt" New topic

Generics doubt

Sandeep Chhabra
Ranch Hand

Joined: Aug 28, 2005
Posts: 340
I want to konw that is it true that we cannot add any element to a Collection whose generic signature is like this:

List l<? extends Object>=new List<? extends Object>
List l<? Super String>=new List<? Super String>
List l<?>=newList<?>

Can we ever use add method on such collections that return true?
I mean

Regards<br />Sandy<br />[SCJP 5.0 - 75%]<br />[SCWCD 1.4 - 85%]<br />------------------<br />Tiger, Tiger burning bright,<br />Like a geek who works all night,<br />What new-fangled bit or byte,<br />Could ease the hacker's weary plight?
Sara Olsen
Ranch Hand

Joined: Oct 12, 2005
Posts: 59

This is an excellent tutorial for learning about Generics:
Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729
Well, you cannot write new List <anything>() because List is an interface.

Ask a Meaningful Question and HowToAskQuestionsOnJavaRanch
Getting someone to think and try something out is much more useful than just telling them the answer.
Sandeep Chhabra
Ranch Hand

Joined: Aug 28, 2005
Posts: 340
Right Barry
ok..Lets make it:
List l<? extends Object>=new LinkedList<? extends Object>
List l<? Super String>=new LinkedList<? Super String>
List l<?>=new LinkedList<?>
Now Can I say that whenever we use ? in generics, we can never add a new element in that?
Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729
You cannot do any of those either, you cannot instantate a class with a wildcard actual type parameter. So new LinkedList<?> is a nono, for example.
Sandeep Chhabra
Ranch Hand

Joined: Aug 28, 2005
Posts: 340
Ok Barry Again My mistake.
Have a look at this code:

(I hope this is fine now)

So this code give me the following error:
--------------------------------------------- cannot find symbol
symbol : method add(java.lang.String)
location: interface java.util.List<capture of ?>
1 error

So shall I infer that we CANNOT add any element if a Collection is declared with '?' (but may be instantiated with some object)

Thanks for correcting
Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729
With Eclipse 3.1.1 I get the compilation error: "The method add(capture-of ?) in the type List<capture-of ?> is not applicable for the arguments (String)" for the add line. Sort of gobbledegook message, isn't it?

However, in section 11.4 of "The Java programming Language, 4th Edition" it says:

Wildcards represent an unknown type, but whenever a variable that has a wildcard type is used, the compiler must treat it as having some specific type so that it can check for correct usage. This specific (but still unknown) type is referred to as the capture of the wildcard. The place you will most commonly come across the capture of a wildcard is in the error messages the compiler produces when you use a parameterized type the wrong way. For example, recall the incorrect attempt to add a String object to a queue accessed through an unbounded wildcard reference:

SingleLinkQueue<?> strings =
new SingleLinkQueue<String>();
strings.add("Hello"); // INVALID: won't compile

The error message this produced from the compiler we used was:

add(capture of ?) in SingleLinkQueue<capture of ?> cannot be applied to (java.lang.String)

This is telling us that when the wildcard reference strings is used, the type of queue is SingleLinkQueue<captureof ?>, so the type of the parameter to add is also "captureof ?". Because String is not compatible with "captureof ?" the call is not allowed.
If a wildcard is always represented by its capture, it would seem that once you have a wildcard type you can only use it wherever a wildcard type is expected. Indeed this is a basic rule that ensures the integrity of the type system.
Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729
Take a look at this method:

If this compiled (it gives the same compile error as above), then we could call the method like this:

and, on some days, end up with the wrong kind of element in the list myList.
[ October 13, 2005: Message edited by: Barry Gaunt ]
Akshay Kiran
Ranch Hand

Joined: Aug 18, 2005
Posts: 220
One easy way (I think) to learn this is by seeing if the code can be misused in any way or not i.e if there is a possibility that the reference of the generic type can allow type unsafe operations, then it is probably not correct.

List<?> list= new LinkedList<String>();

now just consider what types of operations might breach the type homogenity.
remember, when we have something like this, we must consider the case where nothing about the reference can be known at "compile" time.

so, the best thing to do is, to see what might happen when the reference is passed as an argument-

so assume we have

List<String> ls==....//whatever it is, we're not concerned
and then we call

and we have
void operationU(List<?> lu){
//area 1

now given the above,
lets see what are the type-safe operations possible in "area 1"

Q1. Can we lu.add("hi"); ?
A. If we could, then it would be possible to do lu.add(new Integer(4)); also
which would clearly break the type homogenity. wouldn't it?
therefore, we can conclude that lu.add(/*anything*/) is not permissible

Q2. Can we lu.get(1)?
A. why not? is there any way it tampers with the type of data in lu?

so, the conclusion I usually get to, is that with generic types which are the captures os ? i.e Collection<?> etc, only non-destructive operations are permitted, i.e the no data is modified in the reference, only accessing is permitted. Atleast, thats the way I work

You may now ask, why
if it were
void operationU(List <? extends A> les){
//area 2
les.add(/*some object passable as A*/); is permitted?
Simple, the compiler treats les as List of "A" objects, so even if you put an object of B extends A, it will treat it as an object of A, and not B

but also keep in mind that, after type erasure, both the versions of operationU will look like this


I'm developing on this approach, so if you find any flaws, kindly feel free to post it or send me a message,

"It's not enough that we do our best; sometimes we have to do<br />what's required."<br /> <br />-- Sir Winston Churchill
Sandeep Chhabra
Ranch Hand

Joined: Aug 28, 2005
Posts: 340
Thanks for such an informative explination Akshay.

So I think I should conclude wherever I find a collection declared as captures of ? that means that the Collection is read only..or in other words calling add will not be safe on such a generic collection.

Fine I think.
I agree. Here's the link:
subject: Generics doubt
It's not a secret anymore!