Java: Работа с универсальными элементами и картами без приведения / @SuppressWarnings
Теперь я сталкивался с этой проблемой несколько раз и всегда решал ее с помощью @SuppressWarnings
аннотаций.
Соответствующие интерфейсы / абстрактные классы:
public abstract class Data { }
public interface DataOperations {
boolean isValid();
}
public interface DataOperationsFactory<T extends Data> {
Class<T> getDataClass();
DataOperations getOperations(T data);
}
Пример реализации:
public class DataImpl1 extends Data {
public String foo;
}
public class DataImpl1Operations implements DataOperations {
private DataImpl1 data;
public DataImpl1Operations(DataImpl1 data) {
this.data = data;
}
public boolean isValid() {
return data.foo != null;
}
}
public class DataImpl1OperationsFactory extends DataOperationsFactory<DataImpl1> {
public Class<DataImpl1> getDataClass() {
return DataImpl1.class;
}
DataOperations getOperations(DataImpl1 data) {
return new DataImpl1Operations(data);
}
}
Используя этот шаблон, я могу решить, нужно ли мне создавать new DataImpl1Operations
каждый раз. Или, может быть, использовать final static NO_OP
реализация или что у тебя.
Код:
Теперь я хотел бы поместить все эти заводы в Map<Class<T>, DataOperationsFactory<T>>
(конструктор). А потом прочитайте из него (getOps
метод).
public class Test {
Map<Class<?>, DataOperationsFactory<?>> map;
public Test(List<DataOperationsFactory<?>> fs) {
for(DataOperationsFactory<?> f : fs) {
map.put(f.getDataClass(), f);
}
}
@SuppressWarnings("unchecked")
public <T extends Data> DataOperations getOps(T data) {
// --> Here I need to do an unchecked cast <--
DataOperationsFactory<? super T> f =
(DataOperationsFactory<? super T>) map.get(data.getClass());
return f.getOperations(data);
}
}
Есть ли способ сделать это без неконтролируемого кастинга?
1 ответ
Решение
Вы можете делегировать закрытому методу, который захватывает тип, так что его можно использовать для надежного приведения к правильному подклассу Data:
Map<Class<?>, DataOperationsFactory<?>> map;
// Unchanged
public Test(List<DataOperationsFactory<?>> fs) {
for(DataOperationsFactory<?> f : fs) {
map.put(f.getDataClass(), f);
}
}
public DataOperations getOps(Data data) {
DataOperationsFactory<?> f = map.get(data.getClass());
return getOperations(f, data);
}
private static <T extends Data> DataOperations getOperations(DataOperationsFactory<T> f,
Data data) {
return f.getOperations(f.getDataClass().cast(data));
}