Discussion:
Konkrete Frage zu 1.5.0 Generics: Dictionary Warnung
(zu alt für eine Antwort)
Alex Tugarev
2004-09-26 15:02:21 UTC
Permalink
Hallo Group,

hier ein Codefragment:
Dictionary di = getDocumentProperties();
di.put("abc", "123");

Jetzt in Java 1.5.0 bekomme ich in der zweiten Zeile die Warnung:
Unsafe type operation: Should not invoke the method put(K, V) of raw type
Dictionary. References to generic type Dictionary<K,V> should be
parameterized


Leider werde ich aus der Dokumentation seit Tagen nicht schlauer:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Dictionary.html

Was bedeutet die Warnung, und was bedeutet der Hinweis in der Dokumentation
"NOTE: This class is obsolete. New implementations should implement the Map
interface, rather than extending this class."?

Mit freundlichen Grüßen

Alex Tugarev
Alex Tugarev
2004-09-26 15:06:13 UTC
Permalink
Post by Alex Tugarev
Hallo Group,
Dictionary di = getDocumentProperties();
di.put("abc", "123");
Unsafe type operation: Should not invoke the method put(K, V) of raw type
Dictionary. References to generic type Dictionary<K,V> should be
parameterized
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Dictionary.html
Was bedeutet die Warnung, und was bedeutet der Hinweis in der Dokumentation
"NOTE: This class is obsolete. New implementations should implement the Map
interface, rather than extending this class."?
Ist das die Zauberlösung?
Dictionary<Object, Object> di = getDocumentProperties();

Wenn ja, bedeutet das doch nur, dass Dictionary in 1.5.0 eine
Kontainerklasse ist? Also geht der Trend in Richtung c++. Hm, na gut. ;)


Mit freundlichen Grüßen

Alex Tugarev
Christian Wederhake
2004-09-26 16:42:02 UTC
Permalink
Post by Alex Tugarev
Post by Alex Tugarev
Dictionary di = getDocumentProperties();
di.put("abc", "123");
Unsafe type operation: Should not invoke the method put(K, V) of raw type
Dictionary. References to generic type Dictionary<K,V> should be
parameterized
[...]
Ist das die Zauberlösung?
Dictionary<Object, Object> di = getDocumentProperties();
Wenn ja, bedeutet das doch nur, dass Dictionary in 1.5.0 eine
Kontainerklasse ist?
Dictonary war nie etwas anderes, zumindest wenn ich "Kontainerklasse"
noch richtig in Erinnerung habe... :-)
Sie wurde jetzt nur um generics erweitert...
Post by Alex Tugarev
Also geht der Trend in Richtung c++. Hm, na gut. ;)
Nicht wirklich, wenn ich mich noch richtig an das C++-Template-System
erinnere, wo iirc ein List<Number> und ein List<String> zwei differente
Klassen waren; bei Java teilen sich alle generischen Ableitungen
einunddieselbe Klasse. Mal ein Beispiel:
Seien deklariert, nicht-null und enthalten min ein Element:
List<String> s0;
List<Number> s1;
List s2;
Folgende Statements sind voellig korrektes und kompilierbares Java:
s2 = s1;
s2 = s0;
s2.set(0, s1.get(0));
s2.set(0, s1.get(0));
Soweit, so uninteressant. Folgendes hingegen ist nicht nur korrekt
kompilierbar, sondern funktioniert auch noch zur Laufzeit:
s1.set(0, (Number) s2.get(0));
s1.set(0, (Number) s2.get(0));
s0.set(0, (String) s2.get(0));
s0.set(0, (String) s2.get(0));
allerdings muss man natuerlich beachten, was in diesem Fall
"funktionieren" bedeutet... Obiger Code wird so funktionieren,
wenn, und nur wenn das Element aus s2 den entsprechenden
Typ hat (ansonsten geht man mit einer CCE baden :-).
Aber es geht noch interessanter:
List s4 = s0;
s4.set(0, s1.get(0));
Hier stecken wir also eine Number in eine List<String>.
Und das beste daran: Das klappt so auch noch. Zur Laufzeit... :-)
Dafuer kompiliert dann zwar natuerlicherweise ein
String test = s0.get(0);
schmiert einem aber mit einer CCE weg... Kein Wunder... Eine
Number ist nunmal kein String... :-)

