# Generics?



## Wyvern (18. Jan 2007)

Bekomme für folgende Codezeile:

```
HashMap<String,String> hash = (HashMap)request.getAttribute("messages");
```

Die Warnung


> Type safety: The expression of type HashMap needs unchecked conversion to conform to HashMap<String,String>



Was will man mir damit sagen? Ich mein, es läuft, und funktioniert. Aber man will ja was lernen.

(Java Version 1.5.0_09-b03)


----------



## Beni (18. Jan 2007)

Eine normale "Hashmap" ist eben keine "Hashmap<String,String>", der korrekte Cast würde lauten:

```
HashMap<String,String> hash = (HashMap<String, String>)request.getAttribute("messages");
```

Wahrscheinlich gibt es jetzt irgendeine andere Warnung, aber darum ging es ja nicht :wink:


----------



## Guest (19. Jan 2007)

Das hab ich mir auch schon mal gedacht. Das hab icha uch schon mal so gemacht. Aber es läuft so und so. 

Bei der Zeile 

```
HashMap<String,String> hash = (HashMap<String,String>)request.getAttribute("messages");
```

Bekomme ich die Warnmeldung:


> Type safety: The cast from Object to HashMap<String,String> is actually checking against the erased type HashMap



Also ist es nicht viel besser als vorher.  :wink:


----------



## Wyvern (19. Jan 2007)

Letztes Post war von mir. Ich hab mich jetzt doch mal angemeldet.


----------



## Beni (19. Jan 2007)

Naja, ein Cast ist *immer* unsicher, also sollte es auch *immer* eine Warnung geben... ignorieren!


----------



## Wyvern (19. Jan 2007)

Nach längerem Googeln hab ich nun die (oder zumindest eine mögliche) Lösung zu diesem Problem gefunden. 

Das grundsätzliche Problem an der ganzen Geschichte liegt darin, daß der Compiler aus dem Request nur ein Objekt bekommt. Also sagt er, daß er zur Laufzeit nur checken kann, daß das eine HashMap wird. Aber ob da jetzt wirklich 2 Strings ankommen weiß er nicht. Das muß er dem Programmierer einfach glauben. 
Als Programmierer würd ich sagen: "Glaubs mir einfach." Aber damit gibt er sich ja nicht zufrieden. Also muß man nun abprüfen, ob wirklich 2 Strings kommen.

Aus der Zeile 
	
	
	
	





```
HashMap<String,String> hash = (HashMap<String,String>)request.getAttribute("messages");
```
wird 
	
	
	
	





```
HashMap<String,String> hash = checkMessages(request.getAttribute("messages"));
```

und ich hab eine Methode zum checken des Typs geschrieben:

```
/**
	   * Check the message object for HashMap of String objects.
	   * @param obj to check
	   * @return HashMap of Strings
	   */
	  private static HashMap<String,String> checkMessages(Object obj) {
		HashMap message = (HashMap) obj;
		HashMap<String,String> result = null;
		if (message != null) {
	      result = new HashMap<String,String>();
	      for (Iterator<?> itKey = message.keySet().iterator(); itKey.hasNext();) {
	    	  result.put(""+itKey,(String) message.get(itKey));
	      }
	    }
	    return result;
	  }
```

So, ich glaub es wohl auch weniger umständlich, aber zumindest kommen keine Warnings mehr.  ???:L


----------



## Beni (19. Jan 2007)

Naja... also da übersteigen die Kosten (Kopie einer Map machen, der Code an sich) die Gewinne (eine _Warnung_ weniger) doch erheblich... zumal dir da nicht jeder Depp eine (falsche) Map unterschieben kann?


----------



## Wyvern (22. Jan 2007)

Die Messages kommen aus den ApplicationRessources.properties. Daher kann mir keiner ne falsche Message unterjubeln. Die betreffende Hashmap hat auch immer nur einen Eintrag, und das Kopieren nimmt nicht übermäßig viel weg. 

Ich habe mir zur Angewohnheit gemacht, möglichst ohne Warnings zu programmieren. Ich halte das für guten Programmierstil. Auch wenn es vielleicht nicht so effizient ist.


