Memetakan dengan mudah antara enum dan int / String

108

Saat bekerja dengan variabel / parameter yang hanya dapat mengambil sejumlah nilai, saya mencoba untuk selalu menggunakan Java enum, seperti pada

public enum BonusType {
  MONTHLY, YEARLY, ONE_OFF
}

Selama saya tetap berada di dalam kode saya, itu berfungsi dengan baik. Namun, saya sering perlu berinteraksi dengan kode lain yang menggunakan nilai biasa int(atau String) untuk tujuan yang sama, atau saya perlu membaca / menulis dari / ke database tempat data disimpan sebagai angka atau string.

Dalam hal ini, saya ingin memiliki cara yang mudah untuk mengaitkan setiap nilai enum dengan bilangan bulat, sehingga saya dapat mengonversi kedua cara (dengan kata lain, saya memerlukan "enum yang dapat dibalik").

Beralih dari enum ke int itu mudah:

public enum BonusType {
  public final int id;

  BonusType(int id) {
    this.id = id;
  }
  MONTHLY(1), YEARLY(2), ONE_OFF(3);
}

Kemudian saya dapat mengakses nilai int sebagai BonusType x = MONTHLY; int id = x.id;.

Namun, saya tidak melihat cara yang baik untuk kebalikannya, yaitu berpindah dari int ke enum. Idealnya, seperti

BonusType bt = BonusType.getById(2); 

