First, your code is not type safe. It can throw class cast exception at runtime. You should have
private void saveConcreteDOs(AbstractDO[] theEntities) {
entityMap.put(theEntities.getClass().getComponentType(), theEntities);
}
You may have only homogeneous arrays at runtime, and element[0] has the same type as the array component type. However, there's no way to know that by examing this class alone.
With this corrected code, a super smart compiler can prove that getConcreteDOs()
is type safe. However javac is not that smart. It's required by language spec to throw a warning.
Generally, there is no way to express more sophisticated relations between keys and values in Java. The invariant, that a value is an array whose component type is the key, is only maintained in your head.
Now, look at this non-array version:
private Map<Class<? extends AbstractDO>, AbstractDO> map;
protected <E extends AbstractDO> E getConcreteDOs(Class<E> theType)
{
AbstractDO obj = map.get(theType);
return theType.cast(obj);
}
This has no warning, but it's kind of cheating. Class.cast()
hides the warning for us, that's all.
It doesn't help the array version, there is no T[] castArray(Object[])
in Class<T>
. You can make one method yourself, effectively hide the warning in it.
Or you can do this, but it's really unnecessarily tacky. Don't be afraid of unchecked cast warning if you know what you are doing and you examined carefully your program to ensure type safety.
protected <E extends AbstractDO> E[] getConcreteDOs(Class<E[]> arrayType)
{
AbstractDO[] array = map.get(arrayType.getComponentType());
return arrayType.cast(array);
}
...
X[] array = getConcreteDOs(X[].class);