Von Object zu einem generischen Type casten.
-
Hallo
ich habe ein kleines Problem.Vector<Xxx> myVector = new Vector<Xxx>(); ... { Vector<Xxx> kopie = myVector.clone(); }
wenn ich das so mache, dann gibts ein Fehler, ist ja auch klar.
... { Vector<Xxx> kopie = (Vector<Xxx>)myVector.clone() }
da gibts eine Warnung:
Type safety: The cast from Object to Vector<Xxx> is actually checking against the erased type Vector
und wenn ich das so mache
... { Vector<Xxx> kopie = (Vector)myVector.clone() }
dann gibts die Warnung:
Type safety: The expression of type Vector needs unchecked conversion to conform to Vector<Xxx>
wie kann man also richtig einen generischen Type klonen ?
achja alles mit Eclipse neueste version.
-
DEvent schrieb:
... { Vector<Xxx> kopie = (Vector<Xxx>)myVector.clone() }
da gibts eine Warnung:
Type safety: The cast from Object to Vector<Xxx> is actually checking against the erased type Vector
Diese Warnung ist korrekt und leider unvermeidbar. Das hängt mit der Entscheidung zusammen, die VM nicht zu ändern und Generics über Type Erasure zu implementieren. Vector<T> entspricht daher eigentlich nur Vector<Object> mit compile-time Typsicherheit. Das Ergebnis des Clonens ist also Vector<Object> und der Compiler kann nicht wissen, dass da wirklich nur Xxx drin sind (er weiß ja nicht, was clone() wirklich macht). Deshalb kann er den cast von Vector<Object> nach Vector<Xxx> nicht gutheißen. javac meckert da auch.
Ist leider ne Schwachstelle der Generics von Java.
-
dann will ich mal hoffen das sich dann in version 6.0 ändert
wieso haben die nicht einfach ein Cloneable<T> gemacht mitprotected T clone();
-
Stimmt, das ist ne interessante Frage. Man muss natürlich bedenken, dass Java bis 5.0 keine kovarianten return-Typen erlaubt hat, d.h. dein Rückgabetyp müsste _immer_ Object sein. Seit 5.0 darf man das redefinieren. Ich hab grad ein bischen mit meinem eigenen Cloneable rumgespielt, bin aber schon auf die Grenze gestoßen:.
interface Cloneable<T> { T cloneMe(); } class Container<T> implements Cloneable<Container<T>> { public Container<T> cloneMe() { return new Container<T>(); } } class DerivedContainer<T> extends Container<T> implements Cloneable<DerivedContainer<T>> { public DerivedContainer<T> cloneMe() { return new DerivedContainer<T>(); } }
Naja, jetzt soll DerivedContainer Cloneable<Container<T>> implementieren und Cloneable<DerivedContainer<T>>. Das geht natürlich nicht, du kannst nicht ein Interface zweimal mit unterschiedlichem Typparameter implementieren (sowas würde sich mit Type-Erasure IMHO kaum umsetzen lassen. Zwei Methoden die nach der Ersetzung die Signatur Object cloneMe() haben? Ne.)
Das Problem mit den Generics ist inhärent und so lange man die VM dafür nicht ändert, wird sich das kaum lösen lassen.
-
Ähm das mit den zwei Methoden ist natürlich SCHWACHSINN, weil die eine die andere ja redefiniert. Auf jeden Fall darf man nicht zweimal das selbe Interface mit unterschiedlichem Typparameter implementieren.
-
Optimizer schrieb:
Man muss natürlich bedenken, dass Java bis 5.0 keine kovarianten return-Typen erlaubt hat, d.h. dein Rückgabetyp müsste _immer_ Object sein. Seit 5.0 darf man das redefinieren.
LOL, wenn man bedenkt, dass das wahrscheinlich anfangs mit Absicht nicht drin war. C++ hat das nämlich, die Java-Entwickler hätten es einfach übernehmen können, aber irgendwer hat sich bewußt dagegen entschieden. Generizität, kovariante Returntypen, welche Designentscheidung wird als nächstes revidiert? Überschreiben privater Methoden?
-
Das kann man nicht revidieren, ohne mit vorhandenem Code zu brechen. btw. finde ich sowas auch wirklich völlig unnötig. Für template Method kann man Methoden immer noch protected und package-private machen.
In C# darf man private Methoden auch nicht virtual machen. Ich verstehe das ehrlich gesagt auch. Wenn ne Methode privat ist und ich ruf sie in meiner Klasse auf, kann es mir passieren, dass gar nicht meine Methode aufgerufen wird, weil irgendein Vollhonk von meiner Klasse ableitet und meine private Methode redefiniert. Das ist echt böse, wenn ich ne kleine private Hilfsmethode für mich mach und jemand anders kann sie kicken. Du darfst nicht vergessen, dass man in Java kein virtual keyword verwendet.C# hat seltsamerweise immer noch keine kovarianten return-typen, auch in 2.0 nicht. Ich persönlich verstehs auch nicht.
Aber bei den Generics musst du schon zugeben, dass es eine ziemlich andere Lösung ist als die der Templates.
-
Und du weißt ja: better implies different.