Create an enum with elements associated with classes
Suppose I have several concrete classes that extend one abstract class, for example:
public abstract AbstractClass {
// abstract stuff here
}
public FirstSpecificClass extends AbstractClass {
// specific stuff here
}
public SecondSpecificClass extends AbstractClass {
// specific stuff here
}
I need to create enum
in a different location where each entry is connected (linked?) To one of the defined classes; for this purpose, I pass the concrete class as a parameter to the constructor and store it as a private field in the enum (I also provided a getter method for this field). I also need to create a static method that takes an instance of one of the concrete classes as an argument and returns the corresponding enum member (or null). I will do this by traversing each enum record and using instanceof
in conjunction with the recipient for the private field mentioned earlier. This is my attempt:
public enum Types {
FIRST(FirstSpecificClass.class), // line 2
SECOND(SecondSpecificClass.class); // line 3
private Class<AbstractClass> classType;
private Types(Class<AbstractClass> classType) {
this.classType = classType;
}
public Class<AbstractClass> getClassType() {
return this.classType;
}
public static Types fromTypeInstance(AbstractClass instance) {
for(Types t : Types.values())
if(instance instanceof t.getClassType()) return t; // line 17
return null;
}
}
I seem to be misunderstanding how to store the class type as a field so that it can be returned and used in the test instanceof
later. This code generates several compile-time errors:
- (enumeration line 2): constructor
Types(Class<FirstSpecificClass>)
is undefined - (enumeration line 3): constructor
Types(Class<SecondSpecificClass>)
is undefined - (enumeration line 17): Incompatible operand types
boolean
andClass<AbstractClass>
I'm not usually a Java programmer, and my understanding of generics instanceof
is vague at best, although I have a fairly clear understanding of the OOP concept. How can I eliminate these errors and achieve the desired effect?
source to share
In Java, generics are invariant. This means that a is Class<FirstSpecificClass>
not Class<AbstractClass>
, even if a FirstSpecificClass
is AbstractClass
.
You can work around this by explicitly allowing subtypes with the upper bound wildcard. Add ? extends
before the type argument AbstractClass
if necessary.
private Class<? extends AbstractClass> classType;
private Types(Class<? extends AbstractClass> classType) {
this.classType = classType;
}
public Class<? extends AbstractClass> getClassType() {
return this.classType;
}
Also, you have to specify the type directly in the source code for the operator instanceof
, so this won't compile:
if(instance instanceof t.getClassType())
Instead, you can use the object method to solve at runtime: Class
isInstance
if(t.getClassType().isInstance(instance))
source to share