Reputation: 42612
I have Enum:
public enum MyTypes {FOO, BAR}
I defined a class with generic types:
public MyClass<T extends MyTypes> {
private T theType;
...
}
Above code compiles successfully.
Next, I try to create an instance of MyClass with type Foo as the generic parameter:
// Compilation error: Cannot resolve symbol FOO
MyClass<FOO> myInstanceWithFoo = new MyClass();
Is it because Java don't accept enum
type as generic type? If so, is there a workaround to achieve what I want to achieve?
Upvotes: 0
Views: 274
Reputation: 324
It's my guess that you're confusing FOO as a subtype as MyClass when it is in fact an instance.
With 'normal' generics you specify the type the placeholder will be:
public class GenericClass <T extends Object> { // a bit contrived here
private T generic;
}
which is instantiated
GenericClass<String> gen = new GenericClass<>(); // String is a subclass of Object
this is then compiled to
public class GenericClass {
private String generic;
}
Notice there is no value for the String. There is no String instance. To do this we either need a setter or constructor:
public class GenericClass<T extends Object> {
private T generic;
public GenericClass(T generic) {
this.generic = generic;
}
}
GenericClass<String> gen = new GenericClass<>("Passing in a String because T was a String");
or
GenericClass<Integer> gen2 = new GenericClass<>(2); // T is integer so we can only pass integers - 2 will be the instance.
So for the Enum as a generic type we're stating the type which is MyType. The value would be FOO, so again we'd need either a setter or a constructor:
public class MyClass<T extends MyTypes> {
private T theType;
public MyClass(T theType) {
this.theType = theType;
}
}
and to make sure we're have a FOO instance we pass it in to the constructor
MyClass<MyTypes> myInstanceWithFoo = new MyClass<>(MyTypes.FOO);
Hope this makes sense.
Upvotes: 0
Reputation: 49616
Is it because Java don't accept enum type as generic type?
Any enum type is a valid type and can participate in both forming a type parameter (e.g. MyClass<T extends MyTypes>
) and parameterizing a type (e.g. MyClass<MyTypes> myInstance
).
What you did
MyClass<FOO> myInstanceWithFoo = new MyClass();
is never corrent since FOO
is an instance (or object) of MyTypes
. It's not a type, and can't be treated as such.
If so, is there a workaround to achieve what I want to achieve?
There is no need for MyClass
to be generic. It declares a MyTypes
field which could be either MyTypes.FOO
or MyTypes.BAR
(or null
, of course).
class MyClass {
private MyTypes myType;
public MyClass(MyTypes myType) {
this.myType = myType;
}
}
Each MyTypes
instance knows how to create a MyClass
from itself.
enum MyTypes {
FOO, BAR;
public MyClass createMyClass() {
return new MyClass(this);
}
}
An example of how to create them would be
class Example {
public static void main(String[] args) {
MyClass myInstanceWithFoo = MyTypes.FOO.createMyClass();
MyClass myInstanceWithBar = MyTypes.BAR.createMyClass();
}
}
Upvotes: 1