2013-04-25 4 views
7

Ich hätte gerne eine Klasse, die die EnumMap emuliert, aber Int-Werte statt irgendeiner Art von Objekt speichert. Jetzt könnten Sie natürlich eine EnumMap erstellen, die auf Integer abgebildet wird, aber das ist eine Menge Autoboxing, die ich vermeiden möchte, wenn es möglich ist.Zugriff auf die .values ​​() - und .ordinal() -Methode einer beliebigen Enumeration?

Also würde ich eine Klasse wie folgt erhalten:

public class EnumIntAttributeMap 
{ 
    enum Attribute 
    { 
     Height, Weight; 
    } 

    private final int[] values; 

    public EnumIntAttributeMap() 
    { 
     this.values = new int[Attribute.values().length]; 
    } 

    public int getValue(Attribute a) 
    { 
     return this.values[a.ordinal()]; 
    } 

    public void setValue(Attribute a, int value) 
    { 
     this.values[a.ordinal()] = value; 
    } 
} 

Außer, dass ich eine Version vornehmen möchten, die auf allen Aufzählungen generic ist. Jetzt, da die Methoden .values ​​() und .ordinal() vom Compiler implizit hinzugefügt werden, scheint es, als wäre die einzige Möglichkeit, auf sie zuzugreifen, die Reflektion, die die Leistungsgewinne aufzehren würde, die ich zu vermeiden versuche Auto-Boxen, aber vielleicht gibt es etwas, das ich vermisse.

Irgendwelche Gedanken?

EDIT:

Ich glaube, meine erste Frage war unklar. Ich möchte eine Klasse, die (als generischer Parameter) eine Aufzählung akzeptiert und dann dieselben Operationen verwenden kann.

So könnte ich es mit jeder Art von enum verwenden, ohne die Klasse für jede Art von enum jedes Mal schreiben zu müssen. Wie zum Beispiel:

enum Attribute { Height, Weight } 

enum AbilityScore {Str, Dex, Con, Int, Wis, Cha} 

IdealClass<Attribute> attributeVersion; 

IdealClass<AbilityScore> abilityScoreVersion; 

und so weiter.

+0

Wenn Ihre 'int'-Werte klein sind, dh im Cache, wird dies keinen Unterschied machen (BTW können Sie die Größe des Cache erhöhen). Wenn Sie jedoch int-Werte groß sind, könnte es Ihnen etwas Speicher/Müll. –

+0

Ich sah, dass Sie den Integer-Cache mit einem Befehlszeilenargument erweitern können. Gibt es eine Möglichkeit, dies zu tun, nachdem das Programm aus dem Programm gestartet wurde? – Lokathor

Antwort

9

Dies ist eine Lösung:

public class EnumIntMap<E extends Enum<E>> { 

    private final int[] values; 

    public EnumIntMap(Class<E> cls) 
    { 
     this.values = new int[cls.getEnumConstants().length]; 
    } 

    public int getValue(E a) 
    { 
     return this.values[a.ordinal()]; 
    } 

    public void setValue(E a, int value) 
    { 
     this.values[a.ordinal()] = value; 
    } 
} 

Sie müssen die Karte auch mit der Klasse der Enumeration initialisieren.

enum Attribute { Height, Weight } 

enum AbilityScore {Str, Dex, Con, Int, Wis, Cha} 

EnumIntMap<Attribute> attributeVersion = new EnumIntMap(Attribute.class); 

EnumIntMap<AbilityScore> abilityScoreVersion = new EnumIntMap(AbilityScore.class); 
+0

Ach so Das ist, wie du es machst ... Ich hatte versucht, getDeclaringClass() und andere Seltsamkeit zu machen und habe dabei meinen Kopf gegen die Wand geschlagen. Schön. Maba du bist heute mein Liebling. – Lokathor

+0

@ Lokathor Danke :-) – maba

0

Lesen Sie diese: .

Ich glaube, Sie könnten etwas tun, das zu dem Planeten Beispiel ähnelt:

public enum YourEnum{ 
    HEIGHT (0), 
    WIDTH (1); 

    private final int index; 

    YourEnum(int index) { 
     this.index = index; 
    } 
    public int index() { return index; } 
} 
0

Dies ist, was ich persönlich verwenden und gibt mir schöne Standardisierung in den APIs

Common Interface:

public interface IValueEnum<T> {  
    T value(); 
} 

Aufzählungen es wie folgt implementieren:

public enum MyEnum implements IValueEnum<Integer> { 
    WIDTH(1), 
    HEIGHT(2); 

    private final int value; 
    MyEnum(int value) { this.value = value; } 

    @Override 
    public Integer value() { 
     return value; 
    } 
} 

Jetzt können Sie den endgültigen Wert erhalten, indem Sie MyEnum.WIDTH.value() usw. gehen. Da es Generics verwendet, könnten andere Enums Longs oder Strings verwenden oder was Sie haben. Es ermöglicht Ihnen, eine einzelne einfache Enum-basierte Schnittstelle in der Anwendung zu haben. Es ermöglicht auch in Ihrer Karte sein, das Sie ganz allgemein, usw.

EDIT: Basierend auf New Beispiel

public class IdealClass<T extends Enum> { 

    T enumValue; 

    public IdealClass() { 
    } 

} 
+0

Ich benutze bereits die Ordnungszahl der Enumeration als Index, ich möchte das nur für mehr als eine Enum-Art mit derselben Klasse tun können. – Lokathor

+0

@ Lokathor gut mit diesem Ansatz, Sie könnten eine Methode, die getIndex(), um die Schnittstelle hinzufügen, dann können Sie IValueEnum als generischer Typ verwenden ... nein? – Ixx

+0

@Ixx Sie ... könnten? aber das ist praktisch das Gegenteil von dem, was ich wollte. Anstelle einer anpassbaren Map, mit der Sie Enum-Werte auf Ints abbilden können, erhalten Sie eine Reihe von statischen finalen Globals. – Lokathor

1

Alle java Enum implizit java.lang.Enum erweitern, so dass ich denke, was Sie suchen ist:

public class EnumIntAttributeMap<E extends java.lang.Enum<E>> { 
    // [...] 
} 
+0

Aber das gibt Ihnen nur ein E, das Sie dann im Konstruktor nicht mit .values ​​() aufrufen können, um die Array-Länge mit festzulegen. – Lokathor

+0

Sie haben Recht! mabas Antwort adressiert das aber :) – ValarDohaeris

2

Der Schlüssel dieses genetisch zu tun die allgemeine Grenze für eine Enumeration ist, zu wissen:

<T extends Enum<T>> 

Ihre Klasse für jede Enum arbeiten können wie folgt:

public class EnumIntAttributeMap<T extends Enum<T>> { 
    private final int[] values; 
    private final Class<T> clazz; 

    public EnumIntAttributeMap(Class<T> clazz) { 
     this.clazz = clazz; 
     this.values = new int[clazz.getEnumConstants().length]; 
    } 

    public int getValue(T a) { 
     return this.values[a.ordinal()]; 
    } 

    public void setValue(T a, int value) { 
     this.values[a.ordinal()] = value; 
    } 
} 

Beachten Sie, dass Der Konstruktor benötigt einen Token, der aufgrund des Laufzeittyp-Löschvorgangs von Java erforderlich ist.

Verwandte Themen