----------



## KSG9|sebastian (22. Jan 2007)

Guter Programmierstil hin oder her.
Besser ne Warning als Overhead ohne Ende. 
Und wenn du ne Anwendung entwickelst auf die 2000Leute+ gleichzeitig zugreifen dann sind die "paar bytes" schnell mal "paar ganz viele bytes".
Ne Map so zu kopieren, mit Stringverkettung u.s.w. ist u.U. sehr performance-fressend.


----------



## Wyvern (22. Jan 2007)

Edit: überflüssig


----------



## Leroy42 (22. Jan 2007)

Wyvern hat gesagt.:
			
		

> Ich habe mir zur Angewohnheit gemacht, möglichst ohne Warnings zu programmieren. Ich halte das für guten Programmierstil.


Das sehe ich genauso.


			
				Wyvern hat gesagt.:
			
		

> Auch wenn es vielleicht nicht so effizient ist.


Das nun wieder überhaupt nicht.

Im Übrigen finde ich die Warnung



			
				WasWeißDennIchWer hat gesagt.:
			
		

> The cast from Object to HashMap<String,String> is actually checking against the erased type HashMap



schon recht übertrieben; vor allem, wenn man sie _ohne Algorithmusänderung_ nicht wegbekommt,
sogar in gewisser Weise sinnlos (wenn nicht gar fehlerhaft)


----------



## sco (22. Jan 2007)

Leroy42 hat gesagt.:
			
		

> WasWeißDennIchWer hat gesagt.:
> 
> 
> 
> ...




Einer der Gründe, warum manche sagen, dass Generics ein 'Pfusch' sei ...
probiert mal folgendes:

```
class ASet<E> { //Menge mit Array-Repräsentation
public class ASet<E> {

	private E[] elements;


	public ASet(int capacity) {	
		elements = new E[capacity]
	}
}
```

Generics sind zum Haareraufen. Das obige Beispiel läuft nicht, man kann kein Array erzeugen, das nen generischen Typ hat.


```
elements = (E[])new Object[10];
```

das klappt hingegen, aber bedeutet auch ne Warnung.

Und dann kommt das Beste zum Schluss:
Kompiliert man sein Programm. das Generics verwendet, dann wandelt der Compiler im Bytecode alles zu casts um, was Generic war - sah ich beim Decompilieren.
Diese Fälle hier im Thread sind nur zwei der vielen, die auftreten können - gibt aber allgemein viele unerwartete Seiteneffekte, etc.

Die Überlegungen über dieses Feature sind zwar gut ... aber in der Praxis kommts mir manchmal schon so vor, als wärs nicht das Wahre.


----------



## Beni (22. Jan 2007)

```
elements = (E[])new Object[10];
```
Damit lassen sich so lustige Sachen wie "String[] elements = new Object[10]" basteln... das Teil ist eine Zeitbombe die irgendwann per ClassCastException explodiert.

Ich setz Generics ein, seit 1.5 erhältlich ist. Urteil: eine der besseren Ideen die Sun da hatte, und zwar weil es aktiv hilft Fehler zu vermeiden (wenn man sie nicht absichtlich programmiert, siehe oben :bae: ). Dass man damit nicht *alles* lösen kann, tut dem keinen Abbruch. :wink:


----------



## Gast (23. Feb 2007)

Wenn euch Warnungen stören, dann verwendet doch vor der Methode die Annotation:


```
@SuppressWarnings("unchecked")
```

(Syntax nicht auf Korrektheit geprüft)


----------



## KSG9|sebastian (23. Feb 2007)

Genenerics sind imho solang nützlich wie man sich rein in den eigenen Klassen bewegt. Sobald externe Quellen dazukommen (Webanwendungen) wird's ziemlich nutzlos da du nur Warnungen hast. Die einzige "Lösung" ist eben dieses SuppressWarnings.

Insgesamt sind Generics nichts halbes und nix ganzes (meine Meinung). Genau dasselbe wie Autoboxing. An sich schön und gut, aber u.U. auch ne wahre Zeitbombe.


----------

