Reputation: 16037
Consider that I have an interface com.mycompany.SomeInterface
, and an enum com.mycompany.SomeEnum implements SomeInterface
. I want to get all enum constants of this class – as instances of SomeInterface
– at runtime using the Reflection API.
Currently, my code (in the class EnumConstantGetter
) is something like this:
Class<?> clazz = EnumConstantGetter.class.getClassLoader().
loadClass("com.mycompany.SomeEnum");
if (!(SomeInterface.class.isAssignableFrom(clazz)) {
throw new Exception("the class doesn't implement SomeInterface");
}
if (!(clazz.isEnum()) {
throw new Exception("not an enum");
}
Class<? extends Enum<? extends SomeInterface>> castClass =
(Class<? extends Enum<? extends SomeInterface>>) clazz; // cast #1
ArrayList<SomeInterface> vals = new ArrayList<SomeInterface>();
for (Enum<? extends SomeInterface> enumConstant :
castClass.getEnumConstants()) {
vals.add((SomeInterface) enumConstant); // cast #2
}
The above code appears to work, but I get a compiler warning at the creation of castClass
.
My question, then, is: are both casts noted in the code (the cast on the class and the cast on the constant) necessarily valid based on my checks?
In other words, is every member of Enum<? extends T>
guaranteed to implement T
?
If the answer is, "Yes, the casts are safe," then why does the compiler give me this warning?
If not, why not? or, in what circumstances could the routine fail?
EDIT: As my code above is apparently confusing, here's my explanation of what's supposed to be happening:
SomeEnum
in the package com.mycompany
and store its Class
object in a variable.SomeInterface
interface.SomeInterface
, cast it to a Class<? extends Enum<? extends SomeInterface>>
– cast #1SomeInterface
– cast #2 – and add it to the list of constants.Thanks!
Upvotes: 3
Views: 2641
Reputation: 55223
You could do the following:
Class<?> clazz = ...;
Class<? extends SomeInterface> someInterfaceClass;
try {
someInterfaceClass = clazz.asSubclass(SomeInterface.class);
}
catch (ClassCastException cce) {
throw new IllegalStateException("Specified type doesn't implement SomeInterface", cce);
}
SomeInterface[] enumConstants = someInterfaceClass.getEnumConstants();
if (enumConstants == null) {
throw new IllegalStateException("Specified type is not an enum.");
}
//use constants
This avoids the warnings because asSubclass
is checked and getEnumConstants
returns null
if the Class
object "does not represent an enum type".
Upvotes: 5