.AsSubclass class with several limited types and uncontrolled execution

I have a class that is generated with type <T extends Enum<T> & Runnable> . I have a member variable Class<T> bar , which I set by the name of the class: t = (Class<T>) Class.forName(name) . This gives me a warning without warning.

Usually using asSubclass can be used in similar situations, but since T has several boundaries, I cannot use it without warning the compiler:

 //This is type safe, but I still get an unchecked cast warning t = (Class<T>) Class.forName(className).asSubclass(Enum.class).asSubclass(Runnable.class); 

Is there any way to get rid of this warning without using @SupressedWarning("unchecked") ?

Full example:

 public class Example<T extends Enum<T> & Runnable> { Class<T> t; Example(String className) throws ClassNotFoundException { t = (Class<T>) Class.forName(className).asSubclass(Enum.class).asSubclass(Runnable.class); } } 
+6
source share
2 answers
 //This is type safe, but I still get an unchecked cast warning t = (Class<T>) Class.forName(className).asSubclass(Enum.class).asSubclass(Runnable.class); 

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; //uh oh... 

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.

+3
source

I believe that you simply cannot ... The best solution, in my opinion, would be to pass the Class<T> clazz directly as a parameter, and not its String name .

+1
source

Source: https://habr.com/ru/post/949003/


All Articles