Ich bin neu in Java. Beim Codieren einer Map & lt; & gt; fand ich heraus, dass das Deklarieren von Map<int, int>
ein Syntaxfehler ist, während Map<Integer, Integer>
OK ist. Ist es nur in Java möglich, Generics über Objekttypen zu imitieren, im Gegensatz zu Primitiven? Wenn ja, gibt es eine merkliche Leistungseinbuße beim Boxen / Unboxing von Primitiven?
Ja, Sie können Referenztypen nur für generische Typparameter verwenden, und ja, es wird eine gewisse Leistungseinbuße aufgrund von Boxen / Unboxing geben (was größtenteils automatisch gemacht werden kann).
Hier ist ein Zitat aus den FAQ zu Java Generics :
Sind primitive Typen als Typargumente zulässig?
Nein. Nur Referenztypen können als Typargumente verwendet werden. Ein parametrisierter Typ wie
List<int>
oderSet<short>
ist unzulässig. Nur Referenztypen können zur Instanziierung generischer Typen und Methoden verwendet werden. Anstelle vonList<int>
müssen wir eineList<Integer>
deklarieren, indem wir den entsprechenden Wrapper-Typ als Typ-Argument verwenden.[...] Beachten Sie, dass das Fehlen primitiver Instanziierungen zu einer Leistungseinbuße führt. Autoboxing und -Unboxing machen die Verwendung von Wrapper-Typ-Instanziierungen generischer Typen im Quellcode sehr komfortabel und prägnant. Aber die prägnante Schreibweise verbirgt die Tatsache, dass hinter dem Vorhang die virtuelle Maschine viele Wrapper-Objekte erstellt und verwendet, von denen jede zugewiesen und später Müll gesammelt werden muss. Die höhere Leistung der direkten Verwendung von primitiven Typenwerten kann mit generischen Typen nicht erreicht werden. Nur ein regulärer Typ kann die optimale Leistung der Verwendung primitiver Typwerte bieten.
Wenn Sie die Leistung unbedingt benötigen, hat Trove viele Datenstrukturen, die auf primitive Typen spezialisiert sind, aber für die meisten praktischen Zwecke die Verwendung von primitiven Boxen Typen mit Java Collections Framework-Klassen sollten mehr als akzeptable Leistung erbringen.
1) Ja, Java-Generics funktionieren nur bei Objekttypen. Dies liegt daran, wie sie implementiert wurden. Dies geschieht durch Löschvorgang - Im Wesentlichen werden alle generischen Typen nach dem Kompilieren in Bytecode durch Object
ersetzt - dies wurde gemacht, damit Java-Generics funktionieren konnten, ohne den zugrunde liegenden JVM / Bytecode zu modifizieren (schlechte Entscheidung, imo).
2) Ja, es wird einige Box- / Unboxing-Strafe geben; kann nicht vermieden werden, fürchte ich.
Wie andere bemerkt haben, gibt es eine Leistungseinbuße für die Verwendung von Wrapper-Klassen für Primitive. Und obwohl die Kosten nicht wirklich auffallen, wenn Sie wirklich die zusätzliche Leistungssteigerung benötigen, können Sie einfach benutzerdefinierte Unterklassen für die List-Klasse erstellen, eine für jeden primitiven Typ (sie sind nicht viele, also ist das kein Problem) und überschreiben einfach die Methoden Diese setzen und erhalten Werte in der Liste und beschränken sie auf das Akzeptieren jedes Primitivs. Dies wird zu einer Leistungssteigerung führen und die Ausführlichkeit des generischen Listencodes beibehalten.