Satu-satunya solusi yang dapat saya temukan adalah:

  • Letakkan metode pencarian ke dalam enum, yang digunakan BonusType.values()untuk mengisi peta "int -> enum", lalu menyimpannya dan menggunakannya untuk pencarian. Akan berfungsi, tetapi saya harus menyalin metode ini secara identik ke setiap enum yang saya gunakan :-(.
  • Letakkan metode pencarian ke dalam kelas utilitas statis. Maka saya hanya perlu satu metode "pencarian", tetapi saya harus mengutak-atik refleksi untuk membuatnya bekerja untuk enum sewenang-wenang.

Kedua metode tampaknya sangat canggung untuk masalah sederhana (?) Seperti itu.

Ada ide / wawasan lain?

sleske
sumber
1
Saya <3 java enums tetapi membenci mereka karena alasan ini persis! Itu selalu tampak seperti mereka sempurna selain dari satu kekurangan yang sangat jelek ...
Chris Thompson
8
untuk enum-> int Anda bisa menggunakanordinal()
davin
1
Apakah nilai-id Anda dapat ditentukan oleh Anda (artinya, tidak bisakah Anda gunakan saja .ordinal()), atau apakah mereka ditentukan oleh kekuatan luar?
Paŭlo Ebermann
2
@davin: Ya, dan minta kode Anda rusak saat seseorang mengatur ulang deklarasi enum, atau menghapus nilai di tengah. Saya khawatir itu bukan solusi yang tepat: - /.
sleske
1
@davin menggunakan "ordinal ()" harus dihindari sebisa mungkin, itu dalam spesifikasi bahasa
DPM

Jawaban:

37

http://www.javaspecialists.co.za/archive/Issue113.html

Solusinya dimulai mirip dengan Anda dengan nilai int sebagai bagian dari definisi enum. Dia kemudian melanjutkan untuk membuat utilitas pencarian berbasis generik:

public class ReverseEnumMap<V extends Enum<V> & EnumConverter> {
    private Map<Byte, V> map = new HashMap<Byte, V>();
    public ReverseEnumMap(Class<V> valueType) {
        for (V v : valueType.getEnumConstants()) {
            map.put(v.convert(), v);
        }
    }

    public V get(byte num) {
        return map.get(num);
    }
}

Solusi ini bagus dan tidak memerlukan 'mengutak-atik refleksi' karena ini didasarkan pada fakta bahwa semua jenis enum secara implisit mewarisi antarmuka Enum.

Jeff
sumber
Bukankah ini menggunakan ordinal? Sleske menggunakan id hanya karena ordinalnya berubah ketika nilai enum diurutkan ulang.
ekstraneon
Tidak, itu tidak menggunakan ordinal. Ini bergantung pada nilai int yang didefinisikan secara eksplisit. Nilai int itu digunakan sebagai kunci peta (dikembalikan oleh v.convert ()).
Jeff
2
Saya sangat menyukai solusi ini; tampaknya ini adalah yang paling umum yang bisa Anda dapatkan.
sleske
+1. Catatan saya hanya adalah bahwa saya akan menggunakan Numberbukan Byte, karena nilai dukungan saya mungkin lebih besar dalam ukuran.
Ivaylo Slavov
3
Benar-benar dan benar-benar membaca pertanyaannya. Jika Anda berurusan dengan database lama atau sistem eksternal yang telah menentukan bilangan bulat yang tidak ingin Anda sebarkan melalui kode Anda sendiri, maka ini adalah salah satu kasus tersebut. Ordinal adalah cara yang sangat rapuh untuk mempertahankan nilai enum, dan lebih dari itu, ordinal tidak berguna dalam kasus spesifik yang disebutkan dalam pertanyaan.
Jeff
327

enum → int

yourEnum.ordinal()

int → enum

EnumType.values()[someInt]

String → enum

EnumType.valueOf(yourString)

enum → String

yourEnum.name()

Catatan tambahan:
Seperti yang Anda tunjukkan dengan benar, ordinal()mungkin "tidak stabil" dari versi ke versi. Inilah alasan sebenarnya mengapa saya selalu menyimpan konstanta sebagai string di database saya. (Sebenarnya, saat menggunakan MySql, saya menyimpannya sebagai MySql enums !)

aioobe
sumber
2
+1 Ini adalah jawaban yang benar dan jelas. Namun perlu dicatat, ada metode argumen tunggal untuk valueOf yang hanya mengambil String dan ada selama Anda menggunakan jenis enum konkret (misalnya BonusType.valueOf("MONTHLY"))
Tim Bender
18
Penggunaan ordinal()strike me sebagai solusi bermasalah, karena akan rusak ketika daftar nilai enum diatur ulang, atau nilai dihapus. Juga, ini hanya praktis jika nilai int adalah 0 ... n (yang sering saya temukan tidak demikian).
sleske
4
@sleske, jika Anda mulai menghapus konstanta, Anda tetap bermasalah dengan data yang ada. (Memperbarui jawaban saya dalam hal ini.)
aioobe
3
Menggunakan values()array hanya akan berfungsi jika semua nilai Anda diindeks 0 untuk id mereka dan dideklarasikan secara berurutan. (Saya menguji ini untuk memverifikasi bahwa jika Anda menyatakan FOO(0), BAR(2), BAZ(1);itu values[1] == BARdan values[2] == BAZterlepas dari ID yang diteruskan.)
corsiKa
2
@glowcoder, tentu saja, argumen integer hanyalah sebuah field dalam enum-object. Ini tidak ada hubungannya dengan konstanta ordinal yang terkait dengan objek enum (bisa juga a double).
aioobe
29

Saya menemukan ini di web, sangat membantu dan mudah diterapkan. Solusi ini BUKAN dibuat oleh saya

http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks

public enum Status {
 WAITING(0),
 READY(1),
 SKIPPED(-1),
 COMPLETED(5);

 private static final Map<Integer,Status> lookup 
      = new HashMap<Integer,Status>();

 static {
      for(Status s : EnumSet.allOf(Status.class))
           lookup.put(s.getCode(), s);
 }

 private int code;

 private Status(int code) {
      this.code = code;
 }

 public int getCode() { return code; }

 public static Status get(int code) { 
      return lookup.get(code); 
 }

}

melqkiades.dll
sumber
s / EnumSet.allOf (Status.class) /Status.values ​​()
jelinson
8

Sepertinya jawaban untuk pertanyaan ini sudah ketinggalan zaman dengan dirilisnya Java 8.

  1. Jangan gunakan ordinal karena ordinal tidak stabil jika dipertahankan di luar JVM seperti database.
  2. Relatif mudah untuk membuat peta statis dengan nilai-nilai kunci.

public enum AccessLevel {
  PRIVATE("private", 0),
  PUBLIC("public", 1),
  DEFAULT("default", 2);

  AccessLevel(final String name, final int value) {
    this.name = name;
    this.value = value;
  }

  private final String name;
  private final int value;

  public String getName() {
    return name;
  }

  public int getValue() {
    return value;
  }

  static final Map<String, AccessLevel> names = Arrays.stream(AccessLevel.values())
      .collect(Collectors.toMap(AccessLevel::getName, Function.identity()));
  static final Map<Integer, AccessLevel> values = Arrays.stream(AccessLevel.values())
      .collect(Collectors.toMap(AccessLevel::getValue, Function.identity()));

  public static AccessLevel fromName(final String name) {
    return names.get(name);
  }

  public static AccessLevel fromValue(final int value) {
    return values.get(value);
  }
}
John Meyer
sumber
Bukankah seharusnya parameter kedua Collectors.toMap()menjadi, Functions.identity()bukan null?
Adam Michalik
ya, saya mengadopsi ini dari kelas pembantu yang saya gunakan dengan jambu biji yang mengubah null menjadi identitas.
John Meyer
Itu adalah penggunaan yang rapi dari fitur baru Java 8. Namun, itu tetap berarti kode harus diulang di setiap enum - dan pertanyaan saya adalah tentang menghindari boilerplate yang berulang (secara struktural) ini.
sleske
5

org.apache.commons.lang.enums.ValuedEnum;

Untuk menyelamatkan saya menulis banyak kode boilerplate atau kode duplikat untuk setiap Enum, saya menggunakan Apache Commons Lang ValuedEnumsebagai gantinya.

Definisi :

public class NRPEPacketType extends ValuedEnum {    
    public static final NRPEPacketType TYPE_QUERY = new NRPEPacketType( "TYPE_QUERY", 1);
    public static final NRPEPacketType TYPE_RESPONSE = new NRPEPacketType( "TYPE_RESPONSE", 2);

    protected NRPEPacketType(String name, int value) {
        super(name, value);
    }
}

Pemakaian:

int -> ValuedEnum:

NRPEPacketType packetType = 
 (NRPEPacketType) EnumUtils.getEnum(NRPEPacketType.class, 1);
Alastair McCormack
sumber
Ide bagus, saya tidak menyadari bahwa ini ada. Terima kasih telah berbagi!
Keith P
3

Anda mungkin bisa menggunakan sesuatu seperti

interface EnumWithId {
    public int getId();

}


enum Foo implements EnumWithId {

   ...
}

Itu akan mengurangi kebutuhan refleksi di kelas utilitas Anda.

extraneon
sumber
Dapatkah Anda memberikan contoh cara menggunakan cuplikan ini?
IgorGanapolsky
3

Dalam kode ini, untuk pencarian permanen dan intens, memiliki memori atau proses untuk digunakan, dan saya memilih memori, dengan array konverter sebagai indeks. Saya harap ini membantu

public enum Test{ 
VALUE_ONE(101, "Im value one"),
VALUE_TWO(215, "Im value two");
private final int number;
private final byte[] desc;

private final static int[] converter = new int[216];
static{
    Test[] st = values();
    for(int i=0;i<st.length;i++){
        cv[st[i].number]=i;
    }
}

Test(int value, byte[] description) {
    this.number = value;
    this.desc = description;
}   
public int value() {
    return this.number;
}
public byte[] description(){
    return this.desc;
}

public static String description(int value) {
    return values()[converter[rps]].desc;
}

public static Test fromValue(int value){
return values()[converter[rps]];
}
}
Sebastian Sgo Acevedo
sumber
2

Gunakan antarmuka untuk menunjukkan siapa bosnya.

public interface SleskeEnum {
    int id();

    SleskeEnum[] getValues();

}

public enum BonusType implements SleskeEnum {


  MONTHLY(1), YEARLY(2), ONE_OFF(3);

  public final int id;

  BonusType(int id) {
    this.id = id;
  }

  public SleskeEnum[] getValues() {
    return values();
  }

  public int id() { return id; }


}

public class Utils {

  public static SleskeEnum getById(SleskeEnum type, int id) {
      for(SleskeEnum t : type.getValues())
          if(t.id() == id) return t;
      throw new IllegalArgumentException("BonusType does not accept id " + id);
  }

  public static void main(String[] args) {

      BonusType shouldBeMonthly = (BonusType)getById(BonusType.MONTHLY,1);
      System.out.println(shouldBeMonthly == BonusType.MONTHLY);

      BonusType shouldBeMonthly2 = (BonusType)getById(BonusType.MONTHLY,1);
      System.out.println(shouldBeMonthly2 == BonusType.YEARLY);

      BonusType shouldBeYearly = (BonusType)getById(BonusType.MONTHLY,2);
      System.out.println(shouldBeYearly  == BonusType.YEARLY);

      BonusType shouldBeOneOff = (BonusType)getById(BonusType.MONTHLY,3);
      System.out.println(shouldBeOneOff == BonusType.ONE_OFF);

      BonusType shouldException = (BonusType)getById(BonusType.MONTHLY,4);
  }
}

Dan hasilnya:

C:\Documents and Settings\user\My Documents>java Utils
true
false
true
true
Exception in thread "main" java.lang.IllegalArgumentException: BonusType does not accept id 4
        at Utils.getById(Utils.java:6)
        at Utils.main(Utils.java:23)

C:\Documents and Settings\user\My Documents>
corsiKa
sumber
1
Sama seperti dengan jawaban Turd Ferguson, itulah solusi tidak elegan yang ingin saya hindari / tingkatkan ...
sleske
Saya biasanya membuat pemetaan terbalik dalam blok {} statis agar tidak perlu mengulang nilai () setiap kali saya meminta nilai menurut id. Saya juga biasanya memanggil metode valueOf (int) untuk membuatnya tampak seperti metode valueOf (String) yang sudah ada untuk Strings (juga bagian dari pertanyaan OP). Agak suka item 33 di Java Efektif: tinyurl.com/4ffvc38
Fredrik
@Sleske Diperbarui dengan solusi yang lebih halus. @Fredrik menarik, meskipun saya ragu iterasi akan menjadi masalah yang signifikan.
corsiKa
@glowcoder Ya, tidak harus mengulang lebih dari sekali berarti tidak masalah jika Anda melakukannya ribuan kali per detik karena ini bisa menjadi masalah yang sangat signifikan atau hanya menyebutnya dua kali.
Fredrik
@Fredrik Saya akan mengakui ada saat-saat di mana mungkin perlu untuk mengoptimalkan. Saya juga mengatakan bahwa sampai masalah kinerja teridentifikasi, jangan optimalkan untuk itu.
corsiKa
2

Baik the .ordinal()dan values()[i]tidak stabil karena bergantung pada urutan enum. Jadi jika Anda mengubah urutan enum atau menambah / menghapus beberapa program Anda akan rusak.

Berikut adalah metode sederhana namun efektif untuk memetakan antara enum dan int.

public enum Action {
    ROTATE_RIGHT(0), ROTATE_LEFT(1), RIGHT(2), LEFT(3), UP(4), DOWN(5);

    public final int id;
    Action(int id) {
        this.id = id;
    }

    public static Action get(int id){
        for (Action a: Action.values()) {
            if (a.id == id)
                return a;
        }
        throw new IllegalArgumentException("Invalid id");
    }
}

Menerapkannya untuk string seharusnya tidak sulit.

hrzafer.dll
sumber
Ya, saya menyadari bahwa saya bisa melakukan itu - atau bahkan lebih baik, menggunakan peta untuk pencarian terbalik, daripada mengulang melalui semua nilai. Saya menyebutkan ini dalam pertanyaan saya, dan saya juga menyebutkan bahwa saya mencari solusi yang lebih baik, untuk menghindari kode boilerplate di setiap enum.
sleske
2

Contoh penggunaan reverse Enum yang sangat bersih

Langkah 1 Tentukan interfaceEnumConverter

public interface EnumConverter <E extends Enum<E> & EnumConverter<E>> {
    public String convert();
    E convert(String pKey);
}

Langkah 2

Buat nama kelas ReverseEnumMap

import java.util.HashMap;
import java.util.Map;

public class ReverseEnumMap<V extends Enum<V> & EnumConverter<V>> {
    private Map<String, V> map = new HashMap<String, V>();

    public ReverseEnumMap(Class<V> valueType) {
        for (V v : valueType.getEnumConstants()) {
            map.put(v.convert(), v);
        }
    }

    public V get(String pKey) {
        return map.get(pKey);
    }
}

LANGKAH 3

Pergi ke Enumkelas Anda dan implementdengan EnumConverter<ContentType>dan tentu saja timpa metode antarmuka. Anda juga perlu menginisialisasi ReverseEnumMap statis.

public enum ContentType implements EnumConverter<ContentType> {
    VIDEO("Video"), GAME("Game"), TEST("Test"), IMAGE("Image");

    private static ReverseEnumMap<ContentType> map = new ReverseEnumMap<ContentType>(ContentType.class);

    private final String mName;

    ContentType(String pName) {
        this.mName = pName;
    }

    String value() {
        return this.mName;
    }

    @Override
    public String convert() {
        return this.mName;
    }

    @Override
    public ContentType convert(String pKey) {
        return map.get(pKey);
    }
}

LANGKAH 4

Sekarang membuat Communicationfile kelas dan menyebutnya itu metode baru untuk mengkonversi Enumke Stringdan Stringuntuk Enum. Saya baru saja meletakkan metode utama untuk tujuan penjelasan.

public class Communication<E extends Enum<E> & EnumConverter<E>> {
    private final E enumSample;

    public Communication(E enumSample) {
        this.enumSample = enumSample;
    }

    public String resolveEnumToStringValue(E e) {
        return e.convert();
    }

    public E resolveStringEnumConstant(String pName) {
        return enumSample.convert(pName);
    }

//Should not put main method here... just for explanation purpose. 
    public static void main(String... are) {
        Communication<ContentType> comm = new Communication<ContentType>(ContentType.GAME);
        comm.resolveEnumToStringValue(ContentType.GAME); //return Game
        comm.resolveStringEnumConstant("Game"); //return GAME (Enum)
    }
}

Klik untuk penjelasan lengkap

AZ_
sumber
1
Ini saya sangat, sangat suka - Saya telah mencari solusi yang solid untuk masalah ini selama beberapa waktu sekarang. Satu-satunya perubahan yang saya buat adalah membuat ContentType convert(String pKey)statis, yang menghilangkan kebutuhan akan Communicationkelas dan lebih sesuai dengan keinginan saya. +1
Chris Mantle
1

Saya tidak yakin apakah itu sama di Java, tetapi tipe enum di C secara otomatis dipetakan ke integer juga sehingga Anda dapat menggunakan tipe atau integer untuk mengaksesnya. Sudahkah Anda mencoba mengaksesnya dengan integer saja?

Detra83
sumber
2
Enum di Java tidak berperilaku seperti itu. Mereka adalah tipe yang eksplisit.
Chris Thompson
Setiap objek enum akan memiliki nomor internal (yaitu posisi di mana ia dideklarasikan), dan dapat diakses dengan .ordinal()metode tersebut. (Cara lain, gunakan BonusType.values()[i].) Tetapi dalam contoh yang dikutip di atas, indeks di sini dan nilai di luarnya tidak sama.
Paŭlo Ebermann
1

Pertanyaan yang sangat bagus :-) Saya menggunakan solusi yang mirip dengan Mr. Ferguson beberapa waktu lalu. Enum yang telah didekompilasi terlihat seperti ini:

