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
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)
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.
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
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.
Post by:autobot
I love a woman who dresses in stainless steel ... and carries tiny ads:
a bit of art, as a gift, the permaculture playing cards