generische Enum

celph_titled

Erfahrenes Mitglied
Hallo,

ich habe eine Klasse, die Metadaten von Liedern enthält, also Titel, Interpret usw.
Die Werte sind in einer HashMap gespeichert und die möglichen Schlüssel in der Unterklasse 'Field'. Die Daten haben unterschiedliche Typen (z.b. Titel als String, Tracknummer als Integer) und ich will nicht für jeden eine eigene get-Funktion schreiben.
Das müsste wahrscheinlich mit was generischem zu lösen sein, so dass getValue() immer den Typ des Feldes zurück gibt.
Ich dachte da an sowas:
Code:
public class Metadata {
     public static class <T> Field<T> {
          public static final Field<String> ARTIST = new Field<String>();
          public static final Field<String> TITLE = new Field<String>();
          public static final Field<Integer> TRACKNUMBER = new Field<Integer>();
          private Field() {
          }
     }

     private final Map<Field<T>,T> map = new HashMap<Field<T>,T>();

     public T getValue(Field<T> field) {
          return map.get(field);
     }
}

Gibt es statt der 'Field'-Klasse jetzt irgendeine Möglichkeit eine Enum zu benutzen? Ich steh da ein bisschen auf dem Schlauch :( eine generische Enum wie "public static enum Field<T>" scheint ja nicht möglich zu sein.

Ich hab den Verdacht, dass das Thema was hiermit zu tun hat:
http://www.tutorials.de/java/351335-api-experiment-generische-datenmodelle-mit-getyptem-zugriff.html
nur steig ich da nicht ganz durch, vor allem mit den ganzen Annotations.

Dankeschön im Voraus
 
Meinst Du vielleicht soetwas?!

Java:
import java.util.HashMap;
import java.util.Map;

public class MetaDataTest {

    private enum Field {
        ARTIST, TITLE, TRACKNUMBER
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        Map<Field, String> data = new HashMap<Field, String>();
        data.put(Field.ARTIST, "Grönemeyer");
        String artist = data.get(Field.ARTIST);
        System.out.println(artist);
    }

}
 
Zuletzt bearbeitet von einem Moderator:
Naja, das Problem ist, dass nicht alle Einträge Strings sein sollen. Es sollen auch andere Typen möglich sein, aber immer abhängig von dem Field, z.B. Tracknummer als Integer.

Um es genauer zu sagen: die Klasse des Values in der Map soll von dem Key abhängig sein.
 
Zuletzt bearbeitet:
Achso, jetzt ist mir klar was du meinst. Ja, das Beispiel von Thomas sieht zumindest danach aus. So wie ich das sehe, kann eine ENUM durchaus von einem Interface ableiten. In dem Interface definiert man dann den Typ des "Feldes", also Artist > String, Tracknumber > Integer.

Dann erstellt man sich eine eigene (Map-)Klasse, welche put- und get-Methoden zur Verfügung stellt und als Parameter immer die spezifische enum erwartet.

Ich habe versucht mit dem Code von Thomas mal ein Beispiel zusammenzustellen. Bei mir hats funktioniert, allerdings prüfe ich zB nicht auf Typsicherheit. Also wenn Du als Tracknumber einen String setzt, gibt es eine ClassCastException.

Java:
public interface IFieldType {

    Class<?> type();
}

Java:
public enum Field implements IFieldType {
    ARTIST(String.class), TITLE(String.class), TRACKNUMBER(Integer.class);

    private Class<?> type = null;

    private Field(Class<?> type) {
        this.type = type;
    }

    public Class<?> type() {
        return type;
    }
}

Java:
public class MetaDataMap {

    private Map<String, Object> map = null;

    public MetaDataMap() {
        this.map = new HashMap<String, Object>();
    }

    public <T> T get(Field field) {
        return (T) get(field.name(), field.type());
    }

    private <T> T get(String name, Class<T> clazz) {
        Object o = map.get(name);
        if (o != null) {
            return (T) o;
        }
        return null;
    }

    public void put(Field field, Object value) {
        map.put(field.name(), value);
    }
}

Java:
public class MetaDataTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        MetaDataMap data = new MetaDataMap();
        data.put(Field.ARTIST, "Grönemeyer");
        data.put(Field.TITLE, "Mensch");
        data.put(Field.TRACKNUMBER, new Integer(13));
        String artist = data.get(Field.ARTIST);
        String title = data.get(Field.TITLE);
        Integer track = data.get(Field.TRACKNUMBER);
        System.out.println("artist=" + artist);
        System.out.println("title=" + title);
        System.out.println("track=" + track);
    }

}
 
Zuletzt bearbeitet von einem Moderator:
Super, so hab ich es mir vorgestellt. Man hat zwar einen unchecked cast drin, aber das ich ja nicht weiter schlimm.
Vielen Dank
 
Zurück