final class BonusType extends Enum
{

    private BonusType(String s, int i, int id)
    {
        super(s, i);
        this.id = id;
    }

    public static BonusType[] values()
    {
        BonusType abonustype[];
        int i;
        BonusType abonustype1[];
        System.arraycopy(abonustype = ENUM$VALUES, 0, abonustype1 = new BonusType[i = abonustype.length], 0, i);
        return abonustype1;
    }

    public static BonusType valueOf(String s)
    {
        return (BonusType)Enum.valueOf(BonusType, s);
    }

    public static final BonusType MONTHLY;
    public static final BonusType YEARLY;
    public static final BonusType ONE_OFF;
    public final int id;
    private static final BonusType ENUM$VALUES[];

    static 
    {
        MONTHLY = new BonusType("MONTHLY", 0, 1);
        YEARLY = new BonusType("YEARLY", 1, 2);
        ONE_OFF = new BonusType("ONE_OFF", 2, 3);
        ENUM$VALUES = (new BonusType[] {
            MONTHLY, YEARLY, ONE_OFF
        });
    }
}

Melihat ini jelas mengapa ordinal()tidak stabil. Ini adalah bagian idalam super(s, i);. Saya juga pesimis bahwa Anda dapat memikirkan solusi yang lebih elegan daripada yang sudah Anda sebutkan. Lagipula enum adalah kelas seperti kelas akhir lainnya.

