You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@harmony.apache.org by Nathan Beyer <nb...@kc.rr.com> on 2006/06/01 02:08:32 UTC

RE: [classlib] generics puzzler (was: Re: Thanks Stepan! (was: Re: [jira] Resolved: (HARMONY-454) [classlib][luni] java.util.Set generics uplift and related changes))

For anyone interested, I finally figured out the answer to this puzzle.

The following code compiles without error or warning using the new foreach
loop.

for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
	entry.toString();
}

The way to make this work without a compile error or warning and use an
Iterator, you have to declare the Iterator just right.

Iterator<? extends Map.Entry<? extends K, ? extends V>> it =
t.entrySet().iterator();
while(it.hasNext()) {
	Map.Entry<? extends K, ? extends V> entry = it.next();
}

The key is the "? extends" before the Map.Entry declaration.

-Nathan

> -----Original Message-----
> From: Tim Ellison [mailto:t.p.ellison@gmail.com]
> Sent: Thursday, May 11, 2006 3:30 AM
> To: harmony-dev@incubator.apache.org
> Subject: [classlib] generics puzzler (was: Re: Thanks Stepan! (was: Re:
> [jira] Resolved: (HARMONY-454) [classlib][luni] java.util.Set generics
> uplift and related changes))
> 
> But the question remains in my mind whether there is any generic type
> definition you could write that would allow you to cast the  entrySet()
> to a "Set<Map.Entry<capture-of ? extends K, capture-of ? extends V>>"
> equivalent?
> 
> To put it another way, I would expect that
> 	for (Map.Entry<? extends K, ? extends V> entry : map.entrySet())
> 
> should complain that the declaration of 'entry' is not compatible with
> the 'capture-of ? extends K' etc.
> 
> (It's still a useful cheat though)
> 
> Regards,
> Tim
> 
> 
> Neil Bartlett wrote:
> > 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 <nb...@kc.rr.com> 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:t.p.ellison@gmail.com]
> >> > 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 (t.p.ellison@gmail.com)
> >> > IBM Java technology centre, UK.
> >> >
> >> >
> >> > ---------------------------------------------------------------------
> >> > Terms of use : http://incubator.apache.org/harmony/mailing.html
> >> > To unsubscribe, e-mail: harmony-dev-unsubscribe@incubator.apache.org
> >> > For additional commands, e-mail: harmony-dev-
> help@incubator.apache.org
> >>
> >>
> >> ---------------------------------------------------------------------
> >> Terms of use : http://incubator.apache.org/harmony/mailing.html
> >> To unsubscribe, e-mail: harmony-dev-unsubscribe@incubator.apache.org
> >> For additional commands, e-mail: harmony-dev-help@incubator.apache.org
> >>
> >>
> >
> >
> 
> --
> 
> Tim Ellison (t.p.ellison@gmail.com)
> IBM Java technology centre, UK.
> 
> ---------------------------------------------------------------------
> Terms of use : http://incubator.apache.org/harmony/mailing.html
> To unsubscribe, e-mail: harmony-dev-unsubscribe@incubator.apache.org
> For additional commands, e-mail: harmony-dev-help@incubator.apache.org


---------------------------------------------------------------------
Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: harmony-dev-unsubscribe@incubator.apache.org
For additional commands, e-mail: harmony-dev-help@incubator.apache.org