I have searched for my use case and found some interesting answers but they are not as suitable as i need. What would the appropriate way to do this:
@SuppressWarnings("unchecked")
public <T> T newInstance(String name) throws ClassCastException, InstantiationException, IllegalAccessException, ClassNotFoundException {
return (T) loadClass(name).newInstance();
}
or a little different:
public <T> T newInstance(String name, Class<T> c) throws ClassCastException, InstantiationException, IllegalAccessException, ClassNotFoundException {
return c.cast(loadClass(name).newInstance());
}
I think that both methods do the same. From my point of view method 1 is better because of less parameters. Boths throw a ClassCastException
which will be fine for me. Truly, the @SuppressWarnings("unchecked")
annotation is not nice.
Can someone tell me if there are any advantages for one method towards the other?
Edit: Jon Skeet's answer is correct. The following snippet can provide additional clarification.
public class Test {
public static void main(String[] args) {
Object o = new Object();
// Exception at c.cast(o)
Test.<String>realCast(o, String.class);
}
private static <T> T realCast(Object o, Class<T> c) {
return c.cast(o);
}
}
Using realCast()
produces an Exception when o
can't be cast to c
. In comparison to that fakeCast()
only gives a promise that the method's result is type of T
.
I think that both methods do the same.
No, they don't. Because at execution time, the first code doesn't know the type of T
due to type erasure. That means the cast basically does nothing within the method. The calling code might implicitly cast to whatever T
it is specifying, but if the caller is another generic method (with the T
used here as another type parameter), even that wouldn't want.
Here's a simple example of that:
public class Test {
public static void main(String[] args) {
Object o = new Object();
// No exception
Test.<String>fakeCast(o);
// Exception at the point of assignment:
// the code is effectively String x = (String) ...;
String x = Test.<String>fakeCast(o);
}
private static <T> T fakeCast(Object o) {
return (T) o;
}
}
The second code knows the type of T
in the form of Class<T>
, so it can perform a real cast at execution time, at exactly the point you're performing it.
See more on this question at Stackoverflow