Lachezar Balev
sumber
1

Demi kelengkapan, berikut adalah pendekatan umum untuk mengambil nilai enum berdasarkan indeks dari jenis enum apa pun. Tujuan saya adalah membuat metode ini terlihat dan terasa seperti Enum.valueOf (Class, String) . Fyi, saya menyalin metode ini dari sini .

Masalah terkait indeks (sudah dibahas secara mendalam di sini) masih berlaku.

/**
 * Returns the {@link Enum} instance for a given ordinal.
 * This method is the index based alternative
 * to {@link Enum#valueOf(Class, String)}, which
 * requires the name of an instance.
 * 
 * @param <E> the enum type
 * @param type the enum class object
 * @param ordinal the index of the enum instance
 * @throws IndexOutOfBoundsException if ordinal < 0 || ordinal >= enums.length
 * @return the enum instance with the given ordinal
 */
public static <E extends Enum<E>> E valueOf(Class<E> type, int ordinal) {
    Preconditions.checkNotNull(type, "Type");
    final E[] enums = type.getEnumConstants();
    Preconditions.checkElementIndex(ordinal, enums.length, "ordinal");
    return enums[ordinal];
}
whiskeysierra
sumber
Bukan itu yang saya cari, karena ini hanya mengambil nilai enum dengan ordinalnya, bukan dengan id integer yang ditetapkan (lihat pertanyaan saya). Juga, jika saya menginginkannya, saya bisa menggunakan MyEnumType.values()- tidak perlu metode pembantu statis.
sleske
0
Int -->String :

