Issue
I have some requirements for the heterogeneous generic implementation for different types of Java objects. I can see warnings related to unchecked conversion. Any thought on the below implementation to avoid any runtime exception. Please find the below sample code.
class GenericData<T> {
private final Class<T> type;
private final static Map<Class<?>, GenericData> map = new HashMap<>(); //Warning :: GenericData is a raw type. References to generic type GenericData<T> should be parameterized
public final static <T> GenericData<T> of(Class<T> type) {
return map.putIfAbsent(type, new GenericData<T>(type)); // Warning :: Type safety: The expression of type GenericData needs unchecked conversion to conform to GenericData<T>
}
private GenericData(Class<T> type) {
this.type = type;
}
public final T getDataAfterDefaultValueApplied(T Data, T Body) {
Map<String, Object> defaultMap = getDataMap(Data);
Map<String, Object> dataMap = getDataMap(Body);
defaultMap.putAll(dataMap);
final ObjectMapper mapper = new ObjectMapper();
return mapper.convertValue(defaultMap, type);
}
private Map<String, Object> getDataMap(T data) {
// Demo implementation, ignore this one
return (Map<String, Object>) data;
}
}
Solution
For containers of this kind, an unchecked operation is unavoidable. But you should try to minimize it and further, add a runtime check to ensure type safety:
class GenericData<T> {
private final Class<T> type;
private final static Map<Class<?>, GenericData<?>> map = new HashMap<>();
public final static <T> GenericData<T> of(Class<T> type) {
return map.putIfAbsent(type, new GenericData<>(type)).checkedCast(type);
}
private GenericData(Class<T> type) {
this.type = type;
}
@SuppressWarnings("unchecked")
private <U> GenericData<U> checkedCast(Class<U> clazz) {
if(clazz != this.type) throw new ClassCastException(clazz + " != " + this.type);
return (GenericData<U>)this;
}
// ...
}
Here, the unchecked operations are limited to the checkedCast
method and it’s immediately recognizable to the reader that it has been made safe by an explicit check operation and only the compiler can’t recognize it.
Answered By - Holger
Answer Checked By - Mary Flores (JavaFixing Volunteer)