Der Grund fuer das alles?
Auch wenn ich 2e(5e73) verschiedene Auspraegungen einer
generischen Klasse benutze, gibt es weiterhin nur genau eine
einzige "echte" Klasse in Form einer Class-Instanz.
Diese ist, vereinfacht gesagt, so definiert, das die generic-parameter
durch ihre maximal umfassende Oberklasse ersetzt werden, also
im Zweifelsfalle Object...
Bis auf einige wenige, im Alltag so gut wie nicht auftretende,
Sonderfaelle, ist generics reiner syntaktischer Zucker. Aber diesmal
besonders suesser... :-)

Ciao
Chris
--
"Der Frauen höchstes Ziel muss der hausliche Herd, das Familienleben
bleiben, soll anders die Weltordnung nicht verschoben werden."
(Prof. Dr. med. Franz Riegel *1843)
Michael Paap
2004-09-26 15:16:26 UTC
Permalink
Post by Alex Tugarev
Hallo Group,
Dictionary di = getDocumentProperties();
di.put("abc", "123");
Unsafe type operation: Should not invoke the method put(K, V) of raw type
Dictionary. References to generic type Dictionary<K,V> should be
parameterized
Die Methode getDocumentProperties() liefert in 1.5 vermutlich ein
Dictionary<Object,Object> zurück. Dadurch, dass Du dieses in eine
Variable vom Typ Dictionary wirfst, verwirfst Du mutwillig die
ParametrisierungsInformation. Davor will Dich der Compiler (in diesem
Fall imho überflüssigerweise) warnen.

Vermeiden kannst Du die Warnung vermutlich so:

Dictionary<Object, Object> di = getDocumentProperties();
di.put("abc", "123");

Probiere es mal aus, ich habe noch nicht mit 1.5. gearbeitet und habe
auch keins laufen.

Gruß,
Michael
--
Die Adresse im From existiert, wird aber nicht gelesen. Sollte
eine Mail-Antwort auf ein Posting vonnöten sein, bitte folgende
Adresse verwenden: newsreply@<DOMAIN_AUS_DEM_FROM_DIESES_POSTINGS>.
Michael Holtermann
2004-09-26 15:20:55 UTC
Permalink
Moin Alex!
Post by Alex Tugarev
Dictionary di = getDocumentProperties();
di.put("abc", "123");
Unsafe type operation: Should not invoke the method put(K, V) of raw type
Dictionary. References to generic type Dictionary<K,V> should be
parameterized
Ich mach mal einen Schuss ins Blaue, da ich mich mit Generics noch nicht
befasst habe.

di.get("abc") würde dir ein Object zurückliefern, keinen String. Ab Java
1.5.0 kannst du aber vorher definieren, was in solchen Objekten tatsächlich
drinsteckt. Wenn Du dem Dictionary sagst, es enthält als Keys nur Strings
und als Values nur Häuserblöcke, so bekommst du mit einem get immer exakt
Instanzen dieser Klassen zurück und sparst dir das casten.
Post by Alex Tugarev
Was bedeutet die Warnung, und was bedeutet der Hinweis in der
Dokumentation "NOTE: This class is obsolete. New implementations should
implement the Map interface, rather than extending this class."?
Steht doch da. Die Klasse ist veraltet und wird in einer der nächsten
Versionen als deprecated gekennzeichnet, um dann bei Gelegenheit gestrichen
zu werden.

Du sollst auf eine Klasse ausweichen, die Map implementiert und (wenn ich
das richtig sehe) die gleiche Funktionalität wie Directory anbietet.
Interessant wäre dann z.B. Hashtable, HashMap etc.

Grüße, Michael.
--
"Die Grünen bleiben trotz ihrer pazifistischen Haltung konsequent:
Militäreinsätze ja - aber die Anreise in Krisengebiete mit öffentlichen
Verkehrsmitteln und recyclingfähiger Munition!"
Alex Tugarev
2004-09-26 16:34:18 UTC
Permalink
Post by Michael Holtermann
Post by Alex Tugarev
Was bedeutet die Warnung, und was bedeutet der Hinweis in der
Dokumentation "NOTE: This class is obsolete. New implementations should
implement the Map interface, rather than extending this class."?
Steht doch da. Die Klasse ist veraltet und wird in einer der nächsten
Versionen als deprecated gekennzeichnet, um dann bei Gelegenheit gestrichen
zu werden.
Du sollst auf eine Klasse ausweichen, die Map implementiert und (wenn ich
das richtig sehe) die gleiche Funktionalität wie Directory anbietet.
Interessant wäre dann z.B. Hashtable, HashMap etc.
Ja ja, wörtlich habe ich das auch verstanden. Nur, bevor Sun das hier als
deprecated deklariert (das wird wohl noch ne Zeit lang dauern) sollten die
netten Herren sich erstmal darum kümmern, dass Methoden anderer Swing
Klassen die Dictionaries nicht mehr verwenden. Denn z.B. wird in
javax.swing.text.* hauptsächlich mit Dictionaries hantiert.

Und auf die Lösung mit <Object, Object>-Typisierung bin ich vorher schon
gekommen, wie man lesen kann. Wollte nur wissen, ob ich da nicht aus
Versehen einfach nur die Warnung umgehe, statt das Problem zu lösen.

In diesem Sinne, vielen Dank!

Mit freundlichen Grüßen

Alex Tugarev
Paul Ebermann
2004-09-26 16:55:07 UTC
Permalink
Post by Alex Tugarev
Und auf die Lösung mit <Object, Object>-Typisierung bin ich vorher schon
gekommen, wie man lesen kann. Wollte nur wissen, ob ich da nicht aus
Versehen einfach nur die Warnung umgehe, statt das Problem zu lösen.
Da in der Doku steht, dass der Rückgabetyp wirklich
so ist, ist das wirklich die Lösung.


Paul
--
Ich beantworte Java-Fragen per E-Mail nur gegen Bezahlung. Kostenpunkt
100 Euro pro angefangene Stunde. Bitte erwähne in der Anfrage, dass du
das akzeptierst, da ich sonst die E-Mail einfach ignoriere.
(In der Newsgroup fragen ist billiger und oft auch schneller.)
Stefan Matthias Aust
2004-09-26 18:44:31 UTC
Permalink
Post by Alex Tugarev
Dictionary di = getDocumentProperties();
di.put("abc", "123");
Das Codefragment ist unzureichend. Was ist der Rückgabetyp von
getDocumentProperties()? Bzw: Von welcher Klasse ist das implizite
"this"? "di" muss als Supertyp des besagten Rückgabetyps definiert sein.

Ich rate mal, dass es um ein AbstractDocument geht. Das ist als
"Dictionary<Object, Object>" definiert und daher greift jetzt die ganze
IMHO überflüssige Geschwätzigkeit der generischen Typen.

Ein Dictionary ist leider kein Dictionary<Object, Object> sondern ein
"raw"-Typ, der angewarnt wird, weil er die Generizität nicht mehr enthält.
Post by Alex Tugarev
Was bedeutet die Warnung, und was bedeutet der Hinweis in der Dokumentation
"NOTE: This class is obsolete. New implementations should implement the Map
interface, rather than extending this class."?
Das bedeutet, dass die Swing-Entwickler der Entwicklung von Java
hinterherhängen... :)