public enum Country {

    US("US",0),
    UK("UK",2),
    DE("DE",1);


    private static Map<Integer, String> domainToCountryMapping; 
    private String country;
    private int domain;

    private Country(String country,int domain){
        this.country=country.toUpperCase();
        this.domain=domain;
    }

    public String getCountry(){
        return country;
    }


    public static String getCountry(String domain) {
        if (domainToCountryMapping == null) {
            initMapping();
        }

        if(domainToCountryMapping.get(domain)!=null){
            return domainToCountryMapping.get(domain);
        }else{
            return "US";
        }

    }

     private static void initMapping() {
         domainToCountryMapping = new HashMap<Integer, String>();
            for (Country s : values()) {
                domainToCountryMapping.put(s.domain, s.country);
            }
        }
Ran Adler
sumber
0

Saya membutuhkan sesuatu yang berbeda karena saya ingin menggunakan pendekatan umum. Saya membaca enum ke dan dari array byte. Di sinilah saya datang dengan:

public interface EnumConverter {
    public Number convert();
}



public class ByteArrayConverter {
@SuppressWarnings("unchecked")
public static Enum<?> convertToEnum(byte[] values, Class<?> fieldType, NumberSystem numberSystem) throws InvalidDataException {
    if (values == null || values.length == 0) {
        final String message = "The values parameter must contain the value";
        throw new IllegalArgumentException(message);
    }

    if (!dtoFieldType.isEnum()) {
        final String message = "dtoFieldType must be an Enum.";
        throw new IllegalArgumentException(message);
    }

    if (!EnumConverter.class.isAssignableFrom(fieldType)) {
        final String message = "fieldType must implement the EnumConverter interface.";
        throw new IllegalArgumentException(message);
    }

    Enum<?> result = null;
    Integer enumValue = (Integer) convertToType(values, Integer.class, numberSystem); // Our enum's use Integer or Byte for the value field.

    for (Object enumConstant : fieldType.getEnumConstants()) {
        Number ev = ((EnumConverter) enumConstant).convert();

        if (enumValue.equals(ev)) {
            result = (Enum<?>) enumConstant;
            break;
        }
    }

    if (result == null) {
        throw new EnumConstantNotPresentException((Class<? extends Enum>) fieldType, enumValue.toString());
    }

    return result;
}

public static byte[] convertEnumToBytes(Enum<?> value, int requiredLength, NumberSystem numberSystem) throws InvalidDataException {
    if (!(value instanceof EnumConverter)) {
        final String message = "dtoFieldType must implement the EnumConverter interface.";
        throw new IllegalArgumentException(message);
    }

    Number enumValue = ((EnumConverter) value).convert();
    byte[] result = convertToBytes(enumValue, requiredLength, numberSystem);
    return result;
}

public static Object convertToType(byte[] values, Class<?> type, NumberSystem numberSystem) throws InvalidDataException {
    // some logic to convert the byte array supplied by the values param to an Object.
}

public static byte[] convertToBytes(Object value, int requiredLength, NumberSystem numberSystem) throws InvalidDataException {
    // some logic to convert the Object supplied by the'value' param to a byte array.
}
}

Contoh enum:

public enum EnumIntegerMock implements EnumConverter {
    VALUE0(0), VALUE1(1), VALUE2(2);

    private final int value;

    private EnumIntegerMock(int value) {
        this.value = value;
    }

public Integer convert() {
    return value;
}

}

public enum EnumByteMock implements EnumConverter {
    VALUE0(0), VALUE1(1), VALUE2(2);

    private final byte value;

    private EnumByteMock(int value) {
        this.value = (byte) value;
    }

    public Byte convert() {
        return value;
    }
}
Patrick Koorevaar
sumber
0

Hanya karena jawaban yang diterima tidak berdiri sendiri:

Kode dukungan:

public interface EnumWithCode<E extends Enum<E> & EnumWithCode<E>> {

    public Integer getCode();

    E fromCode(Integer code);
}


public class EnumWithCodeMap<V extends Enum<V> & EnumWithCode<V>> {

    private final HashMap<Integer, V> _map = new HashMap<Integer, V>();

    public EnumWithCodeMap(Class<V> valueType) {
        for( V v : valueType.getEnumConstants() )
            _map.put(v.getCode(), v);
    }

    public V get(Integer num) {
        return _map.get(num);
    }
}

Contoh penggunaan:

public enum State implements EnumWithCode<State> {
    NOT_STARTED(0), STARTED(1), ENDED(2);

    private static final EnumWithCodeMap<State> map = new EnumWithCodeMap<State>(
            State.class);

