Hi all,
I have some trouble understanding generics.
if i have a method like :
public void checkGeneric(List<? super String> st){
st.add(new Object()); // Error
}
If i try to add a object to this list i get following error:
The method add(capture#2-of ? super String) in the type List<capture#2-of ? super String> is not applicable for
the arguments (Object)
But according to my understanding with <? super String> any String or supertype of String (i.e. Object) should be acceptable.
Can anyone help me to understand this?
Thanks in advance
I have read the chapter but i can't find the place where it says <? Super someclass> restricts you to add Object.
And yes Himalay st.add("Anything");
works fine but if try to add st.add(new Object()) it doesn't work..
Himalay Majumdar
Ranch Hand
Joined: Sep 28, 2008
Posts: 324
posted
0
Same here. After Deepak said I went through K&B generics section once more, but cud not find an answer. May be its hiding in some context.
Lets wait for someone to enlighten us on this.
Jeena Jeen
Ranch Hand
Joined: Feb 11, 2009
Posts: 47
posted
0
I found something on some other web site that says that its not allowed since String is final so you can not add a new Object() But i don't understand what does it mean? I know that string is immutable and is final but then why can we do st.add("anything") but st.add(new Object()) is not working.
The parameter of this method is "st" and it's reference type is "List<? super String>". What does it mean? Yes, it says "ANY super class of String". But keep in mind that it is not saying that you can pass any super type of String to the add(-) method of st. The only thing what it is saying is the VALUE object for this variable (method argument) CAN be either String or a super-type of it. Let's see a simple example.
Given the statement below:
Accodring to the generic declaration shown above, you can INSTANTIATE the variable st, with any super type of String, as the generic-argument. For an example:
All of the above instantiations are correct, because Object and Serializable are the super type of String, (and String is the same type, so it also can be used).
Now the question is, what can you pass to the add(-) method?
Think about it. The compiler don't know, what will be the instantiation generic type (right side) at the compile time. It can be either String, Object, or Serializable, .... as I shown above.
The key point you have to keep in mind again and again, is, the COMPILER don't know about the INSTANTIATION generic type exactly. The compiler know that it can be ANY super class of String. But it does not know what it is exactly. Because the Java compilation process always deals with the reference type only. (Think about it. You can specify so many instantiations for a one reference variable within a loop, or in a nested if condition. Thus compiler cannot track them).
The argument you have passed to the st.add(-) method, MUST be same or a super class of the INSTANTIATION generic type. But as I described above, the compiler doesn't know, about the INSTANTIATION Generic type exactly. It knows about the reference generic type only (i.e. List<? super String>).
Now, if you attempt to pass an "Object" instance to the add(-) method, the compiler will not permit you to do so. Because as I said, the compiler doesn't know about the instantiation generic type, and the compiler knows that passing an "Object" instance MAY BE a problem at runtime if the instantiation generic-type is NOT Object. Same way, the compiler knows that passing a Serializable (implemented) instance MAY BE a problem at runtime if the instantiation generic-type is NOT either Serializable or a super-type of it. In these cases, the compiler gives an error, as Jeena mentioned in his/her first post in this topic.
But, what if we are passing a "String" instance to the add(-) method? In this case, it WILL NOT BE a problem at runtime, even if the instantiation generic type is either String, Object, or Serializable. Because Object and Serializable are the super type of String. In this case, it will compile successfully.
Also, imagine that SubString is a sub class of String (even though it is not possible to extend from String, as String is a final class), In this case you can pass a SubString instance to the add(-) method, by applying the above theory.
Now we can say, if the generic type of the REFERENCE is List<? super X>, we can pass either X or any SUB class of the X to the add(-) method. But you can NOT pass a SUPER class of X.
Try to apply the above theory, when the REFERENCE generic type is List<? extends Number>
Well ... Devaka was quicker and gave such a explanation that I have to quit (after writing half of my post ... ) But I still have a trump: generics unveiled
Himalay Majumdar
Ranch Hand
Joined: Sep 28, 2008
Posts: 324
posted
0
Exactly Devaka..I just thought about it.
Thanks Devaka for your insight on this. Feel good now. If you can reply to my previous post today..i will be much happier