Enum ve int / String arasında uygun şekilde eşleme


108

Yalnızca sınırlı sayıda değer alabilen değişkenler / parametrelerle çalışırken, her zaman Java'yı kullanmaya çalışıyorum enum.

public enum BonusType {
  MONTHLY, YEARLY, ONE_OFF
}

Kodumun içinde kaldığım sürece, bu iyi çalışıyor. Bununla birlikte, genellikle aynı amaç için düz int(veya String) değerler kullanan diğer kodlarla arayüz oluşturmam gerekir veya verilerin sayı veya dize olarak depolandığı bir veritabanından / veritabanından okumam / yazmam gerekir.

Bu durumda, her bir enum değerini bir tamsayı ile ilişkilendirmek için uygun bir yola sahip olmak istiyorum, böylece her iki yolu da dönüştürebilirim (başka bir deyişle, "tersine çevrilebilir bir numaralandırmaya" ihtiyacım var).

Enum'dan int'e gitmek kolaydır:

public enum BonusType {
  public final int id;

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

Sonra int değerine olarak erişebilirim BonusType x = MONTHLY; int id = x.id;.

Bununla birlikte, tersi için iyi bir yol göremiyorum, yani int'den enum'a gitmek. İdeal olarak, şöyle bir şey

BonusType bt = BonusType.getById(2); 

Bulabildiğim tek çözüm:

  • Numaralandırmaya bir BonusType.values()"int -> enum" haritasını doldurmak için kullanan , ardından bunu önbelleğe alan ve aramalarda kullanan bir arama yöntemi ekleyin. İşe yarardı, ancak bu yöntemi kullandığım her numaraya aynı şekilde kopyalamam gerekir :-(.
  • Arama yöntemini statik bir yardımcı program sınıfına yerleştirin. O zaman sadece bir "arama" yöntemine ihtiyacım olur, ancak bunun keyfi bir enum için çalışmasını sağlamak için yansımayla uğraşmam gerekir.

Her iki yöntem de böylesine basit (?) Bir problem için son derece garip görünüyor.

Başka fikir / anlayış var mı?


1
Ben <3 java numaralandırıyorum ama onlardan tam olarak bu nedenle nefret ediyorum! Gerçekten çirkin bir kusur dışında her zaman mükemmel gibi görünüyorlar ...
Chris Thompson

8
enum-> int için sadece kullanabilirsinizordinal()
davin

1
Kimlik değerleriniz sizin tarafınızdan .ordinal()kararlaştırılabilir mi (yani, sadece kullanamazsınız ) veya dış güçler tarafından mı kararlaştırılır?
Paŭlo Ebermann

2
@davin: Evet, biri enum bildirimini yeniden düzenlediği veya ortadaki bir değeri sildiği anda kodunuzu kırmasını sağlayın. Korkarım bu sağlam bir çözüm değil: - /.
sleske

1
@davin "ordinal ()" kullanmaktan mümkün olduğunca kaçınılmalıdır, bu dilin spesifikasyonundadır
DPM

Yanıtlar:


37

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

Çözüm, enum tanımının bir parçası olarak bir int değeriyle sizinkine benzer şekilde başlar. Daha sonra jenerik tabanlı bir arama aracı oluşturmaya devam ediyor:

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);
    }
}

Bu çözüm güzeldir ve 'yansıma ile uğraşmayı' gerektirmez çünkü tüm enum türlerinin Enum arabirimini örtük olarak miras alması gerçeğine dayanır.


Bu ordinal kullanmıyor mu? Sleske sırf enum değerleri yeniden sıralandığında sıra değiştiği için bir id kullanır.
extraneon

Hayır, sıra kullanmıyor. Açıkça tanımlanmış bir int değerine dayanır. Bu int değeri, harita anahtarı olarak kullanılır (v.convert () tarafından döndürülür).
Jeff

2
Bu çözümü gerçekten beğendim; Görünüşe göre bu alabileceğiniz en genel şey.
sleske

+1. Tek notum, bunun Numberyerine kullanacağım Byteçünkü destek değerim boyut olarak daha büyük olabilir.
Ivaylo Slavov

3
Soruyu gerçekten ve doğru bir şekilde okuyun. Kendi kodunuz aracılığıyla yayılmasını istemediğiniz tam sayıları tanımlayan eski bir veritabanı veya harici bir sistemle uğraşıyorsanız, bu tam olarak bu durumlardan biridir. Sıra, bir numaralamanın değerini sürdürmenin son derece kırılgan bir yoludur ve bunun ötesinde, soruda bahsedilen özel durumda işe yaramaz.
Jeff

327

enum → int

yourEnum.ordinal()

int → enum

EnumType.values()[someInt]

Dize → enum

EnumType.valueOf(yourString)

enum → Dize

yourEnum.name()

Bir yan not:
Doğru bir şekilde işaret ettiğiniz gibi ordinal(), sürümden sürüme "kararsız" olabilir. Veritabanlarımda sabitleri dizeler olarak saklamamın tam nedeni budur. (Aslında MySql kullanırken onları MySql numaralandırmaları olarak saklıyorum !)


