I’m wanting to write a method that I can use to initialise a Map. First cut:
Map map(Object ... o) {for (int i = 0; i < o.length; i+=2){result.put(o[i], o[i+1])}}
Simple, but not type-safe. Using generics, maybe something like:
<TKey, TValue> HashMap<TKey, TValue> map(TKey ... keys, TValue ... values)
but that syntax isn’t supported. So eventually I come to this:
public static <TKey, TValue, TMap extends Map<? super TKey, ? super TValue>> TMap map(TMap map, Pair<? extends TKey, ? extends TValue> ... pairs) { for (Pair<? extends TKey, ? extends TValue> pair: pairs) { map.put(pair.getKey(), pair.getValue()); } return map; } public static <TKey, TValue> HashMap<? super TKey, ? super TValue> map(Pair<? extends TKey, ? extends TValue> ... pairs) { return map(new HashMap<TKey, TValue>(), pairs); } public static <TKey, TValue> Pair<TKey, TValue> pair(TKey key, TValue value) { return new Pair<TKey, TValue>(key, value); } public static final class Pair<TKey, TValue> { private final TKey key; private final TValue value; Pair(TKey key, TValue value) {this.key = key; this.value = value; } public TKey getKey() {return key;} public TValue getValue() {return value;} }
But when I try it out, I need to cast it:
private static final Map<? extends Class<? extends Serializable>, ? super TypeHandler<? extends Serializable > > validCodeTypes = /* (Map<? extends Class<? extends Serializable>, ? super TypeHandler<? extends Serializable >>) */ map( pair(Integer.class, new IntHandler()), pair(Integer.TYPE, new IntHandler()), pair(Character.class, new CharHandler()), pair(Character.TYPE, new CharHandler()), pair(String.class, new StringHandler()) ); private interface TypeHandler<TType extends Serializable> {} private static class CharHandler implements TypeHandler<Character> {} private static class IntHandler implements TypeHandler<Integer> {} private static class StringHandler implements TypeHandler<String> {}
Can anyone tell me how to code my map() methods so that it is entirely general yet doesn’t need to be casted?
To make life easier for yourself, never use a return type that contains wildcards. Wildcard types, in general, are for method parameters only.
So, try this:
I haven’t tested it, but give it a go and see how you fare.
P.S., rather than using a made-up
Pairtype, you may find it easier to useMap.Entry.