Hey, slow down a second! It's true? No no! All you have done is establish that the class corresponding to the name of the past is both Runnable and Enum , and not that it is actually T You have only confirmed the boundaries. Imagine that we had classes T1 and T2 :
package foo; public enum T1 implements Runnable { ; @Override public void run() { } } package foo; public enum T2 implements Runnable { ; @Override public void run() { } }
Then this works fine, but is obviously not type safe:
Example<T1> example = new Example<T1>("foo.T2"); Class<T1> t1Clazz = example.t;
This is also not a problem of several borders. You will have the same problem with only one border.
As @ sp00m mentions, the real solution is likely to pass here Class<T> .
Edit
If, on the other hand, T was only required internally (that is, to indicate multiple boundaries) and should not actually be displayed, then another option would be to maintain the class in two separate references. For instance:
Class<? extends Runnable> runnableClass; Class<? extends Enum> enumClass; Example(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class<?> clazz = Class.forName(className); runnableClass = clazz.asSubclass(Runnable.class); enumClass = clazz.asSubclass(Enum.class); }
This is because without a type parameter there are very few circumstances where you could actually use the knowledge that it is Enum and Runnable at the same time. If you create an instance of a class, you need to assign it to a variable / field of type Runnable or Enum ; you cannot get around both.
source share