2
+1 Bu apaçık doğru cevaptır. Bununla birlikte, valueOf için yalnızca bir String alan ve somut enum türünü (örneğin BonusType.valueOf("MONTHLY")) kullandığınız sürece var olan tek bir argüman yöntemi vardır
Tim Bender

18
ordinal()Enum değerleri listesi yeniden düzenlendiğinde veya bir değer silindiğinde bozulacağı için sorunlu bir çözüm olarak kullanılması beni etkiliyor. Ayrıca, bu yalnızca int değerlerinin 0 ... n olması durumunda pratiktir (ki çoğu zaman böyle olmadığını fark ettim).
sleske

4
@sleske, sabitleri silmeye başlarsanız, zaten var olan kalıcı verilerle sorun yaşarsınız. (Cevabım bu konuda güncellendi.)
aioobe

3
values()Diziyi kullanmak, yalnızca tüm değerleriniz id için 0 indekslenmişse ve sırayla bildirilmişse işe yarar. (Ben bunu doğrulamak için test olduğunu Gümrüğe eğer FOO(0), BAR(2), BAZ(1);o values[1] == BARve values[2] == BAZgeçirilen kimlikleri rağmen.)
corsiKa

2
@glowcoder, tabii ki, tamsayı argümanı yalnızca enum-nesnesinde bir alandır. Enum nesnesiyle ilişkili sıra sabiti ile ilgisi yoktur (aynı şekilde a da olabilirdi double).
aioobe

30

Bunu web'de buldum, çok yardımcı oldu ve uygulaması basitti. Bu çözüm benim tarafımdan YAPILMADI

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); 
 }

}


s / EnumSet.allOf (Status.class) /Status.values ​​()
jelinson

8

Görünüşe göre bu soruya verilen yanıtlar Java 8 sürümüyle güncelliğini yitirmiş.

  1. Bir veritabanı gibi JVM dışında bırakılırsa sıralı kararsız olduğu için sıralı kullanmayın.
  2. Anahtar değerlerle statik bir harita oluşturmak nispeten kolaydır.

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);
  }
}

İkinci parametre ait olmamalı Collectors.toMap()olmak Functions.identity()yerine null?
Adam Michalik

evet, bunu guava ile kullandığım null'u kimliğe dönüştüren yardımcı bir sınıftan aldım.
John Meyer

Bu, Java 8'in yeni özelliklerinin düzgün kullanımıdır. Bununla birlikte, yine de kodun her numaralandırmada tekrarlanması gerektiği anlamına gelir - ve benim sorum bu (yapısal olarak) tekrarlanan standart şablondan kaçınmakla ilgiliydi.
sleske

5

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

Beni her Enum için bir sürü standart kod veya yinelenen kod yazmaktan kurtarmak için, ValuedEnumbunun yerine Apache Commons Lang'ı kullandım.

Tanım :

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);
    }
}

Kullanımı:

int -> ValuedEnum:

NRPEPacketType packetType = 
 (NRPEPacketType) EnumUtils.getEnum(NRPEPacketType.class, 1);

İyi fikir, bunun var olduğunun farkında değildim. Paylaşım için teşekkürler!
Keith P

3

Belki şöyle bir şey kullanabilirsin

interface EnumWithId {
    public int getId();

}


enum Foo implements EnumWithId {

   ...
}

Bu, hizmet sınıfınızdaki yansıtma ihtiyacını azaltacaktır.


Bu pasajın nasıl kullanılacağına dair bir örnek verebilir misiniz?
IgorGanapolsky

3

Bu kodda, kalıcı ve yoğun arama için, kullanım için hafıza veya işlem var ve indeks olarak dönüştürücü dizi ile belleği seçiyorum. Umarım yardımcı olur

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]];
}
}

2

Kimin patron olduğunu göstermek için bir arayüz kullanın.

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);
  }
}

Ve sonuç:

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>

1
Tıpkı Turd Ferguson'un cevabında olduğu gibi, kaçınmak / iyileştirmek istediğim şık olmayan çözüm bu ...
sleske

İd ile bir değer istediğim her seferinde değerler () üzerinde döngü yapmak zorunda kalmamak için genellikle bir statik {} bloğunda ters eşlemeler oluştururum. Ayrıca, Strings için zaten var olan valueOf (String) yöntemi gibi görünmesini sağlamak için genellikle valueOf (int) yöntemini çağırırım (ayrıca OP'nin sorusunun bir parçası). Etkili Java'daki 33. maddeye benziyor: tinyurl.com/4ffvc38
Fredrik

@Sleske Daha rafine bir çözümle güncellendi. @Fredrik ilginç, yinelemenin önemli bir sorun olacağından şüphem olsa da.
corsiKa

@glowcoder Pekala, birden fazla yineleme yapmak zorunda olmamak, bunu saniyede bin kez yapıp çok önemli bir sorun olabileceği veya sadece iki kez çağırmanızın önemli olmadığı anlamına gelir.
Fredrik

@Fredrik, optimize etmenin gerekli olabileceği zamanlar olduğunu kabul ediyorum. Ayrıca, tanımlanmış bir performans sorunu olana kadar bunun için optimize etmeyin.
corsiKa

2

Hem .ordinal()vevalues()[i]Numaralandırma sırasına bağlı olduklarından de kararsızdır. Bu nedenle, numaralandırmaların sırasını değiştirirseniz veya bazılarını ekler / silerseniz programınız bozulur.

İşte enum ve int arasında eşleştirmek için basit ama etkili bir yöntem.

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");
    }
}

