Во-первых, ваш код небезопасен.Он может генерировать исключение приведения класса во время выполнения.У вас должно быть
private void saveConcreteDOs(AbstractDO[] theEntities) {
entityMap.put(<b>theEntities.getClass().getComponentType()</b>, theEntities);
}
У вас могут быть только однородные массивы во время выполнения, и элемент [0] имеет тот же тип, что и тип компонента массива.Тем не менее, нет никакого способа узнать, что, изучая только этот класс.
С этим исправленным кодом супер-умный компилятор может доказать, что getConcreteDOs()
является типобезопасным.Однако, Javac не такой умный.В спецификации языка требуется выдать предупреждение.
Как правило, в Java нет способа выразить более сложные отношения между ключами и значениями.Инвариант, что значение является массивом, тип компонента которого является ключом, поддерживается только в вашей голове.
Теперь посмотрите на эту версию без массива:
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);
}
Это имеетбез предупреждения, но это обманClass.cast()
скрывает предупреждение для нас, вот и все.
Это не помогает версии массива, в 1011 * нет T[] castArray(Object[])
.Вы можете сделать один метод самостоятельно, эффективно скрыв в нем предупреждение.
Или вы можете сделать это, но это действительно излишне липкое.Не бойтесь непроверенного предупреждения, если вы знаете, что делаете, и тщательно изучили свою программу для обеспечения безопасности типов.
protected <E extends AbstractDO> E[] getConcreteDOs(Class<E[]> arrayType)
{
AbstractDO[] array = map.get(arrayType.getComponentType());
return arrayType.cast(array);
}
...
X[] array = getConcreteDOs(X[].class);