简体   繁体   中英

Converting int to Enum in Java reflection

This might look similar to a few other questions but so far I have not found a solution..

I am using reflection to parse my JSONs into different classes and it saves me a lot of effort from writing class-specific parsing code, all the ints, longs, strings, and Calendars etc are easy to deal with, but now I find myself in an hell of Enum specific castings

something like:

else if (field.getType().isAssignableFrom(TransactionType.class)){
    field.set(representation, TransactionType.fromInt(Integer.parseInt(value, 10)));
}

the problem is that enums are stored as integers in the JSON, and I can not find a generic way to parse or cast those integers back to enums when I don't know what enum it specifically is, and I have quite a few enums so 70% of my parsing code are now dedicated to checking enum types...

is there a way that, given only field.getType().isEnum() == true, parse the int value to the enum type of that field

the enum type is declared as:

public static enum TransactionType{
    cashback(0),deposit(1),withdraw(2),invitation(3);
    public int code;
    TransactionType(int code){
        this.code = code;
    }
    private final static TransactionType[] map = TransactionType.values();
    public static TransactionType fromInt(int n){
        return map[n];
    }
}

the JSON can be a bit complicated, but enum related fields has formats as:

{transactionType: 1, someOtherEnumType: 0}

Heres how I would approch this given the information provided. Use a helper method that would sit outside your enum types that can convert any enum type that implements some interface.


public static interface Codeable {
    public int getCode();
}
public static enum TransactionType implements Codeable {
    cashback(0),deposit(1),withdraw(2),invitation(3);

    public int code; 
    TransactionType(int code) { 
        this.code = code; 
    }

    @Override
    public int getCode() {
        return code;
    }
}
public static <T extends Codeable> T fromCodeToEnum(int code, Class<T> clazz) {
    for(T t : clazz.getEnumConstants()) {
        if(t.getCode() == code) {
            return t;
        }
    }
    return null;
}
public static void main(String [] args) {
    TransactionType type = fromCodeToEnum(1, TransactionType.class);
    System.out.println(type); // deposit
}

Edit: Or of course you can just get the enum values and iterate through them. This could be placed wherever you want.

public static TransactionType findTransactionTypeByCode(int code) {

    for(TransactionType t : TransactionType.values()) {
        if(t.getCode() == code) {
            return t;
        }
    }
    return null;
}

Java do not support the implicit cast from literal to value.

Then enum in Java has method ordinal() , that returns int value.

Returns the ordinal of this enumeration constant (its position in its enum declaration, where the >initial constant is assigned an ordinal of zero).

An unsafe solution

if(field.getType().isEnum()) {
  Object itemInstance = field.getType().getEnumConstants()[ordinal];
}

How ever it is not recommended to us it at it was designed as part of API.

The recommendation for this case is to define in the definition of enum.

enum MyEnum {
 ITEM(1);

 private final int index;

 MyEnum(int index) {
   this.index;
 }
}

And then you should implement additional logic to serialize and deserialize, based for example on interface with default method.

interface SerializableEnum<E extends Enum<E>> {

        Class<E> getType();


        default E valueOf(int ordinal) {
            return getType().getEnumConstants()[ordinal];
        }
    }

Note that the best solution is to serialize the enum not via number but via its name.

Class.getEnumConstants() is what you need.

Class<?> cls = field.getType();
if (cls.isEnum()) {
  field.set(representation, 
    cls.getEnumConstants()[Integer.parseInt(value, 10)]);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM