# Methode für generische enummap/enum



## dermoritz (24. Sep 2010)

Ich kriege es irgendwie nicht hin eine Methode zu basteln die eine EnumMap ausgibt und ein enum als Parameter hat. Der Parameter gibt sozusagen den Typ des zurückgegeben enums vor.

Der Kopf der Methode sieht so aus:

```
private EnumMap<?, String> tuWas(Enum<?> enumI, String zeile)
```
als erstes müsste ich den Typ des gegebenen Enums rauskriegen, aber daran scheitere ich (enumI.class funzt nicht). Geht das irgendwie?


----------



## Der Müde Joe (24. Sep 2010)

```
private <T extends Enum<T>> EnumMap<T, String> tuWas(T enumI, String zeile) {
    return null;
}
```

so?


----------



## dermoritz (24. Sep 2010)

Danke das hat schonmal etwas geholfen . nur kann ich jetzt nicht über die werte (values()) von enumI iterieren?! Ich glaube enumI ist eine Enum-Konstante und nicht der Enumtyp. Den ich hab so Methoden wie "name" und "ordinal".  Also die Methode soll genrisch auf einer "EnumKlasse" operieren.

Andererseits fällt mir gerade ein, das es etwas zu generisch ist. Letztendlich habe ich einige lokale (String)enums mit denen die Methode funktionieren soll. All diese Enums haben eine Funktion, welche den Stringwert zurückgibt. Damit könnte ich ein Interface basteln und die angesprochene Methode würde so aussehen:

```
private EnumMap<StringEnum, String> tuWas(StringEnum enumI, String zeile)
```
Das funktioniert aber leider nicht, denn eine EnumMap kann nicht mit einem Interface gebastelt werden. Das Interface sieht so aus:

```
public interface StringEnum {
		public String getString();
	}
```
Also gibt es irgendeine Variante eine Methode generisch für verschiedene Enum-Klassen(die ein Interface implementieren) zu basteln und eine EnumMAp zurückgibt?


----------



## Der Müde Joe (24. Sep 2010)

Nein.

Eine Enum ist nichts anderes als eine Klasse, welche:
- von Enum erbt


```
The direct superclass of an enum type named E is Enum<E>.
```

- final ist 


```
An enum type is implicitly final unless it contains at least one enum constant
```


```
that has a class body. In any case, it is a compile-time error
```


```
to explicitly declare an enum type to be final.
```

und noch anderes Tolles hat...

Classes

EDIT:
Und ne EnumMap will halt genau die <K extends Enum<K>> und nicht was anderes ;-)


----------



## SlaterB (24. Sep 2010)

siehe noch folgendes Beispiel:


```
public class Test {
    public static void main(String[] args)  {
        Map map = null;
        map = tuWas(A.class);
        map = tuWas(B.class);
    }

    private static <T extends StringEnum>Map<T, String> tuWas(Class<T> eClass)  {
        Map<T, String> map = new HashMap<T, String>();
        for (T t : eClass.getEnumConstants())  {
            map.put(t, "mapper " + t.getString());
        }
        return map;
    }
}

interface StringEnum {
    public String getString();
}

enum A     implements StringEnum {
    B, C;
    public String getString()   {
        return "hello " + name();
    }
}

class B  implements StringEnum {
    public String getString()
    {
        return "hello ";
    }
}
```
leider lässt sich soweit ich es auf die Schnelle überblicke, nicht verhindern, dass auch normale Klasse,
die das Interface implementieren, von der Methode angenommen werden

edit:
> private static <T extends Enum<T> & StringEnum>
hilft anscheinend


----------



## dermoritz (24. Sep 2010)

gibt es irgendeine andere Möglichkeit vielleicht ohne Interface? Oder muss ich die Methode für jeden Enum-Typ implementieren? Was ich eben auch nicht verstehe ist, warum in deiner vorgeschlagenen Lösung nicht "enumI.class.getEnumConstants()" nicht funktioniert?! Mit "normalen" enums geht das ja.

Edit: slater ich hab dein Beitrag zu spät entdeckt. Eigentlich wollte ich eben gerne mit EnumMap arbeiten - das soll besonders effizient sein. Aber am wichtigsten wäre mir, dass ich weiß das die Schlüssel enums sind.

Edit2: Slater dein Konstrukt funktioniert (nix mehr rot) - danke. Nun wäre noch die Frage ob ich jemals wieder von T zu einem Enum komme - bzw irgendwann hätte ich gerne eine (Enum)Map bei der ich mit EnumSchlüsseln an die Werte komme?!


----------



## SlaterB (24. Sep 2010)

EnumMap habe ich in meinem Beispiel nicht geschrieben, weil ich das nicht kenne,
kannst du machen wie du willst, 

ich habe von deinem Satz
> gibt es irgendeine Variante eine Methode generisch für verschiedene Enum-Klassen(die ein Interface implementieren) zu basteln und eine EnumMAp zurückgibt? 
nur 
> gibt es irgendeine Variante eine Methode generisch für verschiedene Enum-Klassen(die ein Interface implementieren) zu basteln? 
beantwortet 

----

und wer sagt, dass enumI.class.getEnumConstants() nicht geht?
bzw es muss enumI.getClass().getEnumConstants() lauten

wobei du besser wie in meinem Beispiel die Class an sich übergeben solltest stats speziell einen Enum-Wert davon,
bei Übernahme null sähe es düster aus (edit: ok, ist bei class == null genauso)


----------



## Der Müde Joe (24. Sep 2010)

suchst du sowas?
blick grad net ganz durch (muss nochmals genau lesen)

```
private <T extends Enum<T> & SomeIF> EnumMap<T, String> tuWas(Class<T> clazz, String zeile) {
    if(clazz != null) {
        T[] t = clazz.getEnumConstants();
        EnumMap<T, String> result = new EnumMap<T, String>(clazz);
        //do some stuff
        result.put(t[0], t[0].name());
        return result;
    }
    throw new IllegalArgumentException("peng");
}

interface SomeIF{}
```

EDIT:
oh...des hat ja SlaterB schon geschrieben


----------



## dermoritz (24. Sep 2010)

lange Rede kurzer Sinn, ich glaube Ihr habt mich "gerettet"  Müder Jow danke für "<T extends Enum<T>>", Slater danke für "Class<T>" damit geht es wie folgt:


```
private  <T extends Enum<T>> EnumMap<T, String> tuWas(Class<T> enumI, String zeile){
		EnumMap<T, String> out = new EnumMap<T, String>(enumI);
		for(T t : enumI.getEnumConstants()){
			StringEnum blub = (StringEnum)t;
			out.put(t, "");
		}
		return null;
		
		
	}
```
Falls es jemand interessiert: ich bin gerade dabei einen "Parser" für ein spezielles Textformat zu schreiben. Dieses Textformat hat verschiedene "Sorten" von Zeilen - je nach Sorte erwartet man andere "Tags" (z.B. [Date]). Für jede Sorte Zeile hab ich ein Enum dieser speichert zum Beispiel Datum("[Date]"). so sieht so ein enum ca aus:

```
public enum KopfZeileTags implements StringEnum{
		Date("[Date]"),
                private String tag;
		private KopfZeileTags(String tag) {
			this.tag = tag;
		}
		public String getTag() {
			return tag;
		}
	}
```
Der Parser geht nun Zeilenweise durch die Datei und entscheidet welche Sorte Zeile es ist. Diese Zeile kann nun immer ein und der selben Methode gegeben werden - eben die um die es hier geht. Das praktische ist so können problemlos zusätzliche Zeilensorten hinzukommen aber auch zusätzliche Tags innerhalb der Zeilen. Und am Code muss man kaum was ändern.

EDIT: das sowas geht "<T extends Enum<T> & StringEnum>" wusst ich gar nicht - genial. damit kann ich mir den cast sparen


----------



## Der Müde Joe (24. Sep 2010)

Den 
	
	
	
	





```
StringEnum blub = (StringEnum)t;
```
kriegst du durch:

```
<T extends Enum<T> & StringEnum>
```
 raus.
Dann geht auch automatisch ein getTag ;-)

EDIT:
hehe...selbst erkannt... :toll:


----------



## SlaterB (24. Sep 2010)

wie wir beide inzwischen geschrieben haben:
verwende <T extends Enum<T> & StringEnum>
dann musst du nicht mehr casten und es können keine falschen Enums übergeben werden

edit: Hattrick


----------

