Nathan,

It's a tricky one to be sure.

The problem is that the entrySet() method is returning a
"Set<Map.Entry<capture-of ? extends K, capture-of ? extends V>>",
which is incompatible with the type "Set<Map.Entry<? extends K, ?
extends V>>". It's easier to describe why if I drop the "extends K"
and "extends V" part. So we have "Set<Map.Entry<?, ?>" and
"Set<Map.Entry<capture-of ?, capture-of ?>>".

The first one, "Set<Map.Entry<?, ?>>" is a set of Map.Entries of
different types - ie it is a heterogeneous collection. It could
contain a Map.Entry<Long, Date> and a Map.Entry<String, ResultSet>>
and any other pair of types, all in the same set.

On the other hand, "Set<Map.Entry<capture-of ?, capture-of ?>>" is a
homogenous collection of the same (albeit unknown) pair of types. Eg
it might be a Set<Map.Entry<Long, Date>>, so all of the entries in the
set MUST be Map.Entry<Long, Date>.

In general, even if you could assign this to a local variable without
unchecked type safety warnings, you wouldn't be able to call any
methods on it because the compiler cannot check whether the access is
type-safe. For example you would not be able to call add() because the
Set must contain a specific type, but the compiler doesn't know which
specific type that is!

Regards
Neil

On 5/11/06, Nathan Beyer <[EMAIL PROTECTED]> wrote:
Does someone understand why this works this way? This seems so odd. I know
there are quirks to the generics syntax, but this in an edge I haven't run
into yet. I haven't been able to make this one click in my head yet.

This compiles fine:
        public synchronized void putAll(Map<? extends K,? extends V> map) {
        for (Map.Entry<? extends K,? extends V> entry : map.entrySet()) {
              ...
        }
        }

This won't compile at all:
        public synchronized void putAll(Map<? extends K,? extends V> map) {
        Set<Map.Entry<? extends K, ? extends V>> entries = map.entrySet();
        ...
      }
The error is: Type mismatch: cannot convert from Set<Map.Entry<capture-of ?
extends K,capture-of ? extends V>> to Set<Map.Entry<? extends K,? extends
V>>
The suggested quick fix in Eclipse is "Set<?> entries = ...".

This reports a warning:
        public synchronized void putAll(Map<? extends K,? extends V> map) {
        Map<K,V> map2 = (Map<K,V>)map;
      }
The warning is: Type safety: The cast from Map<capture-of ? extends
K,capture-of ? extends V> to Map<K,V> is actually checking against the
erased type Map
The suggested quick fix in Eclipse is to the annotation:
@SuppressWarnings("unchecked").

-Nathan


> -----Original Message-----
> From: Tim Ellison [mailto:[EMAIL PROTECTED]
> Sent: Wednesday, May 10, 2006 6:59 AM
> To: harmony-dev@incubator.apache.org
> Subject: Thanks Stepan! (was: Re: [jira] Resolved: (HARMONY-454)
> [classlib][luni] java.util.Set generics uplift and related changes)
>
> Stepan Mishura (JIRA) wrote:
> <snip>
> > 2) To avoid casting while-loop was replaced with for-loop. Could you
> review the change?
>
> I was scratching my head about this cast, so I was very pleased to see
> your elegant solution.
>
> I must admit that I don't really understand why the for-loop version is
> inherently different (other than it 'hides' the casting) -- but I've
> learned a new pattern there :-)
>
> Regards,
> Tim
>
> --
>
> Tim Ellison ([EMAIL PROTECTED])
> IBM Java technology centre, UK.
>
>
> ---------------------------------------------------------------------
> Terms of use : http://incubator.apache.org/harmony/mailing.html
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]


---------------------------------------------------------------------
Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




--
Neil Bartlett
Senior Technical Consultant, Integility Ltd
Tel: +44 (0) 20 7043 8328
Fax: +44 (0) 20 7043 8329

LinkedIn Profile: https://www.linkedin.com/in/neilbartlett

Reply via email to