Reputation: 634
I have a class MyClass<GenericArg>
How can I get the class of it?
I tried :
MyClass<GenericArg>.class
and it doesn't compile.
I tried MyClass.class
and it compiles, but with a warning, and I don't like warnings. Is there a possibility to avoid this warning (without a suppresswarning, of course!)?
EDIT :
I have a function construct(Class myClass) where T extends AbstractClass
in the construct method, I instantiate T and return it :
myClass.newInstance();
return myClass;
When I call, I have that :
public class SubClass<myEnum extends Enum<myEnum> extends AbstractClass<myEnum>
{
public static SubClass<myEnum> getSubClass()
{
return construct(SubClass.class);
}
}
Upvotes: 0
Views: 97
Reputation: 10084
I sense that what you want to do is reflectively create an instance of a class which can be generic.
Is this accurate?
For all the reasons already discussed, there is no way in Java 8 to do this without getting a compiler warning, but this does not mean that your code isn't type safe. The warning only means that it is unable to guarantee that your code is type safe. If you are able to prove to yourself that your code is safe, then it is appropriate (and useful) to suppress the warning for the type safe code.
Here is an example of a method that creates and returns an object of the same type as that of the supplied argument:
public static <T> T createInstanceFrom(T myInstance) {
@SuppressWarnings("unchecked")
Class<T> myType = (Class<T>) myInstance.getClass();
T instance = myType.newInstance();
return instance;
}
Because there is no type safe way to cast to a generic type, the cast above will generate a compiler warning telling you that your code may not be type safe. However, you can analyze the code yourself. In this case, myInstance
, instance
, and myType
must always all share the same Class
object. Because you can prove that the code is type safe, it is important to suppress the warning (and add a comment explaining why the code is safe).
You can prove that this is type safe:
List<String> stringList = new ArrayList<>();
List<String> myList1 = createInstanceFrom(stringList);
List<Integer> myList2 = createInstanceFrom(stringList);
List myList3 = createInstanceFrom(stringList);
The createInstanceFrom
method -must- return an object with the same type as its argument, therefore the line with myList1
compiles but the line with myList2
generates a compiler error. The line with myList3
compiles but generates a compiler warning because, again, now that you're using a raw type the compiler cannot guarantee to you that this code is type safe. Here though, there is no way to prove that this code is safe (and so this code should be refactored into something safer).
Upvotes: 1
Reputation: 10084
The class literal MyClass<GenericType>.class
is illegal because it does not exist at run time. Java generics are implemented by erasure and so the byte codes for:
MyClass<GenericType1>
MyClass<GenericType2>
MyClass
all share the same run-time Class object. It's a good thing that you get the compiler error because the generic class literal isn't type safe.
The Java compiler guarantees that your code will be type safe if it compiles without errors or warnings. When you get this particular warning, it is because the Java environment is telling you that it cannot guarantee the type safety of your code. It becomes your responsibility at this point to evaluate your code and determine whether (or not) what you're trying to do is safe.
If it is type safe (and only if) then you should apply the @SuppressWarnings
annotation in the shortest code block possible with a comment explaining how the code is still type safe. If you can't think of any such comment, then you may wish to refactor your design in order to achieve better type safety.
Upvotes: 5