    private final int code;

    private State(int code) {
        this.code = code;
    }

    @Override
    public Integer getCode() {
        return code;
    }

    @Override
    public State fromCode(Integer code) {
        return map.get(code);
    }

}
leonbloy.dll
sumber
0

diberikan:

public enum BonusType {MONTHLY (0), YEARLY (1), ONE_OFF (2)}

BonusType bonus = SETIAP TAHUN;

System.out.println (bonus.Ordinal () + ":" + bonus)

Output: 1: SETIAP TAHUN

David Urry
sumber
0

Jika Anda memiliki mobil kelas

public class Car {
    private Color externalColor;
}

Dan properti Color adalah sebuah kelas

@Data
public class Color {
    private Integer id;
    private String name;
}

Dan Anda ingin mengubah Warna menjadi Enum

public class CarDTO {
    private ColorEnum externalColor;
}

Cukup tambahkan metode di kelas Color untuk mengonversi Color di ColorEnum

@Data
public class Color {
    private Integer id;
    private String name;

    public ColorEnum getEnum(){
        ColorEnum.getById(id);
    }
}

dan di dalam ColorEnum mengimplementasikan metode getById ()

public enum ColorEnum {
...
    public static ColorEnum getById(int id) {
        for(ColorEnum e : values()) {
            if(e.id==id) 
                return e;
        }
    }
}

Sekarang Anda dapat menggunakan classMap

private MapperFactory factory = new DefaultMapperFactory.Builder().build();
...
factory.classMap(Car.class, CarDTO.class)
    .fieldAToB("externalColor.enum","externalColor")
    .byDefault()
    .register();
...
CarDTO dto = mapper.map(car, CarDTO.class);
danilo
sumber