Bunu dizeler için uygulamak zor olmamalı.


Evet, bunu yapabileceğimin farkındayım - ya da daha iyisi, tüm değerleri yinelemek yerine tersine arama için bir harita kullanıyorum. Bundan sorumda bahsetmiştim ve ayrıca her enumda standart kodlardan kaçınmak için daha iyi bir çözüm aradığımı da belirtmiştim.
sleske

2

Ters Enum'un çok temiz bir kullanım örneği

Adım 1 Bir interfaceEnumConverter Tanımlayın

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

Adım 2

ReverseEnumMap sınıf adı oluşturun

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);
    }
}

Aşama 3

Eğer gidin Enumsınıf ve implementonunla EnumConverter<ContentType>ve ders geçersiz kılma arabirim yöntemleri. Ayrıca statik bir ReverseEnumMap'i de başlatmanız gerekir.

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);
    }
}

4. adım

Şimdi bir oluşturmak Communicationsınıf dosyası ve bir dönüştürmek için yeni bir yöntemdir çağırmak Enumiçin Stringve Stringiçin Enum. Açıklama amaçlı ana yöntemi koydum.

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)
    }
}

Tam açıklama için tıklayınız.


1
Bunu gerçekten çok beğendim - Bir süredir bu soruna sağlam bir çözüm arıyorum. Yaptığım tek değişiklik ContentType convert(String pKey), Communicationsınıfa olan ihtiyacı ortadan kaldıran ve daha çok hoşuma giden statik yapmaktı . +1
Chris Mantle

1

Java'da da aynı olup olmadığından emin değilim, ancak C'deki enum türleri de otomatik olarak tamsayılarla eşleştirilir, böylece ona erişmek için tür veya tamsayı kullanabilirsiniz. Henüz tamsayı ile erişmeyi denediniz mi?


2
Java'daki numaralandırmalar bu şekilde davranmaz. Açık bir tipler.
Chris Thompson

Her bir numaralandırma nesnesinin bir dahili numarası (yani bildirildiği konum) olacaktır ve bu numaraya .ordinal()yöntemle erişilebilir . (Diğer şekilde kullanın BonusType.values()[i].) Ancak yukarıda belirtilen örnekte, buradaki dizinler ve dış değerler çakışmaz.
Paŭlo Ebermann

1

Gerçekten harika bir soru :-) Bir süre önce Bay Ferguson'unkine benzer bir çözüm kullandım. Ayrıştırılmış numaramız şuna benzer:

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
        });
    }
}

Bunu görmek, neden ordinal()kararsız olduğu açıktır . Öyle ide super(s, i);. Ayrıca, daha önce sıraladıklarınızdan daha zarif bir çözüm düşünebileceğiniz konusunda da karamsarım. Sonuçta numaralandırmalar, final sınıfları olarak sınıflardır.


1

Tamlık uğruna, burada herhangi bir enum türünden dizine göre enum değerlerini almak için genel bir yaklaşım vardır. Niyetim, yöntemin Enum.valueOf (Class, String) gibi görünmesini ve hissetmesini sağlamaktı . Fyi, bu yöntemi buradan kopyaladım .

Endeksle ilgili sorunlar (burada ayrıntılı olarak tartışılmıştır) hala geçerlidir.

/**
 * 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];
}

Bu gerçekten aradığım şey değil, çünkü bu yalnızca enum değerlerini atanmış bir tamsayı kimliği ile değil, sıralarına göre alır (soruma bakın). Ayrıca, eğer bunu istersem, sadece kullanabilirim MyEnumType.values()- statik bir yardımcı yönteme gerek yok.
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);
            }
        }

0

Farklı bir şeye ihtiyacım vardı çünkü genel bir yaklaşım kullanmak istiyordum. Bayt dizilerine giden ve gelen numaralandırmayı okuyorum. Buraya geldiğim yer:

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.
}
}

Enum örnekleri:

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;
    }
}

0

Kabul edilen yanıt kendi kendine yetmediği için:

Destek kodu:

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);
    }
}

Kullanım örneği:

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);
    }

}

0

verilen:

genel numaralandırma BonusType {MONTHLY (0), YEARLY (1), ONE_OFF (2)}

BonusType bonusu = YILLIK;

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

Çıktı: 1: YEARLY


0

Sınıf Arabanız Varsa

public class Car {
    private Color externalColor;
}

Ve Color özelliği bir sınıftır

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

Ve Rengi bir Enum'a dönüştürmek istiyorsunuz

public class CarDTO {
    private ColorEnum externalColor;
}

Basitçe bir yöntemi ekleyin Renk dönüştürmek için sınıfta Renk içinde ColorEnum

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

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

ve ColorEnum içinde getById () yöntemini uygular

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

Artık bir classMap kullanabilirsiniz

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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.