Re: generics:< ? >vs.< T >
On 03/10/2011 07:01 AM, Lew wrote:
Robert Klemme wrote:
Well, yes that explains why it's a syntax error. What I rather meant (and
should have phrased better): what is the reasoning to forbid "super"
here and
allow only the other direction. On first glance both variants (A
extends B and
B super A) seem equivalent. Am I missing something or is this just an
arbitrary restriction?
I'm sure I don't know. I suppose it does keep things simpler.
Probably. But in my case I found it irritating that I have to place V2
left of V1 in the type declaration although V2 is right of V1 in
argument list.
But for the type of thing that you cited upthread, just a <T> is usually
better than a bounded wildcard type. Unlike types themselves, where the
advice is to generalize the declared type, for generic type parameters
it's often better to specify.
Hmm... Interesting point of view. I'll have to ponder that. My
generic - err - general position on this is to make type parameters as
general as possible. And I apply it also to generic parameters of
methods even though I readily admit that they make things a bit
complicated at times (complicated at least for the implementer, but
since I like puzzles like this it doesn't puzzle me too much). If
things get too complicated for the user of such a method I'd
definitively rethink the approach. There you have another rule of thumb
of mine: easy of use is more important than ease of writing (i.e.
interface matters).
In lieu of 'Map<? super String, V>', a 'Map<String, V>' would be easier
to work with. You have to weigh what the extra assertion buys you. Given
that 'toString()' is ubiquitous, not much. But it might be worth it -
that's the decision the designer makes.
OTOH, you need the 'extends' in another example:
<sscce source="GenericFooferol.java">
package eegee;
import java.util.Map;
/** GenericFooferol. */
public class GenericFooferol
:-))
{
/**
* Copy a {@code Map}.
* @param <T> target value type.
* @param <S> source value type, must be a subtype of {@code T}.
* @param source {@code Map} to copy.
* @param target {@code Map} into which to copy.
* @return Map {@code <String, T>} target map.
*/
public static <T, S extends T> Map <String, T> copy(
Map <?, S> source, Map <String, T> target )
{
if ( source == null || target == null )
{
throw new IllegalArgumentException( "copy(): null argument" );
}
for ( Map.Entry <?, S> entry : source.entrySet() )
{
target.put( entry.getKey().toString(), entry.getValue() );
I'd rather
target.put( String.valueOf(entry.getKey()), entry.getValue() );
or
final Object key = entry.getKey();
target.put( key == null ? null : key.toString(), entry.getValue() );
NPE is such an ugly way to terminate a program. :-)
}
return target;
}
private GenericFooferol(){}
}
</sscce>
Kind regards
robert