• 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
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Generics Clarification

 
Ranch Hand
Posts: 91
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ranchers,
Below is the piece of code
public static <T> void addandDisp(Collection<T> cs, T t)
{
for (T o : cs)
{
s.add(o);
}
for (T o : cs)
{
System.out.println(o);
}
}

//call 1
List<? super Object> ls1 = new LinkedList<Object>();
addandDisp(ls1,new String());
//call 2
List<? extends Object> ls2 = new LinkedList<Object>();
addandDisp(ls2,new Object());
//call 3
List<Object> ls3 = new LinkedList<Object>();
addandDisp(ls3,new String());
//call 4
List<? super Object> ls4 = new LinkedList<Object>();
addandDisp(ls4,new Object());

Here only 1,3 & 4 works but not 2 ! Can someone help me explain what the compiler expects for this kind of method signature.why doesnt 2 work ?
 
Ranch Hand
Posts: 69
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi there, I may not have the 100% correct answer for this.....

but

List<? extends Object> is the same as List <?>
and you are telling the compiler that there could be anything in this list!
And then you are calling it a collection (of objects that could be anything) and then you are adding to that collection.

The compiler doesn't like you adding to the collection anything that may not be a good idea to add! have a look at page 589 of the K&B book if you have it.

The reason the others work: The List <? super Object> I think is the same as List <Object> because super means "the same as or higher" and there is nothing higher than object! So its ok to add to this!

I hope this helps and I also hope I am right! Feel free to correct!
 
Ranch Hand
Posts: 107
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think the problem here with call 2 is that you've declared a list as follows:


which means you can assign a list of Object or anything that extends Object to ls2 eg.



However, with this flexibility, the JVM restricts what you can do with the list, and one of the restrictions is that you can't add to the list as the JVM cannot be sure what type of object is being added.

The reason for this is that we may assign a list of Dog items to ls2, pass the list to a method that then inadvertently adds Car items. These are all valid Objects but the type safety has now been compromised. What we thought was a list of Dog items has now been corrupted.
 
bernard savary
Ranch Hand
Posts: 91
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Ian & Robert . I can understand why compiler doesnt let us add anything to a collection<? extends class> type. But here I think even if the code in addandDisp method is commented i.e empty method
public static <T> void addandDisp(Collection<T> cs, T t)
{ } the pgm dosnt compile. I am not sure if its got to do something with the second parameter in the method, which is also typed T . When we call
List<? extends Object> ls2 = new LinkedList<Object>();
addandDisp(ls2,new String());
The compiler thinks type of ls2 is not clear because anything upto an object goes here and inside the method addandDisp we may call t = cs.get(1) but again even addandDisp(ls2,new Object()); doesnt work! So I dont really know why it is so ... :roll:
 
Robert Elbourn
Ranch Hand
Posts: 69
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I see what you mean! I have just run it again,

this is my next theory

In this line....public <T> void addandDisp(Collection<T> cs, T t)

Both Ts refer to the same type

but this line addandDisp(ls2,new Object());

is basically saying (at compile time)

addandDisp(<? extends Object>,<Object> ;
or even
addandDisp(<could be any object>,<must be an object> ;

Which doesn't fit the pattern of

public <T> void addandDisp(Collection<(must be )T> cs, (must be )T t)



In Summary I think you are right, its the parameters not the adding!
The generic method is expecting two objects of the same type
We are saying they dont have to be the same type (even though they might be)
The compiler says eek we can't have that you might not be able to fulfill the contracts of that generic class then!!
 
Ranch Hand
Posts: 129
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
when you're using generics methods, you cannot modify the collection that you're using generic when it's subtype.

so. List<?extends Object> ls2 = new LinkedList<Object>();

will make the compiler scream if the generic method that uses this does any modification.

for the other three however, they're the same thing. It's restricted to object types only.
 
Author
Posts: 986
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by bernard savary:
I think even if the code in addandDisp method is commented i.e empty method
public static <T> void addandDisp(Collection<T> cs, T t)
{ } the pgm dosnt compile.



Correct. The body of the method is irrelevant as to whether the syntax of the calling code is ok. Only the signature matters. [In Java, that is. There may be other languages (perhaps ML?) where the body could matter.]

When we call
List<? extends Object> ls2 = new LinkedList<Object>();
addandDisp(ls2,new String());
The compiler thinks type of ls2 is not clear



This is kind of it. I wouldn't say that the type of ls2 is unclear, as it is essentially List<T> where T is a magic invisible type variable. Now we don't know anything about T (except that it is constrained to extend Object, which isn't much of a constraint) but we do know that ls2's add() method takes a parameter of type T. This essentially means we can't ever call ls2.add(anyObject) because there is no way we can demonstrate to the compiler that any given object is actually a T.

For the same reason we can't call addandDisp(ls2, anyObject), though the compiler would allow us call addandDisp(ls2, null) if we wanted to.

[ edit: I originally wrote "perhaps Ada?" but I meant ML, not Ada. ]
[ March 05, 2008: Message edited by: Brian Cole ]
 
bernard savary
Ranch Hand
Posts: 91
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
sorry Brian I cant really follow you from "but we do know that ls2's add() method takes a parameter of type T. This essentially means we can't ever call ls2.add(anyObject) because there is no way we can demonstrate to the compiler that any given object is actually a T..."
Could please elobrate a little more on that .I dont understand why you are talking about List.add(E) method here .
 
Brian Cole
Author
Posts: 986
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by bernard savary:
sorry Brian I cant really follow you from "but we do know that ls2's add() method takes a parameter of type T. This essentially means we can't ever call ls2.add(anyObject) because there is no way we can demonstrate to the compiler that any given object is actually a T..."

Could please elobrate a little more on that .I dont understand why you are talking about List.add(E) method here .



The original question isn't about List.add(), but if you understand why we can't call ls2.add(anyObject) then you should also be able to understand why we can't call addandDisp(ls2, anyObject).

At the risk of confusing things further, let me make a crazy analogy. Let's say I have a cage designed for animals of type T. I hire a security guard and tell him "don't allow anyone to put any animals in there unless you are absolutely sure the animal is of type T. I can't tell you exactly what type T is, but it's some kind of mammal."

Now you come up to the security guard with a River Otter and ask if you can put it in the cage. Now it may be the case that T is indeed River Otter (or perhaps T is Otters in general, encompassing both River Otters and Sea Otters) but the point is the security guard still doesn't know what T is, so he can't allow you to insert the River Otter.

In fact, there's no animal he can allow you to insert, because there's nothing you can do to convince him that the animal you hold is definitely a T. Does this make sense? (the security guard == the java compiler)
 
bernard savary
Ranch Hand
Posts: 91
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks that was cool !
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic