• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Generics doubt

 
Ranch Hand
Posts: 340
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
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>
Or
List l<? Super String>=new List<? Super String>
Or
List l<?>=newList<?>

Can we ever use add method on such collections that return true?
I mean
l.add(o);
 
Ranch Hand
Posts: 59
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sandy,

This is an excellent tutorial for learning about Generics:
http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf
 
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, you cannot write new List <anything>() because List is an interface.
 
Sandeep Chhabra
Ranch Hand
Posts: 340
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Right Barry
ok..Lets make it:
List l<? extends Object>=new LinkedList<? extends Object>
Or
List l<? Super String>=new LinkedList<? Super String>
Or
List l<?>=new LinkedList<?>
Now Can I say that whenever we use ? in generics, we can never add a new element in that?
Thanks
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 340
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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:
---------------------------------------------
test62.java:7: cannot find symbol
symbol : method add(java.lang.String)
location: interface java.util.List<capture of ?>
l.add("Test");
^
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
Posts: 7729
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
<snip>
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
Posts: 7729
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Ranch Hand
Posts: 220
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.

consider
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
operationU(ls);

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
operationU(List){

}

I'm developing on this approach, so if you find any flaws, kindly feel free to post it or send me a message,
thanks
 
Sandeep Chhabra
Ranch Hand
Posts: 340
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
reply
    Bookmark Topic Watch Topic
  • New Topic