How to implement enum with generics?
You can't. Java doesn't allow generic types on enum constants. They are allowed on enum types, though:
public enum B implements A<String> {
A1, A2;
}
What you could do in this case is either have an enum type for each generic type, or 'fake' having an enum by just making it a class:
public class B<T> implements A<T> {
public static final B<String> A1 = new B<String>();
public static final B<Integer> A2 = new B<Integer>();
private B() {};
}
Unfortunately, they both have drawbacks.
How can I require a generic parameter to be an enum that implements an interface?
Use an '&
' instead:
public class MyWidget<T extends Enum<T> & MyInterface> {
...
}
The JLS calls this an "intersection type", but I can find no mention of it in the Java tutorials. I'll just say that it does exactly what you were wishing that "extends
" would do.
Also, I should mention that you can have as many types as you want in the intersection type. So if you wanted, you could do:
public class MyWidget<T extends Enum<T> & MyInterface & Serializable & Cloneable> {
...
}
[Note: this code sample should not be construed as an endorsement of the Cloneable
interface; it was merely handy at the time.]
Generic interface for enums in Java
The problem is that I don't want to create converter for each enum and
ideally it should be generic class/interface and I will use
polymorphism here.
You have no choice as your AttributeConverter
implementation could not be parameterized when you annotate your entity.
You should indeed specify it only with the AttributeConverter
class :
@Enumerated(EnumType.STRING)
@Convert(converter = MerchantStatusConverter.class)
private MerchantStatus merchantStatus;
But you could define an abstract class that defines the logic and subclassing it in each enum class.
To achieve it, you should introduce an interface in front of each enum class that declares a fromString()
and a toString()
method.
The interface :
public interface MyEnum<T extends MyEnum<T>>{
T fromString(String type);
String toString(T enumValue);
}
The enum that implements the interface :
public enum MerchantStatus implements MyEnum<MerchantStatus> {
NEW("New"), ...
@Override
public MerchantStatus fromString(String type) {
...
}
@Override
public String toString(MerchantStatus enumValue) {
...
}
}
The abstract AttributeConverter
class :
public abstract class AbstractAttributeConverter<E extends MyEnum<E>> implements AttributeConverter<E, String> {
protected MyEnum<E> myEnum;
@Override
public String convertToDatabaseColumn(E attribute) {
return myEnum.toString(attribute);
}
@Override
public E convertToEntityAttribute(String dbData) {
return myEnum.fromString(dbData);
}
}
And concrete AttributeConverter
class that needs to declare a public constructor to assign the protected myEnum
field to an enum value (whatever of it):
public class MerchantStatusAttributeConverter extends AbstractAttributeConverter<MerchantStatus> {
public MerchantStatusAttributeConverter(){
myEnum = MerchantStatus.NEW;
}
}
Java Enum as generic type in Enum
In your method implementation PerspectiveCommands
is not the enum but your type parameter, which often is called T
. It thus shadows the enum of the same name like axtavt already said, thus PERSPECTIVE
is unknown here.
Your abstract method declaration is fine but you might use a slightly different approach.
public void test(PerspectiveCommands command)
would not work, since this method would not override the generic version. The reason is that with the generic version the type is inferred from the parameter and thus you could pass any enum.
However, I assume you have an interface or abstract class which defines the abstract method. So try something like this:
interface TestInterface<T extends Enum<T>>
{
public abstract void test(T command);
}
class TestImpl implements TestInterface<PerspectiveCommands>
{
@Override
public void test(PerspectiveCommands command) {
if(command == PerspectiveCommands.PERSPECTIVE){
//do something
}
}
}
Get values of generic enum that implements an interface
I suspect you may be looking for something like:
public static <T extends Enum<T> & GenericMethods> T[] getEnums(Class<T> enum1) {
return enum1.getEnumConstants();
}
public static void main(String[] args) {
for (GenericMethods gm : getEnums(SpecificEnum.class)) {
System.out.println(gm.getString());
}
}
Results:
(demo: https://ideone.com/v6on2p)
NOT
RELATED
TEXT
Changes:
- moved
<T extends GenericMethods>
before return type since only there generic method can declare its generic type. - modified generic type to
<T extends Enum<T> & GenericMethods>
to force T to also be subtype of some Enum aside from implementing GenericMethods - used
getEnumConstants()
instead ofvalues()
as we are usingClass
, notenum
type.
Calling Enum.values() on a generic type
A common way to do this is to pass the target class object (or an object of the target class) as an argument to the function, then use methods from the class object to do the tricky part. For enum classes, the class object has a method which returns the equivalent of Enum.values(). You can use that to get the enum values from the target class:
public class Scratch {
enum lower { a, b, c };
enum upper { A, B, C };
static <T extends Enum<T>> T translate(Enum<?> aFrom, Class<T> aTo) {
return aTo.getEnumConstants()[aFrom.ordinal()];
}
public static void main(String[] args) {
for (lower ll : lower.values()) {
upper uu = translate(ll, upper.class);
System.out.printf("Upper of '%s' is '%s'\n", ll, uu);
}
for (upper uu : upper.values()) {
lower ll = translate(uu, lower.class);
System.out.printf("Lower of '%s' is '%s'\n", uu, ll);
}
}
}
Running this produces the following output:
Upper of 'a' is 'A'
Upper of 'b' is 'B'
Upper of 'c' is 'C'
Lower of 'A' is 'a'
Lower of 'B' is 'b'
Lower of 'C' is 'c'
JAVA - Passing a generic enum as a method parameter for a constructor
You can let your enums implement a common interface:
interface CommonInterface {
public String getId();
public String getProductName();
public BuySection getBuySection();
}
enum FstEnum implements CommonInterface {}
enum SndEnum implements CommonInterface {}
class Product<E extends Enum<E> & CommonInterface> {
E type;
Product(E type) {
this.type = type;
}
}
public static <E extends Enum<E> & CommonInterface> void setActualProduct(E itemType) {
actualProduct = new Product<E>(itemType);
}
A few remarks wrt. naming conventions: class names should be singular (BuySection
, not BuySections
), enums should begin with uppercase letters (as should all types, e.g. ItemsA
, not itemsA
)
Related Topics
How to Create Your Own Library for Android Development to Be Used in Every Program You Write
What Optimizations How to Expect from Dalvik and the Android Toolchain
Getview VS. Bindview in a Custom Cursoradapter
How to Get Count of Number Methods Used in a Jar File
Convert Object to JSON in Android
Key Hash for Facebook Android Sdk
Unsupported Major.Minor Version 52.0 in My App
Why Use Enums Instead of Constants? Which Is Better in Terms of Software Design and Readability
Capture Screen of Glsurfaceview to Bitmap
How to Pass Values Between a Dialog and an Activity
How to Fetch Android Market Data When There Is No API
Recyclerview Not Call Oncreateviewholder
Requestlegacyexternalstorage Is Not Working in Android 11 - API 30
Writing Pcm Recorded Data into a .Wav File (Java Android)
Can't Get Okhttp's Response.Body.Tostring() to Return a String
Android Overlay a View Ontop of Everything