I don't really understand your problem. Is this what you're looking for?
class MyClass {
protected static <T> Set<T> SetFactory(int size)
{
return new HashSet<T>(size);
}
protected static <K, V> Map<K, Set<V>> mapFactory(Collection<K> keys)
{
Map<K, Set<V>> result = new HashMap<K, Set<V>>(keys.size());
for (K key : keys)
result.put(key, MyClass.<V>SetFactory(20));
return result;
}
}
Note the explicit type parameter (<V>
) on the generic method invocation.
Update:
I'm probably wrong, but stating there
is no cast seems like semantics to me
- having to put the MyClass. on front seems pretty close to having to
cast. Can you explain the distinction?
A cast would be (Set<V>) SetFactory(20)
, and it would generate a compiler warning about type safety, because with type erasure there is no way to check that the run-time type of the result of the SetFactory
function has a type of V
.
Using a type parameter on the method invocation is much like saying new HashSet<V>()
. When you invoke a constructor of a generic class, you have to specify the type arguments for the constructor. Whenever you invoke a generic method, the type parameters must be specified. Often, these can be inferred from an assignment of the result of the method, or from the method's parameters, but not always.
However, it's not a cast. A cast always performs a type check at run-time. Specifying the generic type as I show here works at compile-time.