2016-08-29 3 views
6

मेरे पास कई enums हैं जो एक int द्वारा पाया जा सकता है। यह enum पर एक स्थिर विधि द्वारा किया जाता है। उदाहरण के लिए:इंटरफेस में स्टेटिक विधियां काम नहीं कर रही हैं, कई enums से विशिष्ट enum मूल्य कैसे प्राप्त करें?

enum Foo { 
A, B, C, D, ... ; 
    public static Foo fromInt(int i) { 
    switch(i) { 
    case 15: return A; 
    case 42: return B; 
    ... 
} 
} 
enum Bar { 
BLA, BOO, BEE, ... ; 
    public static Bar fromInt(int i) { 
    switch(i) { 
    case 78: return BLA; 
    case 22: return BOO; 
    ... 
} 
} 
... 

अब कुछ कोड में मैं एक सामान्य प्रकार T कि इन enums के होने की गारंटी है है और मैं एक पूर्णांक i है। मैं fromInt विधि को कैसे कॉल कर सकता हूं और मूल्य i द्वारा enum का उदाहरण प्राप्त कर सकता हूं?

मैंने स्थिर विधि fromInt के साथ एक इंटरफ़ेस बनाने का प्रयास किया है और enums इसे लागू करने दें, लेकिन स्थैतिक विधियां इंटरफेस में काम नहीं करती हैं।

मैं जावा 8.

+0

प्रतिबिंब के बारे में क्या? –

+0

तो आपके पास कहीं 'कक्षा 'चर है, है ना? क्या आप इस सामान्य प्रकार के साथ अपना कोड प्रदान कर सकते हैं? – sp00m

+2

क्या आप गारंटी देते हैं कि 'Foo' और' Bar' में 'int' मानों के सेट अलग हैं? – bradimus

उत्तर

2

लघु जवाब उपयोग नहीं कर सकते आप नहीं

लांग जवाब आपको लगता है कि enum की Class पारित कर सकते हैं कर सकते हैं या तो अपने विधि के लिए और प्रतिबिंब द्वारा fromInt आह्वान या कारखाने इंटरफ़ेस बना सकते हैं और अपने प्रत्येक enum के लिए इसे लागू करें और फिर अपनी विधि के लिए सही उदाहरण पास करें।

0

विस्तार @talex's answer:

चिंतन:

public class YourEnumFactory { 

    public static <T extends Enum<T>> T get(Class<T> type,int i) { 
    try { 
     return (T) type.getDeclaredMethod("fromInt", int.class).invoke(null, i); 
    } catch (Exception e) { 
     throw new IllegalStateException("Could not find instance of '" + type + "' given '" + i + "'", e); 
    } 
    } 

} 

कारखानों:

public class YourEnumFactory { 

    private interface Factory<T> { 
    T fromInt(int i); 
    } 

    private static final Map<Class<?>, Factory<?>> FACTORIES; 
    static { 
    Map<Class<?>, Factory<?>> factories = new HashMap<>(); 
    factories.put(Foo.class, new Factory<Foo>() { 

     @Override 
     public Foo fromInt(int i) { 
     return Foo.fromInt(i); 
     } 

    }); 
    factories.put(Bar.class, new Factory<Bar>() { 

     @Override 
     public Bar fromInt(int i) { 
     return Bar.fromInt(i); 
     } 

    }); 
    FACTORIES = Collections.unmodifiableMap(factories); 
    } 

    public static <T extends Enum<T>> T get(Class<T> type, int i) { 
    Factory<T> factory = (Factory<T>) FACTORIES.get(type); 
    if (factory != null) { 
     return factory.fromInt(i); 
    } else { 
     throw new InvalidParameterException("No factory for type '" + type + "'"); 
    } 
    } 

} 

मैं हमेशा प्रतिबिंब से बचने की कोशिश के रूप में, मैं व्यक्तिगत रूप से दूसरा समाधान का चयन करेंगे।

0

आप ऐसा नहीं कर सकते, लेकिन मैं इसे इस तरह करना होगा:

interface HasId() { 
    public int getId(); 
} 

public class MyRegistry { 
    private static Map<Class<?>, Map<Integer, Object>> REGISTRY = new HashMap<>(); 
    public static <T extends HasId> T fromInt(int id, Class<T> clazz) { 
     return clazz.cast(REGISTRY.getOrDefault(clazz, Collections.emptyMap()).get(id)); 
    } 
    public static void register(HasId obj) { 
     REGISTRY.putIfAbsent(obj.getClass(), new HashMap<>()).put(obj.getId, obj); 
    } 
} 

enum Foo implements HasId { 
    A(15), B(42), C(86), D(99); 
    private final int id; 
    Foo(int id) { 
     this.id = id; 
     MyRegistry.register(this); 
    } 
    public int getId() { 
     return id; 
    } 
} 
// ditto for other enums or non enums as you like 

तब उपयोग करने के लिए:

Foo foo = MyRegistry.fromInt(15, Foo.class); // A 

अस्वीकरण: कोड संकलन या यह के रूप में काम नहीं कर सकते हैं मेरे फोन पर थंब गया था (लेकिन यह एक उचित मौका है कि यह काम करेगा)

+0

ध्यान दें कि 'putIfAbsent' जिस तरह से आप अपेक्षा करते हैं उस पर काम नहीं करता है (यह' computeIfAbsent' की तरह नहीं है)। 'putIfAbsent' हमेशा पुराना मान देता है, यानी' शून्य 'अगर पिछले मैपिंग और पिछले (अभी भी मौजूद) मूल्य अन्यथा नहीं था। इसके अलावा, यह थ्रेड सुरक्षित मानचित्र का उपयोग करने में मदद नहीं करता है, जब इसमें गैर-थ्रेडसेफ 'सेट' को बिना किसी सुरक्षा के एक्सेस किया जाता है। – Holger

+0

इसके अलावा, कोड वास्तविक 'enum' प्रकार के वर्ग प्रारंभिक पर निर्भर करता है जिसकी गारंटी नहीं है। दूसरी तरफ, पंजीकरण की आवश्यकता को खत्म करने, enum मूल्यों को प्रतिबिंबित करने से 'INT' को फिर से चालू करना आसान होगा। – Holger

+0

@ होल्गर कॉल में पारित कक्षा शाब्दिक होने के कारण enum प्रारंभिक गारंटी नहीं है? – Bohemian

संबंधित मुद्दे