aspose file tools*
The moose likes Java in General and the fly likes generics - incompatible types Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "generics - incompatible types" Watch "generics - incompatible types" New topic
Author

generics - incompatible types

Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
I thought I more or less understand generics, but I don't get why the following doesn't compile:



The error I get is

^

Eclipse "quick fixes" the second line to



which isn't really satisfactory. Is there any better solution?


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
This works:

Can't say I really understand why though.


"I'm not back." - Bill Harding, Twister
Edwin Dalorzo
Ranch Hand

Joined: Dec 31, 2004
Posts: 961
Map.Entry is an interface, hence, Map.entrySet() actually implements a new Map.Entry.

Then, you're a actually receiving <? extends Map.Entry> and not Map.Entry itself.

Actually, reviewing the Tiger source code I discovered that HashMap has static nested class named Entry which hides that declard in the Map interface. This static nested class named Entry implements Map.Entry.

At least that�s what I think.

I had a hard time trying to figure it out, too. If somebody has another reasoning regarding this issue, please post it. I would like to read it.

Best regards,
Edwin Dalorzo.

[ April 11, 2006: Message edited by: Edwin Dalorzo ]
[ April 11, 2006: Message edited by: Edwin Dalorzo ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
But this works fine:

Much nicer. Map.Entry is still an interface, and there's no problem. It's just when we have wildcards that extra ugliness ensues.

I believe this relates to the rules for capture conversion, and specifically to the statement that "Capture conversion is not applied recursively." Capture conversion doesn't apply if the ? is nested within multiple < > braces. So it's necessary to introduce an additional ? within the outermost < >, to allow capture conversion to work.

That's the reasoning according the the JLS rules, I think. But I haven't really absorbed why it's necessary here.
[ April 11, 2006: Message edited by: Jim Yingst ]
Edwin Dalorzo
Ranch Hand

Joined: Dec 31, 2004
Posts: 961
Yeah, now I remember that rule. I have been trying to remember it the whole morning.

I read about these rules in the Java Programming Language Book like a couple of months ago. And I have to confess that I had completely forgotten about it.

Damn, I will have to dust it off out of my library now that I get back home.

I am really having difficulty learning all the oddities of generecy. From time to time I always face something I simply cannot understand, like this.

I think you are probably right, Jim. I will not rest until I can really master this generics stuff.

Thanks!
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Jim Yingst:

I believe this relates to the rules for capture conversion, and specifically to the statement that "Capture conversion is not applied recursively." Capture conversion doesn't apply if the ? is nested within multiple < > braces. So it's necessary to introduce an additional ? within the outermost < >, to allow capture conversion to work.


Yes, this sounds as if it's the problem. And as you, I'm not sure how it works this way - have to think a little bit more about it.

Anyway, thanks for the solution provided above!
Edwin Dalorzo
Ranch Hand

Joined: Dec 31, 2004
Posts: 961
Ok, I have like an hour reading generics stuff. I think Jim was completely right. This is about violating the rules of capture conversion:

From The Java Programming Language, Fourth Edition


[...] you can oly apply capture conversion if the type variable is defined at the top-level of the generic type [...] suppose you have the method:

static <T> void processListOfLists(List<List<T>> list)

and you tried to invoke it with an argument of type List<List<?>>. The capture will not uniquely determine the an element type for the outer list [...]


I did some test of my own this time. I created this generic class:



And then I wrote som code. Note how data type is directly infered. In this case ther is not capture conversion.



However in this second case capture conversion infers "capture of ? super String" as Object:



Then I changed the Rancha class to contain a list of lists, like this:



And repeat the first test again.

This code compiles:



But in the case where capture conversion should be applied, just like inthe previous test, compiling fails: Type mismatch: cannot convert from List<List<capture-of ? super String>> to List<List<? super String>



So, unless once again I am wrong, this should prove you right, Jim.

Best regards,
Edwin Dalorzo.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
But the question remains: *why* does it work this way?
Edwin Dalorzo
Ranch Hand

Joined: Dec 31, 2004
Posts: 961
Well, I cannot be certain, but I believe that capture conversion just applies to the capture (?) and not to the extension mechanism (... extends X).

Capture conversion is an attempt of the compiler to infer the type of the capture.

In order words <? extends List<List<? super String>> is interpreted as
"capture of ? that extends some complex type X". And the complex type X will not be evaluated for capture conversion, because the system can already infer what the type of the capture is, which in this case is X, whatever it means (in this case List<List<? super String>>.

I ran some tests and concept survided.

At least that's what I think. However I still have a couple of questions. If I can figure out something else, I will post it later.



Best regards,
Edwin Dalorzo.

[ April 12, 2006: Message edited by: Edwin Dalorzo ]
[ April 12, 2006: Message edited by: Edwin Dalorzo ]
Edwin Dalorzo
Ranch Hand

Joined: Dec 31, 2004
Posts: 961
Look at this variation of the same case.

In this example I cannot add an element to the list of lists. It is a violtion of the same rule about nested type parameters.

The outer list is required that all the elements are of the same type. In this case capture conversion is impossible. This happens because capture conversion cannot infer the actual type of the outer List when the actual type of the inner list is List<? super String>

That means that the outer list could contain many different kind of lists, like a List<Object>, a List<CharSequence> or a List<String>.

However, capture conversion cannot assume any of this types, because it would make the outter list incompatible for all the others.

In other words if capture conversion interprets List<List<? super String>> as List<List<Object>> then we could not add a List<String> or a List<CharSequence> to the outer List.

Hence, capture conversion fails because it is incapable of assigning a compatible type with all posible lists to the outer List



The truth is that I have some difficulty assimilating this rules.

Regards,
Edwin Dalorzo
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14266
    
  21

OK, I didn't dive into the details of this question, but you might find an answer in Angelika Langer's Java Generics FAQ.


Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 8 API documentation
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Edwin, you cant add anything to a list of unknown type. Even if the type is narrowed down. So its not surprising that you can't to the list. Furthermore, that is not a 'collection' thing. That applies to any objects methods if the object is referred to by a wildcard.

I'm struggling with this question. Was there a consensus reached on this one? I can't find any solid answers on google or in any FAQs either.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: generics - incompatible types