2013-07-12 11 views
5

Nach meinem Verständnis ist der Grund, warum es in Java Java-Rohtypen und -Typen gibt, dass es zu der Zeit, als Generika eingeführt wurden, Standard-APIs gab, die nicht generisch gemacht werden konnten, ohne bestehenden Code zu brechen.Warum ist Java (aber nicht .NET) nicht in der Lage, Generics zu verarbeiten, ohne dass ein unformatierter Typ/Typ erforderlich ist?

Generics wurde auch in .NET zu einem späteren Zeitpunkt eingeführt, aber diese Funktion wurde in einer Weise implementiert, die nicht auf unformatierten Typen oder Typenlöschung beruht (und wenn dies der Fall ist) transparent für den Benutzer). Daher wurden vorhandene APIs (z. B. der Code im Namespace System.Collections) und neue generische APIs (z. B. der Code im Namespace System.Collections.Generic) unverändert beibehalten.

Also, warum Java-Generics, im Gegensatz zu .NET-Generics, erfordert rohe Typen/Typ löschen?

Antwort

8

.Net führte Generika ein, indem die Bytecode-Sprache, die virtuelle Maschine und JITter geändert wurden, um generische Typen zu erkennen.
Dies war eine enorme Menge an Arbeit, die etwa zwei Jahre dauerte.

Java führte Generics als reine Kompilierzeit ein, mit nur geringen Laufzeitänderungen (neue Metadaten und Reflektions-APIs).
Dies war eine viel einfachere Aufgabe, und es hielt die Abwärtskompatibilität mit älteren Laufzeiten aufrecht, aber es ist viel ärgerlicher, damit zu arbeiten.

+3

Darüber hinaus ersetzte .Net die vorhandenen Container durch generische Versionen in einem anderen Namespace. Code, der sie verwenden möchte, muss auf einmal portiert werden. Java's Art erlaubte ihnen, die existierenden Container einfach generisch zu machen, so dass Porting Bit für Bit nur die gelegentliche Cast- und Warnunterdrückung bedeutet. –

+0

@SebastianRedl: Das ist im Grunde eine Erweiterung von Generics, die nur eine Kompilierzeitfunktion ist. – SLaks

+0

Obwohl .NET die Bytecode-Sprache geändert hat, glaube ich nicht, dass Java dies unbedingt hätte tun müssen, damit generische Objekte ihren Typ erkennen können. Ich würde denken, dass es möglich gewesen wäre, dass jede generische Objektinstanz ein oder mehrere Compiler-generierte Felder enthält, die die Kombination von Typen bezeichnen, mit denen die Instanz instanziiert wurde, und dass der Compiler Code generiert, der solche Felder validiert. Ich denke, ein größeres Problem wäre, dass, wenn eine 'ArrayList ' implementiert würde, um irgendein anderer Typ als 'ArrayList' zu sein ... – supercat

3

Sun war besonders daran interessiert, Abwärtskompatibilität zu garantieren, da es sich um eine große etablierte Basis von Java-Software handelte. Um dies zu tun, waren sie der Meinung, dass das Minimum an Änderungen in der JVM am besten war. Im Nachhinein scheint dies auf lange Sicht nicht die beste Entscheidung gewesen zu sein, da es bedeutet, dass die JVM Generika nicht wirklich versteht und viele redundante Klassenprüfungen nicht optimieren kann.

Oracle im Vergleich waren weniger zurückhaltend, die JVM zu ändern, und haben ernsthafte und öffentliche Bugs erlitten vor allem. mit Sicherheit zu tun haben. (Sie meinen nicht das Gleiche, aber eines kann zum anderen führen) Trotzdem hat Oracle der JVM nur eine Anweisung hinzugefügt, die Java nicht einmal verwendet, während Sun keine hinzugefügt hat, so dass es relativ ist. ;)

Microsoft hingegen hatte eine kleinere Codebasis für C# und Kunden gewohnt, signifikante, sogar brechende Änderungen zwischen Hauptversionen. Dies bedeutet kurzfristig mehr Schmerz, kann aber auf lange Sicht eine bessere Wahl sein. Sie haben weniger Probleme, die aus historischen Gründen herumliegen.

Kurz gesagt ist der Unterschied nicht technisch, es ist mehr politisch und historisch.

+1

Der Unterschied ist ** extrem ** technisch. – SLaks