In a library I am developing I have a factory method that looks a bit like:
public <T> T instantiate(Type targetType) {
return ...;
}
I am using a type parameterized method to avoid that users of my library have to cast every time they invoke it (that would be the case if I would have chosen to return Object
).
Is there any reason this is not a good design choice ?.
I do not like that the programmer can invoke my method like:
String s = instantiate(Integer.class);
Which is clearly wrong.
Unfortunately, the method requires a type and not a class, otherwise I could have written something like:
public <T> T instantiate(Class<T> targetClass) {
return ...;
}
2
Java generics simply can’t do what you want it to do, because Type
is not itself parameterized like Class
is, and it can’t be because it also covers primitive types, which cannot be type parameters. You’d probably also run into problems with the lack of covariance. Adding a second Class
parameter is probably the most simple solution.
Java’s type system, especially its generics just aren’t very powerful, at least compared to languages like Haskell. But it’s good enough 99.9% of the time, and I’d rather live with a few edge cases where type safety cannot be guaranteed at compile time than lose myself in esotheric type constructs (there’s already more than enough opportunity in Java for that when you use nested generics with wildcards).
2
I’ve tried to do the same thing quite recently and I got into problems. Take a look at my question here: https://stackoverflow.com/questions/15389994/lazy-class-cast-in-java
Instead, I would add a second parameter to that method, the class object of the type T. Basically, your alternative combined with what you need:
public <T> T instantiate(Type targetType, Class<T> klass) {
return ...;
}