bye
--
Stefan Matthias Aust // "Zweifel sind der Ansporn des Denkens..." -U
Alex Tugarev
2004-09-26 21:08:24 UTC
Permalink
Post by Stefan Matthias Aust
Post by Alex Tugarev
Dictionary di = getDocumentProperties();
di.put("abc", "123");
Das Codefragment ist unzureichend. Was ist der Rückgabetyp von
getDocumentProperties()? Bzw: Von welcher Klasse ist das implizite
"this"? "di" muss als Supertyp des besagten Rückgabetyps definiert sein.
public Dictionary<Object,Object> getDocumentProperties() von der Klasse
AbstractDocument. Allerdings hätte ich schon geschrieben, falls es nicht so
eindeutig wäre. Es geht eben nur um die Frage: Generics, oder nicht
generics?
Post by Stefan Matthias Aust
Ich rate mal, dass es um ein AbstractDocument geht. Das ist als
"Dictionary<Object, Object>" definiert und daher greift jetzt die ganze
IMHO überflüssige Geschwätzigkeit der generischen Typen.
Genau, und der Compiler wirft einem eine Warnung aus. Zwar kann man sie
ignorieren, aber den Hinweis in der Dokumentation kann man ohne
(unnötigerweise) tiefer in den Code einzugreifen nicht mitnachvollziehen.
HTMLDokument::getDocumentProperties() liefert nun eben nur noch generics
(ohne Warnungen). Sun's Tipp mit den Maps kann ich hier (leider noch) nicht
befolgen.
Post by Stefan Matthias Aust
Ein Dictionary ist leider kein Dictionary<Object, Object> sondern ein
"raw"-Typ, der angewarnt wird, weil er die Generizität nicht mehr enthält.
Post by Alex Tugarev
Was bedeutet die Warnung, und was bedeutet der Hinweis in der Dokumentation
"NOTE: This class is obsolete. New implementations should implement the Map
interface, rather than extending this class."?
Das bedeutet, dass die Swing-Entwickler der Entwicklung von Java
hinterherhängen... :)
Das ist nichts Neues. Schließlich haben diese auch schon so manchen
Zeitplan einfach vergessen. Oder, wie war das doch noch mal mit HTML 4.x?
Sollte das nicht ein Bestandteil von Java 1.5.0 werden? Damit meine ich
auch Swing. Es geht doch mittlerweile so weit, dass manche
Anwendungsentwickler für bestimmte Projekte grundlegenden Programmcode erst
entwickeln müssen. Dieser hätte meiner Meinung nach bereits von den Java
Entwicklern und von den Swing Entwicklern implementiert werden müssen.
Zugegeben Java ist jung, aber langsam sollte es schon mal Erwachsen werden.
1.5.0 geht da schon in die richtige Richtung, deshalb springe ich lieber
jetzt auf diesen Zug, als später. Hier wird wenigstens noch etwas
Entwickelt. Was man von manch anderen Programmiersprachen nicht mehr
behaupten kann. Nun gut, ich seh es schon, das entwickelt sich hier bei mir
langsam aber sicher wieder zu einem OT.

Ich danke!

Mit freundlichen Grüßen

Alex Tugarev
Christian Wederhake
2004-09-26 16:16:56 UTC
Permalink
Post by Alex Tugarev
Dictionary di = getDocumentProperties();
di.put("abc", "123");
Unsafe type operation: Should not invoke the method put(K, V) of raw type
Dictionary. References to generic type Dictionary<K,V> should be
parameterized
Diese Warnung kannst Du, sofern Du generics nicht benutzen moechtes oder
kannst, getrost ignorieren.
Seit mit 5.0 generics eingefuehrt wurden, wurde auch etliches an vorhandenem
Code generifiziert (ein schickes Wort :-), so auch respektive insbesondere die
Collection-API, oder wie Sun da nennt: JCF, da selbige wohl einer der groessten
Nutzniesser von generics sein duerfte.
Aber: Alter Code soll ja auch weiter ohne Aenderungen lauffaehig sein, und so
wurden eben nicht-generische (raw) Typdeklarationen zu allen ihren generischen
Pendants zuweisungskompatibel gemacht, mit Ausnahme dieser netten kleinen
Warnung eben.
Wenn Du nicht mit der Warnung leben moechtest, deklarier den Typen
statt raw eben generisch, so wie man frueher den Typen gesehen hat:
Dictonary<Object, Object>
Notwendig ist das aber nicht wirklich...
Post by Alex Tugarev
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Dictionary.html
Was bedeutet die Warnung, und was bedeutet der Hinweis in der Dokumentation
"NOTE: This class is obsolete. New implementations should implement the Map
interface, rather than extending this class."?
Dictonary ist hoellisch veraltet und wurde vermutlich nur deswegen nicht
als deprecated markiert, weil deren Unterklasse Hashtable (die wie Vector
ebenfalls hoellisch veraltet ist), noch eine gewisse Existenzberechtigung hat
und ausserdem dieser drei Klassen noch in etlichem an alten Code (auch
von Seiten Suns) zu finden sind, wie, aus mir unerfindlichen Gruenden,
ind Deinem AbstractDocument.
Fuer Key-Value-Mapping steht seit 1.2 das o.g. JCF zu Verfuegung mit Map
und Collection als Grundlage... Das direkte Pendant zu einem Dictonary
ist eine AbstractMap oder, idologisch gesehen, direkt das Map-Interface.
Als Pendant zur Hashtable, als konkreter Implementation, dient, je nach
Thread-safeness-Anforderungen, wahlweise direkt HashMap oder eine
durch Collecitons#sychronizedMap(Map) erhaltene Instanz.

