Generics?

Status
Nicht offen für weitere Antworten.
W

Wyvern

Gast
Bekomme für folgende Codezeile:
Code:
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)
 
B

Beni

Gast
Eine normale "Hashmap" ist eben keine "Hashmap<String,String>", der korrekte Cast würde lauten:
Code:
HashMap<String,String> hash = (HashMap<String, String>)request.getAttribute("messages");

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

Guest

Gast
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
Code:
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:
 
B

Beni

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

Wyvern

Mitglied
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
Code:
HashMap<String,String> hash = (HashMap<String,String>)request.getAttribute("messages");
wird
Code:
HashMap<String,String> hash = checkMessages(request.getAttribute("messages"));

und ich hab eine Methode zum checken des Typs geschrieben:
Code:
/**
	   * 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
 
B

Beni

Gast
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

Mitglied
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

Top Contributor
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.
 

Leroy42

Top Contributor
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

Mitglied
Leroy42 hat gesagt.:
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)


Einer der Gründe, warum manche sagen, dass Generics ein 'Pfusch' sei ...
probiert mal folgendes:
Code:
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.

Code:
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.
 
B

Beni

Gast
Code:
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:
 
G

Gast

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

Code:
@SuppressWarnings("unchecked")

(Syntax nicht auf Korrektheit geprüft)
 

KSG9|sebastian

Top Contributor
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.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben