I have the following classes:
public interface IDataSource<T> {
public List<T> getData(int numberOfEntries);
}
public class MyDataSource implements IDataSource<MyData> {
public List<MyData> getData(int numberOfEntries) {
...
}
}
public class MyOtherDataSource implements IDataSource<MyOtherData> {
public List<MyOtherData> getData(int numberOfEntries) {
...
}
}
I would like to use a factory that return the correct implementation based on the data type. I wrote the following but I get "Unchecked cast" warnings:
public static <T> IDataSource<T> getDataSource(Class<T> dataType) {
if (dataType.equals(MyData.class)) {
return (IDataSource<T>) new MyDataSource();
} else if (dataType.equals(MyOtherData.class)) {
return (IDataSource<T>) new MyOtherDataSource();
}
return null;
}
Am I doing it wrong? What can I do to get rid of the warnings?
I am not aware of any way to get rid of those warnings without @SuppressWarnings("unchecked")
.
You are passing in a Class
object so T
can be captured. But you are forced to check the Class
at runtime to determine which IDataSource<T>
to return. At this time, type erasure has long since occurred.
At compile time, Java can't be sure of type safety. It can't guarantee that the T
in the Class
at runtime would be the same T
in the IDataSource<T>
returned, so it produces the warning.
This looks like one of those times when you're forced to annotate the method with @SuppressWarnings("unchecked")
to remove the warning. That warning is there for a reason, so it is up to you to provide and ensure type safety. As written, it looks like you have provided type safety.
@SuppressWarnings("unchecked")
public static <T> IDataSource<T> getDataSource(Class<T> dataType) {
You're doing it right, and you should simply suppress the warnings. Factories are one of the tricky areas in generics where you really do need to manually cast to a generic type, and you have to ensure via whatever means that the returned value matches the Class<T>
you pass in. For example, in this case you're hard-coding a couple of IDataSource
implementations, so I would recommend writing unit tests that verify that the types are correct so that if the MyData
implementation changes in an incompatible way, you'll get an error on build.
Just annotate the getDataSource
method with @SuppressWarnings("unchecked")
, and it's always a good idea to add an explanatory comment when suppressing warnings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With