Ciao
Chris
--
"Ich habe eine Menge Geld für Sauferei, leichte Mädchen
und schnelle Autos ausgegeben. Den Rest habe ich einfach
verplempert." (George Best)
Alex Tugarev
2004-09-26 21:13:28 UTC
Permalink
Post by Christian Wederhake
Post by Alex Tugarev
Dictionary di = getDocumentProperties();
di.put("abc", "123");
Unsafe type operation: Should not invoke the method put(K, V) of raw type
Dictionary. References to generic type Dictionary<K,V> should be
parameterized
Diese Warnung kannst Du, sofern Du generics nicht benutzen moechtes oder
kannst, getrost ignorieren.
Seit mit 5.0 generics eingefuehrt wurden, wurde auch etliches an vorhandenem
Code generifiziert (ein schickes Wort :-), so auch respektive insbesondere die
Collection-API, oder wie Sun da nennt: JCF, da selbige wohl einer der groessten
Nutzniesser von generics sein duerfte.
Aber: Alter Code soll ja auch weiter ohne Aenderungen lauffaehig sein, und so
wurden eben nicht-generische (raw) Typdeklarationen zu allen ihren generischen
Pendants zuweisungskompatibel gemacht, mit Ausnahme dieser netten kleinen
Warnung eben.
Wenn Du nicht mit der Warnung leben moechtest, deklarier den Typen
Dictonary<Object, Object>
Notwendig ist das aber nicht wirklich...
Post by Alex Tugarev
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Dictionary.html
Was bedeutet die Warnung, und was bedeutet der Hinweis in der Dokumentation
"NOTE: This class is obsolete. New implementations should implement the Map
interface, rather than extending this class."?
Dictonary ist hoellisch veraltet und wurde vermutlich nur deswegen nicht
als deprecated markiert, weil deren Unterklasse Hashtable (die wie Vector
ebenfalls hoellisch veraltet ist), noch eine gewisse Existenzberechtigung hat
und ausserdem dieser drei Klassen noch in etlichem an alten Code (auch
von Seiten Suns) zu finden sind, wie, aus mir unerfindlichen Gruenden,
ind Deinem AbstractDocument.
Fuer Key-Value-Mapping steht seit 1.2 das o.g. JCF zu Verfuegung mit Map
und Collection als Grundlage... Das direkte Pendant zu einem Dictonary
ist eine AbstractMap oder, idologisch gesehen, direkt das Map-Interface.
Als Pendant zur Hashtable, als konkreter Implementation, dient, je nach
Thread-safeness-Anforderungen, wahlweise direkt HashMap oder eine
durch Collecitons#sychronizedMap(Map) erhaltene Instanz.
Danke für die Infos, ich hole mir noch was zu essen, und dann lese ich es
mir noch mal durch, nicht das ich etwas überlesen habe. So lernt man
wirklich besser.
Und mit dem letzten Teil hast du zwar vollkommen Recht, aber es gibt halt
noch zu viele Konflikte zwischen Theorie und Praxis. Z.B. kann ich Sun's
Tipp mit den Maps hier ja wohl nicht ohne weiteres verwenden, da ich halt
keine Alternative zu Dictionary bekommen kann.
Und *zugebentue* habe jetzt schriftlich Container-Klassen mit Templates
verwechselt. Aber dein Argument ist mir auch einleuchtend. Danke für die
Nachhilfe, lese später noch etwas darüber. Das brennt jetzt.

Mit freundlichen Grüßen

Alex Tugarev

Loading...